Skip to content

Commit e2cbe8b

Browse files
authored
Merge pull request matplotlib#29007 from timhoffm/figure-num
MNT: Deprecate changing Figure.number
2 parents 82acbd8 + b81c2c9 commit e2cbe8b

File tree

5 files changed

+64
-1
lines changed

5 files changed

+64
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Changing ``Figure.number``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Changing ``Figure.number`` is deprecated. This value is used by `.pyplot`
5+
to identify figures. It must stay in sync with the pyplot internal state
6+
and is not intended to be modified by the user.

lib/matplotlib/_pylab_helpers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def _set_new_active_manager(cls, manager):
108108
manager._cidgcf = manager.canvas.mpl_connect(
109109
"button_press_event", lambda event: cls.set_active(manager))
110110
fig = manager.canvas.figure
111-
fig.number = manager.num
111+
fig._number = manager.num
112112
label = fig.get_label()
113113
if label:
114114
manager.set_window_title(label)

lib/matplotlib/figure.py

+30
Original file line numberDiff line numberDiff line change
@@ -2808,6 +2808,36 @@ def axes(self):
28082808

28092809
get_axes = axes.fget
28102810

2811+
@property
2812+
def number(self):
2813+
"""The figure id, used to identify figures in `.pyplot`."""
2814+
# Historically, pyplot dynamically added a number attribute to figure.
2815+
# However, this number must stay in sync with the figure manager.
2816+
# AFAICS overwriting the number attribute does not have the desired
2817+
# effect for pyplot. But there are some repos in GitHub that do change
2818+
# number. So let's take it slow and properly migrate away from writing.
2819+
#
2820+
# Making the dynamic attribute private and wrapping it in a property
2821+
# allows to maintain current behavior and deprecate write-access.
2822+
#
2823+
# When the deprecation expires, there's no need for duplicate state
2824+
# anymore and the private _number attribute can be replaced by
2825+
# `self.canvas.manager.num` if that exists and None otherwise.
2826+
if hasattr(self, '_number'):
2827+
return self._number
2828+
else:
2829+
raise AttributeError(
2830+
"'Figure' object has no attribute 'number'. In the future this"
2831+
"will change to returning 'None' instead.")
2832+
2833+
@number.setter
2834+
def number(self, num):
2835+
_api.warn_deprecated(
2836+
"3.10",
2837+
message="Changing 'Figure.number' is deprecated since %(since)s and "
2838+
"will raise an error starting %(removal)s")
2839+
self._number = num
2840+
28112841
def _get_renderer(self):
28122842
if hasattr(self.canvas, 'get_renderer'):
28132843
return self.canvas.get_renderer()

lib/matplotlib/figure.pyi

+4
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ class Figure(FigureBase):
343343
def get_layout_engine(self) -> LayoutEngine | None: ...
344344
def _repr_html_(self) -> str | None: ...
345345
def show(self, warn: bool = ...) -> None: ...
346+
@property
347+
def number(self) -> int | str: ...
348+
@number.setter
349+
def number(self, num: int | str) -> None: ...
346350
@property # type: ignore[misc]
347351
def axes(self) -> list[Axes]: ... # type: ignore[override]
348352
def get_axes(self) -> list[Axes]: ...

lib/matplotlib/tests/test_figure.py

+23
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,29 @@ def test_figure_label():
151151
plt.figure(Figure())
152152

153153

154+
def test_figure_label_replaced():
155+
plt.close('all')
156+
fig = plt.figure(1)
157+
with pytest.warns(mpl.MatplotlibDeprecationWarning,
158+
match="Changing 'Figure.number' is deprecated"):
159+
fig.number = 2
160+
assert fig.number == 2
161+
162+
163+
def test_figure_no_label():
164+
# standalone figures do not have a figure attribute
165+
fig = Figure()
166+
with pytest.raises(AttributeError):
167+
fig.number
168+
# but one can set one
169+
with pytest.warns(mpl.MatplotlibDeprecationWarning,
170+
match="Changing 'Figure.number' is deprecated"):
171+
fig.number = 5
172+
assert fig.number == 5
173+
# even though it's not known by pyplot
174+
assert not plt.fignum_exists(fig.number)
175+
176+
154177
def test_fignum_exists():
155178
# pyplot figure creation, selection and closing with fignum_exists
156179
plt.figure('one')

0 commit comments

Comments
 (0)