Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3fa657a

Browse filesBrowse files
committed
setattr context manager.
1 parent 7673002 commit 3fa657a
Copy full SHA for 3fa657a

File tree

Expand file treeCollapse file tree

12 files changed

+152
-213
lines changed
Filter options
Expand file treeCollapse file tree

12 files changed

+152
-213
lines changed

‎lib/matplotlib/artist.py

Copy file name to clipboardExpand all lines: lib/matplotlib/artist.py
+2-7Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -881,13 +881,8 @@ def _update_property(self, k, v):
881881
raise AttributeError('Unknown property %s' % k)
882882
return func(v)
883883

884-
store = self.eventson
885-
self.eventson = False
886-
try:
887-
ret = [_update_property(self, k, v)
888-
for k, v in props.items()]
889-
finally:
890-
self.eventson = store
884+
with cbook._setattr_cm(self, eventson=False):
885+
ret = [_update_property(self, k, v) for k, v in props.items()]
891886

892887
if len(ret):
893888
self.pchanged()

‎lib/matplotlib/backend_bases.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backend_bases.py
+92-100Lines changed: 92 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,17 +2146,6 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
21462146
tight bbox is calculated.
21472147
21482148
"""
2149-
self._is_saving = True
2150-
# Remove the figure manager, if any, to avoid resizing the GUI widget.
2151-
# Having *no* manager and a *None* manager are currently different (see
2152-
# Figure.show); should probably be normalized to None at some point.
2153-
_no_manager = object()
2154-
if hasattr(self, 'manager'):
2155-
manager = self.manager
2156-
del self.manager
2157-
else:
2158-
manager = _no_manager
2159-
21602149
if format is None:
21612150
# get format from filename, or from backend's default filetype
21622151
if isinstance(filename, six.string_types):
@@ -2173,104 +2162,107 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
21732162

21742163
if dpi is None:
21752164
dpi = rcParams['savefig.dpi']
2176-
21772165
if dpi == 'figure':
21782166
dpi = getattr(self.figure, '_original_dpi', self.figure.dpi)
21792167

2180-
if facecolor is None:
2181-
facecolor = rcParams['savefig.facecolor']
2182-
if edgecolor is None:
2183-
edgecolor = rcParams['savefig.edgecolor']
2184-
2185-
origDPI = self.figure.dpi
2186-
origfacecolor = self.figure.get_facecolor()
2187-
origedgecolor = self.figure.get_edgecolor()
2188-
2189-
self.figure.dpi = dpi
2190-
self.figure.set_facecolor(facecolor)
2191-
self.figure.set_edgecolor(edgecolor)
2192-
2193-
bbox_inches = kwargs.pop("bbox_inches", None)
2194-
if bbox_inches is None:
2195-
bbox_inches = rcParams['savefig.bbox']
2196-
2197-
if bbox_inches:
2198-
# call adjust_bbox to save only the given area
2199-
if bbox_inches == "tight":
2200-
# When bbox_inches == "tight", it saves the figure twice. The
2201-
# first save command (to a BytesIO) is just to estimate the
2202-
# bounding box of the figure.
2168+
# Remove the figure manager, if any, to avoid resizing the GUI widget.
2169+
# Some code (e.g. Figure.show) differentiates between having *no*
2170+
# manager and a *None* manager, which should be fixed at some point,
2171+
# but this should be fine.
2172+
with cbook._setattr_cm(self, _is_saving=True, manager=None), \
2173+
cbook._setattr_cm(self.figure, dpi=dpi):
2174+
2175+
if facecolor is None:
2176+
facecolor = rcParams['savefig.facecolor']
2177+
if edgecolor is None:
2178+
edgecolor = rcParams['savefig.edgecolor']
2179+
2180+
origfacecolor = self.figure.get_facecolor()
2181+
origedgecolor = self.figure.get_edgecolor()
2182+
2183+
self.figure.dpi = dpi
2184+
self.figure.set_facecolor(facecolor)
2185+
self.figure.set_edgecolor(edgecolor)
2186+
2187+
bbox_inches = kwargs.pop("bbox_inches", None)
2188+
if bbox_inches is None:
2189+
bbox_inches = rcParams['savefig.bbox']
2190+
2191+
if bbox_inches:
2192+
# call adjust_bbox to save only the given area
2193+
if bbox_inches == "tight":
2194+
# When bbox_inches == "tight", it saves the figure twice.
2195+
# The first save command (to a BytesIO) is just to estimate
2196+
# the bounding box of the figure.
2197+
result = print_method(
2198+
io.BytesIO(),
2199+
dpi=dpi,
2200+
facecolor=facecolor,
2201+
edgecolor=edgecolor,
2202+
orientation=orientation,
2203+
dryrun=True,
2204+
**kwargs)
2205+
renderer = self.figure._cachedRenderer
2206+
bbox_inches = self.figure.get_tightbbox(renderer)
2207+
2208+
bbox_artists = kwargs.pop("bbox_extra_artists", None)
2209+
if bbox_artists is None:
2210+
bbox_artists = \
2211+
self.figure.get_default_bbox_extra_artists()
2212+
2213+
bbox_filtered = []
2214+
for a in bbox_artists:
2215+
bbox = a.get_window_extent(renderer)
2216+
if a.get_clip_on():
2217+
clip_box = a.get_clip_box()
2218+
if clip_box is not None:
2219+
bbox = Bbox.intersection(bbox, clip_box)
2220+
clip_path = a.get_clip_path()
2221+
if clip_path is not None and bbox is not None:
2222+
clip_path = \
2223+
clip_path.get_fully_transformed_path()
2224+
bbox = Bbox.intersection(
2225+
bbox, clip_path.get_extents())
2226+
if bbox is not None and (
2227+
bbox.width != 0 or bbox.height != 0):
2228+
bbox_filtered.append(bbox)
2229+
2230+
if bbox_filtered:
2231+
_bbox = Bbox.union(bbox_filtered)
2232+
trans = Affine2D().scale(1.0 / self.figure.dpi)
2233+
bbox_extra = TransformedBbox(_bbox, trans)
2234+
bbox_inches = Bbox.union([bbox_inches, bbox_extra])
2235+
2236+
pad = kwargs.pop("pad_inches", None)
2237+
if pad is None:
2238+
pad = rcParams['savefig.pad_inches']
2239+
2240+
bbox_inches = bbox_inches.padded(pad)
2241+
2242+
restore_bbox = tight_bbox.adjust_bbox(self.figure, bbox_inches,
2243+
canvas.fixed_dpi)
2244+
2245+
_bbox_inches_restore = (bbox_inches, restore_bbox)
2246+
else:
2247+
_bbox_inches_restore = None
2248+
2249+
try:
22032250
result = print_method(
2204-
io.BytesIO(),
2251+
filename,
22052252
dpi=dpi,
22062253
facecolor=facecolor,
22072254
edgecolor=edgecolor,
22082255
orientation=orientation,
2209-
dryrun=True,
2256+
bbox_inches_restore=_bbox_inches_restore,
22102257
**kwargs)
2211-
renderer = self.figure._cachedRenderer
2212-
bbox_inches = self.figure.get_tightbbox(renderer)
2213-
2214-
bbox_artists = kwargs.pop("bbox_extra_artists", None)
2215-
if bbox_artists is None:
2216-
bbox_artists = self.figure.get_default_bbox_extra_artists()
2217-
2218-
bbox_filtered = []
2219-
for a in bbox_artists:
2220-
bbox = a.get_window_extent(renderer)
2221-
if a.get_clip_on():
2222-
clip_box = a.get_clip_box()
2223-
if clip_box is not None:
2224-
bbox = Bbox.intersection(bbox, clip_box)
2225-
clip_path = a.get_clip_path()
2226-
if clip_path is not None and bbox is not None:
2227-
clip_path = clip_path.get_fully_transformed_path()
2228-
bbox = Bbox.intersection(bbox,
2229-
clip_path.get_extents())
2230-
if bbox is not None and (bbox.width != 0 or
2231-
bbox.height != 0):
2232-
bbox_filtered.append(bbox)
2233-
2234-
if bbox_filtered:
2235-
_bbox = Bbox.union(bbox_filtered)
2236-
trans = Affine2D().scale(1.0 / self.figure.dpi)
2237-
bbox_extra = TransformedBbox(_bbox, trans)
2238-
bbox_inches = Bbox.union([bbox_inches, bbox_extra])
2239-
2240-
pad = kwargs.pop("pad_inches", None)
2241-
if pad is None:
2242-
pad = rcParams['savefig.pad_inches']
2243-
2244-
bbox_inches = bbox_inches.padded(pad)
2245-
2246-
restore_bbox = tight_bbox.adjust_bbox(self.figure, bbox_inches,
2247-
canvas.fixed_dpi)
2248-
2249-
_bbox_inches_restore = (bbox_inches, restore_bbox)
2250-
else:
2251-
_bbox_inches_restore = None
2252-
2253-
try:
2254-
result = print_method(
2255-
filename,
2256-
dpi=dpi,
2257-
facecolor=facecolor,
2258-
edgecolor=edgecolor,
2259-
orientation=orientation,
2260-
bbox_inches_restore=_bbox_inches_restore,
2261-
**kwargs)
2262-
finally:
2263-
if bbox_inches and restore_bbox:
2264-
restore_bbox()
2265-
2266-
self.figure.dpi = origDPI
2267-
self.figure.set_facecolor(origfacecolor)
2268-
self.figure.set_edgecolor(origedgecolor)
2269-
self.figure.set_canvas(self)
2270-
if manager is not _no_manager:
2271-
self.manager = manager
2272-
self._is_saving = False
2273-
return result
2258+
finally:
2259+
if bbox_inches and restore_bbox:
2260+
restore_bbox()
2261+
2262+
self.figure.set_facecolor(origfacecolor)
2263+
self.figure.set_edgecolor(origedgecolor)
2264+
self.figure.set_canvas(self)
2265+
return result
22742266

22752267
@classmethod
22762268
def get_default_filetype(cls):

‎lib/matplotlib/backends/backend_agg.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_agg.py
+12-32Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -491,53 +491,33 @@ def buffer_rgba(self):
491491
def print_raw(self, filename_or_obj, *args, **kwargs):
492492
FigureCanvasAgg.draw(self)
493493
renderer = self.get_renderer()
494-
original_dpi = renderer.dpi
495-
renderer.dpi = self.figure.dpi
496-
if isinstance(filename_or_obj, six.string_types):
497-
fileobj = open(filename_or_obj, 'wb')
498-
close = True
499-
else:
500-
fileobj = filename_or_obj
501-
close = False
502-
try:
503-
fileobj.write(renderer._renderer.buffer_rgba())
504-
finally:
505-
if close:
506-
fileobj.close()
507-
renderer.dpi = original_dpi
494+
with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \
495+
cbook.open_file_cm(filename_or_obj, "wb") as fh:
496+
fh.write(renderer._renderer.buffer_rgba())
508497
print_rgba = print_raw
509498

510499
def print_png(self, filename_or_obj, *args, **kwargs):
511500
FigureCanvasAgg.draw(self)
512501
renderer = self.get_renderer()
513-
original_dpi = renderer.dpi
514-
renderer.dpi = self.figure.dpi
515502

516-
version_str = 'matplotlib version ' + __version__ + \
517-
', http://matplotlib.org/'
503+
version_str = (
504+
'matplotlib version ' + __version__ + ', http://matplotlib.org/')
518505
metadata = OrderedDict({'Software': version_str})
519506
user_metadata = kwargs.pop("metadata", None)
520507
if user_metadata is not None:
521508
metadata.update(user_metadata)
522509

523-
try:
524-
with cbook.open_file_cm(filename_or_obj, "wb") as fh:
525-
_png.write_png(renderer._renderer, fh,
526-
self.figure.dpi, metadata=metadata)
527-
finally:
528-
renderer.dpi = original_dpi
510+
with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \
511+
cbook.open_file_cm(filename_or_obj, "wb") as fh:
512+
_png.write_png(renderer._renderer, fh,
513+
self.figure.dpi, metadata=metadata)
529514

530515
def print_to_buffer(self):
531516
FigureCanvasAgg.draw(self)
532517
renderer = self.get_renderer()
533-
original_dpi = renderer.dpi
534-
renderer.dpi = self.figure.dpi
535-
try:
536-
result = (renderer._renderer.buffer_rgba(),
537-
(int(renderer.width), int(renderer.height)))
538-
finally:
539-
renderer.dpi = original_dpi
540-
return result
518+
with cbook._setattr_cm(renderer, dpi=self.figure.dpi):
519+
return (renderer._renderer.buffer_rgba(),
520+
(int(renderer.width), int(renderer.height)))
541521

542522
if _has_pil:
543523
# add JPEG support

‎lib/matplotlib/backends/backend_qt5.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_qt5.py
+4-10Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import matplotlib
1414

15+
from matplotlib import backend_tools, cbook
1516
from matplotlib._pylab_helpers import Gcf
1617
from matplotlib.backend_bases import (
1718
_Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2,
@@ -20,7 +21,6 @@
2021
from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool
2122
from matplotlib.figure import Figure
2223
from matplotlib.backend_managers import ToolManager
23-
from matplotlib import backend_tools
2424

2525
from .qt_compat import (
2626
QtCore, QtGui, QtWidgets, _getSaveFileName, is_pyqt5, __version__, QT_API)
@@ -169,12 +169,9 @@ def cooperative_qwidget_init(self, *args, **kwargs):
169169

170170
@functools.wraps(__init__)
171171
def wrapper(self, **kwargs):
172-
try:
173-
QtWidgets.QWidget.__init__ = cooperative_qwidget_init
172+
with cbook._setattr_cm(QtWidgets.QWidget,
173+
__init__=cooperative_qwidget_init):
174174
__init__(self, **kwargs)
175-
finally:
176-
# Restore __init__
177-
QtWidgets.QWidget.__init__ = qwidget_init
178175

179176
return wrapper
180177

@@ -490,11 +487,8 @@ def draw(self):
490487
# that uses the result of the draw() to update plot elements.
491488
if self._is_drawing:
492489
return
493-
self._is_drawing = True
494-
try:
490+
with cbook._setattr_cm(self, _is_drawing=True):
495491
super(FigureCanvasQT, self).draw()
496-
finally:
497-
self._is_drawing = False
498492
self.update()
499493

500494
def draw_idle(self):

‎lib/matplotlib/backends/backend_webagg_core.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_webagg_core.py
+2-5Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,11 @@ def show(self):
151151

152152
def draw(self):
153153
renderer = self.get_renderer(cleared=True)
154-
155154
self._png_is_old = True
156-
157-
backend_agg.RendererAgg.lock.acquire()
158155
try:
159-
self.figure.draw(renderer)
156+
with backend_agg.RendererAgg.lock:
157+
self.figure.draw(renderer)
160158
finally:
161-
backend_agg.RendererAgg.lock.release()
162159
# Swap the frames
163160
self.manager.refresh_all()
164161

‎lib/matplotlib/cbook/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/cbook/__init__.py
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,3 +2830,21 @@ def _str_lower_equal(obj, s):
28302830
cannot be used in a boolean context.
28312831
"""
28322832
return isinstance(obj, six.string_types) and obj.lower() == s
2833+
2834+
2835+
@contextlib.contextmanager
2836+
def _setattr_cm(obj, **kwargs):
2837+
"""Temporarily set some attributes; restore original state at context exit.
2838+
"""
2839+
sentinel = object()
2840+
origs = [(attr, getattr(obj, attr, sentinel)) for attr in kwargs]
2841+
try:
2842+
for attr, val in kwargs.items():
2843+
setattr(obj, attr, val)
2844+
yield
2845+
finally:
2846+
for attr, orig in origs:
2847+
if orig is sentinel:
2848+
delattr(obj, attr)
2849+
else:
2850+
setattr(obj, attr, orig)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.