Skip to content

Commit c080824

Browse files
authored
Merge pull request matplotlib#16828 from QuLogic/setattr_cm
Use more _setattr_cm, thus fix Text('').get_window_extent(dpi=...)
2 parents e7fcb37 + af74526 commit c080824

File tree

5 files changed

+43
-36
lines changed

5 files changed

+43
-36
lines changed

lib/matplotlib/legend_handler.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def legend_artist(self, legend, orig_handle, fontsize, handlebox)
2828

2929
import numpy as np
3030

31+
from matplotlib import cbook
3132
from matplotlib.lines import Line2D
3233
from matplotlib.patches import Rectangle
3334
import matplotlib.collections as mcoll
@@ -607,19 +608,15 @@ def create_artists(self, legend, orig_handle,
607608
if using_linecoll:
608609
# change the function used by update_prop() from the default
609610
# to one that handles LineCollection
610-
orig_update_func = self._update_prop_func
611-
self._update_prop_func = self._copy_collection_props
612-
613-
for line in leg_stemlines:
614-
self.update_prop(line, stemlines, legend)
611+
with cbook._setattr_cm(
612+
self, _update_prop_func=self._copy_collection_props):
613+
for line in leg_stemlines:
614+
self.update_prop(line, stemlines, legend)
615615

616616
else:
617617
for lm, m in zip(leg_stemlines, stemlines):
618618
self.update_prop(lm, m, legend)
619619

620-
if using_linecoll:
621-
self._update_prop_func = orig_update_func
622-
623620
leg_baseline = Line2D([np.min(xdata), np.max(xdata)],
624621
[bottom, bottom])
625622
self.update_prop(leg_baseline, baseline, legend)

lib/matplotlib/quiver.py

+9-12
Original file line numberDiff line numberDiff line change
@@ -306,18 +306,15 @@ def _init(self):
306306
if not self.Q._initialized:
307307
self.Q._init()
308308
self._set_transform()
309-
_pivot = self.Q.pivot
310-
self.Q.pivot = self.pivot[self.labelpos]
311-
# Hack: save and restore the Umask
312-
_mask = self.Q.Umask
313-
self.Q.Umask = ma.nomask
314-
u = self.U * np.cos(np.radians(self.angle))
315-
v = self.U * np.sin(np.radians(self.angle))
316-
angle = self.Q.angles if isinstance(self.Q.angles, str) else 'uv'
317-
self.verts = self.Q._make_verts(
318-
np.array([u]), np.array([v]), angle)
319-
self.Q.Umask = _mask
320-
self.Q.pivot = _pivot
309+
with cbook._setattr_cm(self.Q, pivot=self.pivot[self.labelpos],
310+
# Hack: save and restore the Umask
311+
Umask=ma.nomask):
312+
u = self.U * np.cos(np.radians(self.angle))
313+
v = self.U * np.sin(np.radians(self.angle))
314+
angle = (self.Q.angles if isinstance(self.Q.angles, str)
315+
else 'uv')
316+
self.verts = self.Q._make_verts(
317+
np.array([u]), np.array([v]), angle)
321318
kw = self.Q.polykw
322319
kw.update(self.kw)
323320
self.vector = mcollections.PolyCollection(

lib/matplotlib/tests/test_text.py

+16
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,22 @@ def test_set_position():
321321
assert a + shift_val == b
322322

323323

324+
@pytest.mark.parametrize('text', ['', 'O'], ids=['empty', 'non-empty'])
325+
def test_non_default_dpi(text):
326+
fig, ax = plt.subplots()
327+
328+
t1 = ax.text(0.5, 0.5, text, ha='left', va='bottom')
329+
fig.canvas.draw()
330+
dpi = fig.dpi
331+
332+
bbox1 = t1.get_window_extent()
333+
bbox2 = t1.get_window_extent(dpi=dpi * 10)
334+
np.testing.assert_allclose(bbox2.get_points(), bbox1.get_points() * 10,
335+
rtol=5e-2)
336+
# Text.get_window_extent should not permanently change dpi.
337+
assert fig.dpi == dpi
338+
339+
324340
def test_get_rotation_string():
325341
assert mpl.text.get_rotation('horizontal') == 0.
326342
assert mpl.text.get_rotation('vertical') == 90.

lib/matplotlib/text.py

+11-12
Original file line numberDiff line numberDiff line change
@@ -891,12 +891,12 @@ def get_window_extent(self, renderer=None, dpi=None):
891891
#return _unit_box
892892
if not self.get_visible():
893893
return Bbox.unit()
894-
if dpi is not None:
895-
dpi_orig = self.figure.dpi
896-
self.figure.dpi = dpi
894+
if dpi is None:
895+
dpi = self.figure.dpi
897896
if self.get_text() == '':
898-
tx, ty = self._get_xy_display()
899-
return Bbox.from_bounds(tx, ty, 0, 0)
897+
with cbook._setattr_cm(self.figure, dpi=dpi):
898+
tx, ty = self._get_xy_display()
899+
return Bbox.from_bounds(tx, ty, 0, 0)
900900

901901
if renderer is not None:
902902
self._renderer = renderer
@@ -905,13 +905,12 @@ def get_window_extent(self, renderer=None, dpi=None):
905905
if self._renderer is None:
906906
raise RuntimeError('Cannot get window extent w/o renderer')
907907

908-
bbox, info, descent = self._get_layout(self._renderer)
909-
x, y = self.get_unitless_position()
910-
x, y = self.get_transform().transform((x, y))
911-
bbox = bbox.translated(x, y)
912-
if dpi is not None:
913-
self.figure.dpi = dpi_orig
914-
return bbox
908+
with cbook._setattr_cm(self.figure, dpi=dpi):
909+
bbox, info, descent = self._get_layout(self._renderer)
910+
x, y = self.get_unitless_position()
911+
x, y = self.get_transform().transform((x, y))
912+
bbox = bbox.translated(x, y)
913+
return bbox
915914

916915
def set_backgroundcolor(self, color):
917916
"""

lib/matplotlib/widgets.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -1151,10 +1151,8 @@ def __init__(self, targetfig, toolfig):
11511151

11521152
# During reset there can be a temporary invalid state depending on the
11531153
# order of the reset so we turn off validation for the resetting
1154-
validate = toolfig.subplotpars.validate
1155-
toolfig.subplotpars.validate = False
1156-
self.buttonreset.on_clicked(self._on_reset)
1157-
toolfig.subplotpars.validate = validate
1154+
with cbook._setattr_cm(toolfig.subplotpars, validate=False):
1155+
self.buttonreset.on_clicked(self._on_reset)
11581156

11591157
def _on_slider_changed(self, _):
11601158
self.targetfig.subplots_adjust(

0 commit comments

Comments
 (0)