Skip to content

Commit c137a71

Browse files
committed
API : property-ify Artist.axes
- deprecate Artist.{get,set}_axes - add axes property - Raise exception when trying to move artists between axes.
1 parent 69decec commit c137a71

File tree

6 files changed

+73
-14
lines changed

6 files changed

+73
-14
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Prevent moving artists between Axes, Property-ify Artist.axes, deprecate Artist.{get,set}_axes
2+
``````````````````````````````````````````````````````````````````````````````````````````````
3+
4+
The reason this was done was to prevent adding an Artist that is
5+
already associated with an Axes to be moved/added to a different Axes.
6+
This was never supported as it causes havoc with the transform stack.
7+
The apparent support for this (as it did not raise an exception) was
8+
the source of multiple bug reports and questions on SO.
9+
10+
For almost all use-cases, the assignment of the axes to an artist should be
11+
taken care of by the axes as part of the ``Axes.add_*`` method, hence the
12+
deprecation {get,set}_axes.
13+
14+
Removing the ``set_axes`` method will also remove the 'axes' line from
15+
the ACCEPTS kwarg tables (assuming that the removal date gets here
16+
before that gets overhauled).

lib/matplotlib/artist.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import inspect
99
import matplotlib
1010
import matplotlib.cbook as cbook
11+
from matplotlib.cbook import mplDeprecation
1112
from matplotlib import docstring, rcParams
1213
from .transforms import (Bbox, IdentityTransform, TransformedBbox,
1314
TransformedPath, Transform)
@@ -77,6 +78,7 @@ class Artist(object):
7778
zorder = 0
7879

7980
def __init__(self):
81+
self._axes = None
8082
self.figure = None
8183

8284
self._transform = None
@@ -175,17 +177,43 @@ def set_axes(self, axes):
175177
Set the :class:`~matplotlib.axes.Axes` instance in which the
176178
artist resides, if any.
177179
180+
This has been deprecated in mpl 1.5, please use the
181+
axes property. Will be removed in 1.7 or 2.0.
182+
178183
ACCEPTS: an :class:`~matplotlib.axes.Axes` instance
179184
"""
185+
warnings.warn(_get_axes_msg, mplDeprecation, stacklevel=1)
180186
self.axes = axes
181187

182188
def get_axes(self):
183189
"""
184190
Return the :class:`~matplotlib.axes.Axes` instance the artist
185-
resides in, or *None*
191+
resides in, or *None*.
192+
193+
This has been deprecated in mpl 1.5, please use the
194+
axes property. Will be removed in 1.7 or 2.0.
186195
"""
196+
warnings.warn(_get_axes_msg, mplDeprecation, stacklevel=1)
187197
return self.axes
188198

199+
@property
200+
def axes(self):
201+
"""
202+
The :class:`~matplotlib.axes.Axes` instance the artist
203+
resides in, or *None*.
204+
"""
205+
return self._axes
206+
207+
@axes.setter
208+
def axes(self, new_axes):
209+
if self._axes is not None and new_axes != self._axes:
210+
raise ValueError("Can not reset the axes. You are "
211+
"probably trying to re-use an artist "
212+
"in more than one Axes which is not "
213+
"supported")
214+
self._axes = new_axes
215+
return new_axes
216+
189217
def get_window_extent(self, renderer):
190218
"""
191219
Get the axes bounding box in display space.
@@ -751,10 +779,13 @@ def update(self, props):
751779
changed = False
752780

753781
for k, v in six.iteritems(props):
754-
func = getattr(self, 'set_' + k, None)
755-
if func is None or not six.callable(func):
756-
raise AttributeError('Unknown property %s' % k)
757-
func(v)
782+
if k in ['axes']:
783+
setattr(self, k, v)
784+
else:
785+
func = getattr(self, 'set_' + k, None)
786+
if func is None or not six.callable(func):
787+
raise AttributeError('Unknown property %s' % k)
788+
func(v)
758789
changed = True
759790
self.eventson = store
760791
if changed:
@@ -1328,3 +1359,6 @@ def kwdoc(a):
13281359
return '\n'.join(ArtistInspector(a).pprint_setters(leadingspace=2))
13291360

13301361
docstring.interpd.update(Artist=kwdoc(Artist))
1362+
1363+
_get_axes_msg = """This has been deprecated in mpl 1.5, please use the
1364+
axes property. A removal date has not been set."""

lib/matplotlib/axes/_base.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,8 @@ def __init__(self, fig, rect,
392392
else:
393393
self._position = mtransforms.Bbox.from_bounds(*rect)
394394
self._originalPosition = self._position.frozen()
395-
self.set_axes(self)
395+
# self.set_axes(self)
396+
self.axes = self
396397
self.set_aspect('auto')
397398
self._adjustable = 'box'
398399
self.set_anchor('C')
@@ -774,7 +775,7 @@ def _set_artist_props(self, a):
774775
if not a.is_transform_set():
775776
a.set_transform(self.transData)
776777

777-
a.set_axes(self)
778+
a.axes = self
778779

779780
def _gen_axes_patch(self):
780781
"""
@@ -1431,7 +1432,7 @@ def add_artist(self, a):
14311432
14321433
Returns the artist.
14331434
"""
1434-
a.set_axes(self)
1435+
a.axes = self
14351436
self.artists.append(a)
14361437
self._set_artist_props(a)
14371438
a.set_clip_path(self.patch)

lib/matplotlib/figure.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,11 @@ def __init__(self,
298298
Defaults to rc ``figure.autolayout``.
299299
"""
300300
Artist.__init__(self)
301-
301+
# remove the non-figure artist _axes property
302+
# as it makes no sense for a figure to be _in_ an axes
303+
# this is used by the property methods in the artist base class
304+
# which are over-ridden in this class
305+
del self._axes
302306
self.callbacks = cbook.CallbackRegistry()
303307

304308
if figsize is None:

lib/matplotlib/legend.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ def __init__(self, parent, handles, labels,
304304

305305
if isinstance(parent, Axes):
306306
self.isaxes = True
307-
self.set_axes(parent)
307+
self.axes = parent
308308
self.set_figure(parent.figure)
309309
elif isinstance(parent, Figure):
310310
self.isaxes = False
@@ -391,7 +391,9 @@ def _set_artist_props(self, a):
391391
"""
392392
a.set_figure(self.figure)
393393
if self.isaxes:
394-
a.set_axes(self.axes)
394+
# a.set_axes(self.axes)
395+
a.axes = self.axes
396+
395397
a.set_transform(self.get_transform())
396398

397399
def _set_loc(self, loc):

lib/matplotlib/lines.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,15 +536,17 @@ def get_window_extent(self, renderer):
536536
bbox = bbox.padded(ms)
537537
return bbox
538538

539-
def set_axes(self, ax):
540-
Artist.set_axes(self, ax)
539+
@Artist.axes.setter
540+
def axes(self, ax):
541+
# call the set method from the base-class property
542+
Artist.axes.fset(self, ax)
543+
# connect unit-related callbacks
541544
if ax.xaxis is not None:
542545
self._xcid = ax.xaxis.callbacks.connect('units',
543546
self.recache_always)
544547
if ax.yaxis is not None:
545548
self._ycid = ax.yaxis.callbacks.connect('units',
546549
self.recache_always)
547-
set_axes.__doc__ = Artist.set_axes.__doc__
548550

549551
def set_data(self, *args):
550552
"""

0 commit comments

Comments
 (0)