Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 21a68c0

Browse files
committed
Rationalise artist get_figure; make figure attribute a property
1 parent 9387431 commit 21a68c0

File tree

7 files changed

+69
-12
lines changed

7 files changed

+69
-12
lines changed

ci/mypy-stubtest-allowlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,6 @@ matplotlib.tri.*TriInterpolator.gradient
4646
matplotlib.backend_bases.FigureCanvasBase._T
4747
matplotlib.backend_managers.ToolManager._T
4848
matplotlib.spines.Spine._T
49+
50+
# Parameter inconsistency due to 3.10 deprecation
51+
matplotlib.figure.SubFigure.get_figure
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
SubFigure.get_figure
2+
~~~~~~~~~~~~~~~~~~~~
3+
4+
...in future will by default return the direct parent figure, which may be a SubFigure.
5+
This will make the default behavior consistent with the ``get_figure`` method of other
6+
artists. To control the behavior, use the *root* parameter.

lib/matplotlib/artist.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def __init__(self):
181181
self._stale = True
182182
self.stale_callback = None
183183
self._axes = None
184-
self.figure = None
184+
self._figure = None
185185

186186
self._transform = None
187187
self._transformSet = False
@@ -251,7 +251,7 @@ def remove(self):
251251
if self.figure:
252252
if not _ax_flag:
253253
self.figure.stale = True
254-
self.figure = None
254+
self._figure = None
255255

256256
else:
257257
raise NotImplementedError('cannot remove artist')
@@ -720,9 +720,20 @@ def set_path_effects(self, path_effects):
720720
def get_path_effects(self):
721721
return self._path_effects
722722

723-
def get_figure(self):
724-
"""Return the `.Figure` instance the artist belongs to."""
725-
return self.figure
723+
def get_figure(self, root=False):
724+
"""
725+
Return the `.Figure` or `.SubFigure` instance the artist belongs to.
726+
727+
Parameters
728+
----------
729+
root : bool, default=False
730+
If False, return the (Sub)Figure this artist is on. If True,
731+
return the root Figure for a nested tree of SubFigures.
732+
"""
733+
if root:
734+
return self._figure._figure
735+
736+
return self._figure
726737

727738
def set_figure(self, fig):
728739
"""
@@ -740,14 +751,16 @@ def set_figure(self, fig):
740751
# trying to change the figure an artist is associated with which
741752
# is not allowed for the same reason as adding the same instance
742753
# to more than one Axes
743-
if self.figure is not None:
754+
if self._figure is not None:
744755
raise RuntimeError("Can not put single artist in "
745756
"more than one figure")
746-
self.figure = fig
747-
if self.figure and self.figure is not self:
757+
self._figure = fig
758+
if self._figure and self._figure is not self:
748759
self.pchanged()
749760
self.stale = True
750761

762+
figure = property(get_figure, set_figure)
763+
751764
def set_clip_box(self, clipbox):
752765
"""
753766
Set the artist's clip `.Bbox`.

lib/matplotlib/artist.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class Artist:
8787
) -> None: ...
8888
def set_path_effects(self, path_effects: list[AbstractPathEffect]) -> None: ...
8989
def get_path_effects(self) -> list[AbstractPathEffect]: ...
90-
def get_figure(self) -> Figure | None: ...
90+
def get_figure(self, root: bool = ...) -> Figure | SubFigure | None: ...
9191
def set_figure(self, fig: Figure) -> None: ...
9292
def set_clip_box(self, clipbox: BboxBase | None) -> None: ...
9393
def set_clip_path(

lib/matplotlib/axes/_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1295,7 +1295,7 @@ def __clear(self):
12951295
self._gridOn = mpl.rcParams['axes.grid']
12961296
old_children, self._children = self._children, []
12971297
for chld in old_children:
1298-
chld.axes = chld.figure = None
1298+
chld.axes = chld._figure = None
12991299
self._mouseover_set = _OrderedSet()
13001300
self.child_axes = []
13011301
self._current_image = None # strictly for pyplot via _sci, _gci

lib/matplotlib/figure.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2215,7 +2215,7 @@ def __init__(self, parent, subplotspec, *,
22152215

22162216
self._subplotspec = subplotspec
22172217
self._parent = parent
2218-
self.figure = parent.figure
2218+
self._figure = parent._figure
22192219

22202220
# subfigures use the parent axstack
22212221
self._axstack = parent._axstack
@@ -2239,6 +2239,20 @@ def __init__(self, parent, subplotspec, *,
22392239
self._set_artist_props(self.patch)
22402240
self.patch.set_antialiased(False)
22412241

2242+
def get_figure(self, root=None):
2243+
if root is None:
2244+
_api.warn_deprecated(
2245+
'3.10',
2246+
message=('From Matplotlib 3.12 SubFigure.get_figure will by default '
2247+
'return the direct parent figure, which may be a SubFigure. '
2248+
'To suppress this warning, pass the root parameter.'))
2249+
root = True
2250+
2251+
if root:
2252+
return self.figure
2253+
2254+
return self._parent
2255+
22422256
@property
22432257
def dpi(self):
22442258
return self._parent.dpi
@@ -2493,7 +2507,7 @@ def __init__(self,
24932507
%(Figure:kwdoc)s
24942508
"""
24952509
super().__init__(**kwargs)
2496-
self.figure = self
2510+
self._figure = self
24972511
self._layout_engine = None
24982512

24992513
if layout is not None:

lib/matplotlib/tests/test_artist.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,3 +562,24 @@ def draw(self, renderer, extra):
562562

563563
assert 'aardvark' == art.draw(renderer, 'aardvark')
564564
assert 'aardvark' == art.draw(renderer, extra='aardvark')
565+
566+
567+
def test_get_figure():
568+
fig = plt.figure()
569+
sfig1 = fig.subfigures()
570+
sfig2 = sfig1.subfigures()
571+
ax = sfig2.subplots()
572+
573+
assert fig.get_figure() == fig
574+
575+
assert ax.get_figure() == sfig2
576+
assert ax.get_figure(root=False) == sfig2
577+
assert ax.get_figure(root=True) == fig
578+
579+
# SubFigure.get_figure has separate implementation but should give consistent
580+
# results to other artists.
581+
assert sfig2.get_figure(root=False) == sfig1
582+
assert sfig2.get_figure(root=True) == fig
583+
# Currently different results by default.
584+
with pytest.warns(mpl.MatplotlibDeprecationWarning):
585+
assert sfig2.get_figure() == fig

0 commit comments

Comments
 (0)