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 690b213

Browse filesBrowse files
committed
setattr context manager.
1 parent 5e52ce1 commit 690b213
Copy full SHA for 690b213

File tree

Expand file treeCollapse file tree

11 files changed

+149
-204
lines changed
Filter options
Expand file treeCollapse file tree

11 files changed

+149
-204
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
@@ -880,13 +880,8 @@ def _update_property(self, k, v):
880880
raise AttributeError('Unknown property %s' % k)
881881
return func(v)
882882

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

891886
if len(ret):
892887
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
@@ -2113,17 +2113,6 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
21132113
tight bbox is calculated.
21142114
21152115
"""
2116-
self._is_saving = True
2117-
# Remove the figure manager, if any, to avoid resizing the GUI widget.
2118-
# Having *no* manager and a *None* manager are currently different (see
2119-
# Figure.show); should probably be normalized to None at some point.
2120-
_no_manager = object()
2121-
if hasattr(self, 'manager'):
2122-
manager = self.manager
2123-
del self.manager
2124-
else:
2125-
manager = _no_manager
2126-
21272116
if format is None:
21282117
# get format from filename, or from backend's default filetype
21292118
if isinstance(filename, getattr(os, "PathLike", ())):
@@ -2142,104 +2131,107 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
21422131

21432132
if dpi is None:
21442133
dpi = rcParams['savefig.dpi']
2145-
21462134
if dpi == 'figure':
21472135
dpi = getattr(self.figure, '_original_dpi', self.figure.dpi)
21482136

2149-
if facecolor is None:
2150-
facecolor = rcParams['savefig.facecolor']
2151-
if edgecolor is None:
2152-
edgecolor = rcParams['savefig.edgecolor']
2153-
2154-
origDPI = self.figure.dpi
2155-
origfacecolor = self.figure.get_facecolor()
2156-
origedgecolor = self.figure.get_edgecolor()
2157-
2158-
self.figure.dpi = dpi
2159-
self.figure.set_facecolor(facecolor)
2160-
self.figure.set_edgecolor(edgecolor)
2161-
2162-
bbox_inches = kwargs.pop("bbox_inches", None)
2163-
if bbox_inches is None:
2164-
bbox_inches = rcParams['savefig.bbox']
2165-
2166-
if bbox_inches:
2167-
# call adjust_bbox to save only the given area
2168-
if bbox_inches == "tight":
2169-
# When bbox_inches == "tight", it saves the figure twice. The
2170-
# first save command (to a BytesIO) is just to estimate the
2171-
# bounding box of the figure.
2137+
# Remove the figure manager, if any, to avoid resizing the GUI widget.
2138+
# Some code (e.g. Figure.show) differentiates between having *no*
2139+
# manager and a *None* manager, which should be fixed at some point,
2140+
# but this should be fine.
2141+
with cbook._setattr_cm(self, _is_saving=True, manager=None), \
2142+
cbook._setattr_cm(self.figure, dpi=dpi):
2143+
2144+
if facecolor is None:
2145+
facecolor = rcParams['savefig.facecolor']
2146+
if edgecolor is None:
2147+
edgecolor = rcParams['savefig.edgecolor']
2148+
2149+
origfacecolor = self.figure.get_facecolor()
2150+
origedgecolor = self.figure.get_edgecolor()
2151+
2152+
self.figure.dpi = dpi
2153+
self.figure.set_facecolor(facecolor)
2154+
self.figure.set_edgecolor(edgecolor)
2155+
2156+
bbox_inches = kwargs.pop("bbox_inches", None)
2157+
if bbox_inches is None:
2158+
bbox_inches = rcParams['savefig.bbox']
2159+
2160+
if bbox_inches:
2161+
# call adjust_bbox to save only the given area
2162+
if bbox_inches == "tight":
2163+
# When bbox_inches == "tight", it saves the figure twice.
2164+
# The first save command (to a BytesIO) is just to estimate
2165+
# the bounding box of the figure.
2166+
result = print_method(
2167+
io.BytesIO(),
2168+
dpi=dpi,
2169+
facecolor=facecolor,
2170+
edgecolor=edgecolor,
2171+
orientation=orientation,
2172+
dryrun=True,
2173+
**kwargs)
2174+
renderer = self.figure._cachedRenderer
2175+
bbox_inches = self.figure.get_tightbbox(renderer)
2176+
2177+
bbox_artists = kwargs.pop("bbox_extra_artists", None)
2178+
if bbox_artists is None:
2179+
bbox_artists = \
2180+
self.figure.get_default_bbox_extra_artists()
2181+
2182+
bbox_filtered = []
2183+
for a in bbox_artists:
2184+
bbox = a.get_window_extent(renderer)
2185+
if a.get_clip_on():
2186+
clip_box = a.get_clip_box()
2187+
if clip_box is not None:
2188+
bbox = Bbox.intersection(bbox, clip_box)
2189+
clip_path = a.get_clip_path()
2190+
if clip_path is not None and bbox is not None:
2191+
clip_path = \
2192+
clip_path.get_fully_transformed_path()
2193+
bbox = Bbox.intersection(
2194+
bbox, clip_path.get_extents())
2195+
if bbox is not None and (
2196+
bbox.width != 0 or bbox.height != 0):
2197+
bbox_filtered.append(bbox)
2198+
2199+
if bbox_filtered:
2200+
_bbox = Bbox.union(bbox_filtered)
2201+
trans = Affine2D().scale(1.0 / self.figure.dpi)
2202+
bbox_extra = TransformedBbox(_bbox, trans)
2203+
bbox_inches = Bbox.union([bbox_inches, bbox_extra])
2204+
2205+
pad = kwargs.pop("pad_inches", None)
2206+
if pad is None:
2207+
pad = rcParams['savefig.pad_inches']
2208+
2209+
bbox_inches = bbox_inches.padded(pad)
2210+
2211+
restore_bbox = tight_bbox.adjust_bbox(self.figure, bbox_inches,
2212+
canvas.fixed_dpi)
2213+
2214+
_bbox_inches_restore = (bbox_inches, restore_bbox)
2215+
else:
2216+
_bbox_inches_restore = None
2217+
2218+
try:
21722219
result = print_method(
2173-
io.BytesIO(),
2220+
filename,
21742221
dpi=dpi,
21752222
facecolor=facecolor,
21762223
edgecolor=edgecolor,
21772224
orientation=orientation,
2178-
dryrun=True,
2225+
bbox_inches_restore=_bbox_inches_restore,
21792226
**kwargs)
2180-
renderer = self.figure._cachedRenderer
2181-
bbox_inches = self.figure.get_tightbbox(renderer)
2182-
2183-
bbox_artists = kwargs.pop("bbox_extra_artists", None)
2184-
if bbox_artists is None:
2185-
bbox_artists = self.figure.get_default_bbox_extra_artists()
2186-
2187-
bbox_filtered = []
2188-
for a in bbox_artists:
2189-
bbox = a.get_window_extent(renderer)
2190-
if a.get_clip_on():
2191-
clip_box = a.get_clip_box()
2192-
if clip_box is not None:
2193-
bbox = Bbox.intersection(bbox, clip_box)
2194-
clip_path = a.get_clip_path()
2195-
if clip_path is not None and bbox is not None:
2196-
clip_path = clip_path.get_fully_transformed_path()
2197-
bbox = Bbox.intersection(bbox,
2198-
clip_path.get_extents())
2199-
if bbox is not None and (bbox.width != 0 or
2200-
bbox.height != 0):
2201-
bbox_filtered.append(bbox)
2202-
2203-
if bbox_filtered:
2204-
_bbox = Bbox.union(bbox_filtered)
2205-
trans = Affine2D().scale(1.0 / self.figure.dpi)
2206-
bbox_extra = TransformedBbox(_bbox, trans)
2207-
bbox_inches = Bbox.union([bbox_inches, bbox_extra])
2208-
2209-
pad = kwargs.pop("pad_inches", None)
2210-
if pad is None:
2211-
pad = rcParams['savefig.pad_inches']
2212-
2213-
bbox_inches = bbox_inches.padded(pad)
2214-
2215-
restore_bbox = tight_bbox.adjust_bbox(self.figure, bbox_inches,
2216-
canvas.fixed_dpi)
2217-
2218-
_bbox_inches_restore = (bbox_inches, restore_bbox)
2219-
else:
2220-
_bbox_inches_restore = None
2221-
2222-
try:
2223-
result = print_method(
2224-
filename,
2225-
dpi=dpi,
2226-
facecolor=facecolor,
2227-
edgecolor=edgecolor,
2228-
orientation=orientation,
2229-
bbox_inches_restore=_bbox_inches_restore,
2230-
**kwargs)
2231-
finally:
2232-
if bbox_inches and restore_bbox:
2233-
restore_bbox()
2234-
2235-
self.figure.dpi = origDPI
2236-
self.figure.set_facecolor(origfacecolor)
2237-
self.figure.set_edgecolor(origedgecolor)
2238-
self.figure.set_canvas(self)
2239-
if manager is not _no_manager:
2240-
self.manager = manager
2241-
self._is_saving = False
2242-
return result
2227+
finally:
2228+
if bbox_inches and restore_bbox:
2229+
restore_bbox()
2230+
2231+
self.figure.set_facecolor(origfacecolor)
2232+
self.figure.set_edgecolor(origedgecolor)
2233+
self.figure.set_canvas(self)
2234+
return result
22432235

22442236
@classmethod
22452237
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
@@ -486,53 +486,33 @@ def buffer_rgba(self):
486486
def print_raw(self, filename_or_obj, *args, **kwargs):
487487
FigureCanvasAgg.draw(self)
488488
renderer = self.get_renderer()
489-
original_dpi = renderer.dpi
490-
renderer.dpi = self.figure.dpi
491-
if isinstance(filename_or_obj, six.string_types):
492-
fileobj = open(filename_or_obj, 'wb')
493-
close = True
494-
else:
495-
fileobj = filename_or_obj
496-
close = False
497-
try:
498-
fileobj.write(renderer._renderer.buffer_rgba())
499-
finally:
500-
if close:
501-
fileobj.close()
502-
renderer.dpi = original_dpi
489+
with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \
490+
cbook.open_file_cm(filename_or_obj, "wb") as fh:
491+
fh.write(renderer._renderer.buffer_rgba())
503492
print_rgba = print_raw
504493

505494
def print_png(self, filename_or_obj, *args, **kwargs):
506495
FigureCanvasAgg.draw(self)
507496
renderer = self.get_renderer()
508-
original_dpi = renderer.dpi
509-
renderer.dpi = self.figure.dpi
510497

511-
version_str = 'matplotlib version ' + __version__ + \
512-
', http://matplotlib.org/'
498+
version_str = (
499+
'matplotlib version ' + __version__ + ', http://matplotlib.org/')
513500
metadata = OrderedDict({'Software': version_str})
514501
user_metadata = kwargs.pop("metadata", None)
515502
if user_metadata is not None:
516503
metadata.update(user_metadata)
517504

518-
try:
519-
with cbook.open_file_cm(filename_or_obj, "wb") as fh:
520-
_png.write_png(renderer._renderer, fh,
521-
self.figure.dpi, metadata=metadata)
522-
finally:
523-
renderer.dpi = original_dpi
505+
with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \
506+
cbook.open_file_cm(filename_or_obj, "wb") as fh:
507+
_png.write_png(renderer._renderer, fh,
508+
self.figure.dpi, metadata=metadata)
524509

525510
def print_to_buffer(self):
526511
FigureCanvasAgg.draw(self)
527512
renderer = self.get_renderer()
528-
original_dpi = renderer.dpi
529-
renderer.dpi = self.figure.dpi
530-
try:
531-
result = (renderer._renderer.buffer_rgba(),
532-
(int(renderer.width), int(renderer.height)))
533-
finally:
534-
renderer.dpi = original_dpi
535-
return result
513+
with cbook._setattr_cm(renderer, dpi=self.figure.dpi):
514+
return (renderer._renderer.buffer_rgba(),
515+
(int(renderer.width), int(renderer.height)))
536516

537517
if _has_pil:
538518
# 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

@@ -492,11 +489,8 @@ def draw(self):
492489
# that uses the result of the draw() to update plot elements.
493490
if self._is_drawing:
494491
return
495-
self._is_drawing = True
496-
try:
492+
with cbook._setattr_cm(self, _is_drawing=True):
497493
super().draw()
498-
finally:
499-
self._is_drawing = False
500494
self.update()
501495

502496
def draw_idle(self):

‎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
@@ -2070,3 +2070,21 @@ def method(self, *args, **kwargs):
20702070
raise NotImplementedError("Parent class already defines aliases")
20712071
cls._alias_map = alias_d
20722072
return cls
2073+
2074+
2075+
@contextlib.contextmanager
2076+
def _setattr_cm(obj, **kwargs):
2077+
"""Temporarily set some attributes; restore original state at context exit.
2078+
"""
2079+
sentinel = object()
2080+
origs = [(attr, getattr(obj, attr, sentinel)) for attr in kwargs]
2081+
try:
2082+
for attr, val in kwargs.items():
2083+
setattr(obj, attr, val)
2084+
yield
2085+
finally:
2086+
for attr, orig in origs:
2087+
if orig is sentinel:
2088+
delattr(obj, attr)
2089+
else:
2090+
setattr(obj, attr, orig)

‎lib/matplotlib/font_manager.py

Copy file name to clipboardExpand all lines: lib/matplotlib/font_manager.py
+3-10Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,7 @@ def win32InstalledFonts(directory=None, fontext='ttf'):
218218
direc = os.path.abspath(direc).lower()
219219
if os.path.splitext(direc)[1][1:] in fontext:
220220
items.add(direc)
221-
except EnvironmentError:
222-
continue
223-
except WindowsError:
224-
continue
225-
except MemoryError:
221+
except (EnvironmentError, MemoryError, WindowsError):
226222
continue
227223
return list(items)
228224
finally:
@@ -520,17 +516,14 @@ def createFontList(fontfiles, fontext='ttf'):
520516
seen.add(fname)
521517
if fontext == 'afm':
522518
try:
523-
fh = open(fpath, 'rb')
519+
with open(fpath, 'rb') as fh:
520+
font = afm.AFM(fh)
524521
except EnvironmentError:
525522
_log.info("Could not open font file %s", fpath)
526523
continue
527-
try:
528-
font = afm.AFM(fh)
529524
except RuntimeError:
530525
_log.info("Could not parse font file %s", fpath)
531526
continue
532-
finally:
533-
fh.close()
534527
try:
535528
prop = afmFontProperty(fpath, font)
536529
except KeyError:

0 commit comments

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