Skip to content

Commit 9bf86b2

Browse files
committed
Add Artist._cm_set for temporarily setting an Artist property.
This corresponds to _setattr_cm, but for Artist properties. (Calling it `_set_cm` sounded too much like setting a "cm" property. Perhaps `_setattr_cm` should have been `_cm_setattr`...)
1 parent 319f24f commit 9bf86b2

File tree

5 files changed

+37
-44
lines changed

5 files changed

+37
-44
lines changed

lib/matplotlib/artist.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from collections import namedtuple
2+
import contextlib
23
from functools import wraps
34
import inspect
45
import logging
@@ -1154,6 +1155,18 @@ def set(self, **kwargs):
11541155
kwargs = cbook.normalize_kwargs(kwargs, self)
11551156
return self.update(kwargs)
11561157

1158+
@contextlib.contextmanager
1159+
def _cm_set(self, **kwargs):
1160+
"""
1161+
`.Artist.set` context-manager that restores original values at exit.
1162+
"""
1163+
orig_vals = {k: getattr(self, f"get_{k}")() for k in kwargs}
1164+
try:
1165+
self.set(**kwargs)
1166+
yield
1167+
finally:
1168+
self.set(**orig_vals)
1169+
11571170
def findobj(self, match=None, include_self=True):
11581171
"""
11591172
Find artist objects.

lib/matplotlib/axes/_base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3122,8 +3122,7 @@ def redraw_in_frame(self):
31223122
with ExitStack() as stack:
31233123
for artist in [*self._get_axis_list(),
31243124
self.title, self._left_title, self._right_title]:
3125-
stack.callback(artist.set_visible, artist.get_visible())
3126-
artist.set_visible(False)
3125+
stack.enter_context(artist._cm_set(visible=False))
31273126
self.draw(self.figure._cachedRenderer)
31283127

31293128
def get_renderer_cache(self):

lib/matplotlib/backend_bases.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"""
2727

2828
from collections import namedtuple
29-
from contextlib import contextmanager, nullcontext
29+
from contextlib import ExitStack, contextmanager, nullcontext
3030
from enum import Enum, IntEnum
3131
import functools
3232
import importlib
@@ -2256,22 +2256,16 @@ def print_figure(
22562256

22572257
# Remove the figure manager, if any, to avoid resizing the GUI widget.
22582258
with cbook._setattr_cm(self, manager=None), \
2259-
cbook._setattr_cm(self.figure, dpi=dpi), \
2260-
cbook._setattr_cm(canvas, _is_saving=True):
2261-
origfacecolor = self.figure.get_facecolor()
2262-
origedgecolor = self.figure.get_edgecolor()
2263-
2264-
if facecolor is None:
2265-
facecolor = rcParams['savefig.facecolor']
2266-
if cbook._str_equal(facecolor, 'auto'):
2267-
facecolor = origfacecolor
2268-
if edgecolor is None:
2269-
edgecolor = rcParams['savefig.edgecolor']
2270-
if cbook._str_equal(edgecolor, 'auto'):
2271-
edgecolor = origedgecolor
2272-
2273-
self.figure.set_facecolor(facecolor)
2274-
self.figure.set_edgecolor(edgecolor)
2259+
cbook._setattr_cm(self.figure, dpi=dpi), \
2260+
cbook._setattr_cm(canvas, _is_saving=True), \
2261+
ExitStack() as stack:
2262+
2263+
for prop in ["facecolor", "edgecolor"]:
2264+
color = locals()[prop]
2265+
if color is None:
2266+
color = rcParams[f"savefig.{prop}"]
2267+
if not cbook._str_equal(color, "auto"):
2268+
stack.enter_context(self.figure._cm_set(**{prop: color}))
22752269

22762270
if bbox_inches is None:
22772271
bbox_inches = rcParams['savefig.bbox']
@@ -2306,8 +2300,7 @@ def print_figure(
23062300
_bbox_inches_restore = None
23072301

23082302
# we have already done CL above, so turn it off:
2309-
cl_state = self.figure.get_constrained_layout()
2310-
self.figure.set_constrained_layout(False)
2303+
stack.enter_context(self.figure._cm_set(constrained_layout=False))
23112304
try:
23122305
# _get_renderer may change the figure dpi (as vector formats
23132306
# force the figure dpi to 72), so we need to set it again here.
@@ -2323,11 +2316,7 @@ def print_figure(
23232316
if bbox_inches and restore_bbox:
23242317
restore_bbox()
23252318

2326-
self.figure.set_facecolor(origfacecolor)
2327-
self.figure.set_edgecolor(origedgecolor)
23282319
self.figure.set_canvas(self)
2329-
# reset to cached state
2330-
self.figure.set_constrained_layout(cl_state)
23312320
return result
23322321

23332322
@classmethod

lib/matplotlib/figure.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Control the default spacing between subplots.
1515
"""
1616

17+
from contextlib import ExitStack
1718
import inspect
1819
import logging
1920
from numbers import Integral
@@ -2922,23 +2923,15 @@ def savefig(self, fname, *, transparent=None, **kwargs):
29222923
if transparent is None:
29232924
transparent = mpl.rcParams['savefig.transparent']
29242925

2925-
if transparent:
2926-
kwargs.setdefault('facecolor', 'none')
2927-
kwargs.setdefault('edgecolor', 'none')
2928-
original_axes_colors = []
2929-
for ax in self.axes:
2930-
patch = ax.patch
2931-
original_axes_colors.append((patch.get_facecolor(),
2932-
patch.get_edgecolor()))
2933-
patch.set_facecolor('none')
2934-
patch.set_edgecolor('none')
2935-
2936-
self.canvas.print_figure(fname, **kwargs)
2937-
2938-
if transparent:
2939-
for ax, cc in zip(self.axes, original_axes_colors):
2940-
ax.patch.set_facecolor(cc[0])
2941-
ax.patch.set_edgecolor(cc[1])
2926+
with ExitStack() as stack:
2927+
if transparent:
2928+
kwargs.setdefault('facecolor', 'none')
2929+
kwargs.setdefault('edgecolor', 'none')
2930+
for ax in self.axes:
2931+
stack.enter_context(
2932+
ax.patch._cm_set(facecolor='none', edgecolor='none'))
2933+
2934+
self.canvas.print_figure(fname, **kwargs)
29422935

29432936
def ginput(self, n=1, timeout=30, show_clicks=True,
29442937
mouse_add=MouseButton.LEFT,

lib/matplotlib/widgets.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,8 +1735,7 @@ def update_background(self, event):
17351735
with ExitStack() as stack:
17361736
if needs_redraw:
17371737
for artist in self.artists:
1738-
stack.callback(artist.set_visible, artist.get_visible())
1739-
artist.set_visible(False)
1738+
stack.enter_context(artist._cm_set(visible=False))
17401739
self.canvas.draw()
17411740
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
17421741
if needs_redraw:

0 commit comments

Comments
 (0)