diff --git a/doc/api/next_api_changes/deprecations/21425-AL.rst b/doc/api/next_api_changes/deprecations/21425-AL.rst new file mode 100644 index 000000000000..d6652bfbac57 --- /dev/null +++ b/doc/api/next_api_changes/deprecations/21425-AL.rst @@ -0,0 +1,15 @@ +3D Axis +~~~~~~~ +The previous constructor of `.axis3d.Axis`, with signature +``(self, adir, v_intervalx, d_intervalx, axes, *args, rotate_label=None, **kwargs)`` +is deprecated in favor of a new signature closer to the one of 2D Axis; it +is now ``(self, axes, *, rotate_label=None, **kwargs)`` where ``kwargs`` are +forwarded to the 2D Axis constructor. The axis direction is now inferred from +the axis class' ``axis_name`` attribute (as in the 2D case); the ``adir`` +attribute is deprecated. + +The ``init3d`` method of 3D Axis is also deprecated; all the relevant +initialization is done as part of the constructor. + +The ``d_interval`` and ``v_interval`` attributes of 3D Axis are deprecated; use +``get_data_interval`` and ``get_view_interval`` instead. diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 3e93c85fa888..9968bd0f5760 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -194,14 +194,9 @@ def set_top_view(self): def _init_axis(self): """Init 3D axes; overrides creation of regular X/Y axes.""" - self.xaxis = axis3d.XAxis('x', self.xy_viewLim.intervalx, - self.xy_dataLim.intervalx, self) - self.yaxis = axis3d.YAxis('y', self.xy_viewLim.intervaly, - self.xy_dataLim.intervaly, self) - self.zaxis = axis3d.ZAxis('z', self.zz_viewLim.intervalx, - self.zz_dataLim.intervalx, self) - for ax in self.xaxis, self.yaxis, self.zaxis: - ax.init3d() + self.xaxis = axis3d.XAxis(self) + self.yaxis = axis3d.YAxis(self) + self.zaxis = axis3d.ZAxis(self) def get_zaxis(self): """Return the ``ZAxis`` (`~.axis3d.Axis`) instance.""" diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 7d6110c25a47..08450c52fdcd 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -2,11 +2,13 @@ # Created: 23 Sep 2005 # Parts rewritten by Reinier Heeres +import inspect + import numpy as np -import matplotlib.transforms as mtransforms from matplotlib import ( - artist, lines as mlines, axis as maxis, patches as mpatches, rcParams) + _api, artist, lines as mlines, axis as maxis, patches as mpatches, + transforms as mtransforms, rcParams) from . import art3d, proj3d @@ -51,14 +53,34 @@ class Axis(maxis.XAxis): 'color': (0.925, 0.925, 0.925, 0.5)}, } - def __init__(self, adir, v_intervalx, d_intervalx, axes, *args, - rotate_label=None, **kwargs): - # adir identifies which axes this is - self.adir = adir + def _old_init(self, adir, v_intervalx, d_intervalx, axes, *args, + rotate_label=None, **kwargs): + return locals() + + def _new_init(self, axes, *, rotate_label=None, **kwargs): + return locals() + + def __init__(self, *args, **kwargs): + params = _api.select_matching_signature( + [self._old_init, self._new_init], *args, **kwargs) + if "adir" in params: + _api.warn_deprecated( + "3.6", message=f"The signature of 3D Axis constructors has " + f"changed in %(since)s; the new signature is " + f"{inspect.signature(type(self).__init__)}", pending=True) + if params["adir"] != self.axis_name: + raise ValueError(f"Cannot instantiate {type(self).__name__} " + f"with adir={params['adir']!r}") + axes = params["axes"] + rotate_label = params["rotate_label"] + args = params.get("args", ()) + kwargs = params["kwargs"] + + name = self.axis_name # This is a temporary member variable. # Do not depend on this existing in future releases! - self._axinfo = self._AXINFO[adir].copy() + self._axinfo = self._AXINFO[name].copy() if rcParams['_internal.classic_mode']: self._axinfo.update({ 'label': {'va': 'center', 'ha': 'center'}, @@ -85,10 +107,10 @@ def __init__(self, adir, v_intervalx, d_intervalx, axes, *args, 'outward_factor': 0.1, 'linewidth': { True: ( # major - rcParams['xtick.major.width'] if adir in 'xz' else + rcParams['xtick.major.width'] if name in 'xz' else rcParams['ytick.major.width']), False: ( # minor - rcParams['xtick.minor.width'] if adir in 'xz' else + rcParams['xtick.minor.width'] if name in 'xz' else rcParams['ytick.minor.width']), } }, @@ -106,11 +128,18 @@ def __init__(self, adir, v_intervalx, d_intervalx, axes, *args, super().__init__(axes, *args, **kwargs) # data and viewing intervals for this direction - self.d_interval = d_intervalx - self.v_interval = v_intervalx + if "d_intervalx" in params: + self.set_data_interval(*params["d_intervalx"]) + if "v_intervalx" in params: + self.set_view_interval(*params["v_intervalx"]) self.set_rotate_label(rotate_label) + self._init3d() # Inline after init3d deprecation elapses. + + __init__.__signature__ = inspect.signature(_new_init) + adir = _api.deprecated("3.6", pending=True)( + property(lambda self: self.axis_name)) - def init3d(self): + def _init3d(self): self.line = mlines.Line2D( xdata=(0, 0), ydata=(0, 0), linewidth=self._axinfo['axisline']['linewidth'], @@ -133,6 +162,10 @@ def init3d(self): self.label._transform = self.axes.transData self.offsetText._transform = self.axes.transData + @_api.deprecated("3.6", pending=True) + def init3d(self): # After deprecation elapses, inline _init3d to __init__. + self._init3d() + def get_major_ticks(self, numticks=None): ticks = super().get_major_ticks(numticks) for t in ticks: @@ -496,27 +529,18 @@ def get_tightbbox(self, renderer, *, for_layout_only=False): return mtransforms.Bbox.union([*bb_1, *bb_2, *other]) - @property - def d_interval(self): - return self.get_data_interval() - - @d_interval.setter - def d_interval(self, minmax): - self.set_data_interval(*minmax) - - @property - def v_interval(self): - return self.get_view_interval() - - @v_interval.setter - def v_interval(self, minmax): - self.set_view_interval(*minmax) - - -# Use classes to look at different data limits + d_interval = _api.deprecated( + "3.6", alternative="get_data_interval", pending=True)( + property(lambda self: self.get_data_interval(), + lambda self, minmax: self.set_data_interval(*minmax))) + v_interval = _api.deprecated( + "3.6", alternative="get_view_interval", pending=True)( + property(lambda self: self.get_view_interval(), + lambda self, minmax: self.set_view_interval(*minmax))) class XAxis(Axis): + axis_name = "x" get_view_interval, set_view_interval = maxis._make_getset_interval( "view", "xy_viewLim", "intervalx") get_data_interval, set_data_interval = maxis._make_getset_interval( @@ -524,6 +548,7 @@ class XAxis(Axis): class YAxis(Axis): + axis_name = "y" get_view_interval, set_view_interval = maxis._make_getset_interval( "view", "xy_viewLim", "intervaly") get_data_interval, set_data_interval = maxis._make_getset_interval( @@ -531,6 +556,7 @@ class YAxis(Axis): class ZAxis(Axis): + axis_name = "z" get_view_interval, set_view_interval = maxis._make_getset_interval( "view", "zz_viewLim", "intervalx") get_data_interval, set_data_interval = maxis._make_getset_interval(