Skip to content

Commit a02949e

Browse files
committed
Fix xkcd() not resetting context anymore.
1 parent 0aaf239 commit a02949e

File tree

4 files changed

+51
-28
lines changed

4 files changed

+51
-28
lines changed

lib/matplotlib/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,16 +1222,17 @@ def rc_context(rc=None, fname=None):
12221222
12231223
"""
12241224

1225-
orig = rcParams.copy()
1225+
_rcParams = rcParams # Prevent it from being set to None at shutdown.
1226+
orig = _rcParams.copy()
12261227
try:
12271228
if fname:
12281229
rc_file(fname)
12291230
if rc:
1230-
rcParams.update(rc)
1231+
_rcParams.update(rc)
12311232
yield
12321233
finally:
12331234
# No need to revalidate the original values.
1234-
dict.update(rcParams, orig)
1235+
dict.update(_rcParams, orig)
12351236

12361237

12371238
_use_error_msg = """

lib/matplotlib/pyplot.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,13 @@
2121
import six
2222

2323
import sys
24-
import warnings
2524
import time
2625
import types
26+
import warnings
27+
try:
28+
from contextlib import ExitStack
29+
except ImportError:
30+
from contextlib2 import ExitStack # Py2
2731

2832
from cycler import cycler
2933
import matplotlib
@@ -389,28 +393,30 @@ def xkcd(scale=1, length=100, randomness=2):
389393
"xkcd mode is not compatible with text.usetex = True")
390394

391395
from matplotlib import patheffects
392-
context = rc_context()
393-
try:
394-
rcParams['font.family'] = ['xkcd', 'Humor Sans', 'Comic Sans MS']
395-
rcParams['font.size'] = 14.0
396-
rcParams['path.sketch'] = (scale, length, randomness)
397-
rcParams['path.effects'] = [
398-
patheffects.withStroke(linewidth=4, foreground="w")]
399-
rcParams['axes.linewidth'] = 1.5
400-
rcParams['lines.linewidth'] = 2.0
401-
rcParams['figure.facecolor'] = 'white'
402-
rcParams['grid.linewidth'] = 0.0
403-
rcParams['axes.grid'] = False
404-
rcParams['axes.unicode_minus'] = False
405-
rcParams['axes.edgecolor'] = 'black'
406-
rcParams['xtick.major.size'] = 8
407-
rcParams['xtick.major.width'] = 3
408-
rcParams['ytick.major.size'] = 8
409-
rcParams['ytick.major.width'] = 3
410-
except:
411-
context.__exit__(*sys.exc_info())
412-
raise
413-
return context
396+
# In order to make the call to `xkcd` that does not use a context manager
397+
# (cm) work, we need to enter into the cm ourselves, and return a dummy cm
398+
# (implemented with ExitStack) that does nothing on entry and cleans up the
399+
# xkcd context on exit. Additionally, we need to keep a reference to the
400+
# dummy cm because it would otherwise be exited when GC'd.
401+
xkcd._stack = stack = ExitStack()
402+
stack.enter_context(rc_context({
403+
'font.family': ['xkcd', 'Humor Sans', 'Comic Sans MS'],
404+
'font.size': 14.0,
405+
'path.sketch': (scale, length, randomness),
406+
'path.effects': [patheffects.withStroke(linewidth=4, foreground="w")],
407+
'axes.linewidth': 1.5,
408+
'lines.linewidth': 2.0,
409+
'figure.facecolor': 'white',
410+
'grid.linewidth': 0.0,
411+
'axes.grid': False,
412+
'axes.unicode_minus': False,
413+
'axes.edgecolor': 'black',
414+
'xtick.major.size': 8,
415+
'xtick.major.width': 3,
416+
'ytick.major.size': 8,
417+
'ytick.major.width': 3,
418+
}))
419+
return stack
414420

415421

416422
## Figures ##

lib/matplotlib/tests/test_style.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import pytest
1212

1313
import matplotlib as mpl
14-
from matplotlib import style
14+
from matplotlib import pyplot as plt, style
1515
from matplotlib.style.core import USER_LIBRARY_PATHS, STYLE_EXTENSION
1616

1717
import six
@@ -158,3 +158,16 @@ def test_alias(equiv_styles):
158158
rc_base = rc_dicts[0]
159159
for nm, rc in zip(equiv_styles[1:], rc_dicts[1:]):
160160
assert rc_base == rc
161+
162+
163+
def test_xkcd_no_cm():
164+
assert mpl.rcParams["path.sketch"] is None
165+
plt.xkcd()
166+
assert mpl.rcParams["path.sketch"] == (1, 100, 2)
167+
168+
169+
def test_xkcd_cm():
170+
assert mpl.rcParams["path.sketch"] is None
171+
with plt.xkcd():
172+
assert mpl.rcParams["path.sketch"] == (1, 100, 2)
173+
assert mpl.rcParams["path.sketch"] is None

setupext.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1465,7 +1465,10 @@ def get_install_requires(self):
14651465
"six>=1.10",
14661466
]
14671467
if sys.version_info < (3,):
1468-
install_requires += ["backports.functools_lru_cache"]
1468+
install_requires += [
1469+
"backports.functools_lru_cache",
1470+
"contextlib2>=0.5.0",
1471+
]
14691472
if sys.version_info < (3,) and os.name == "posix":
14701473
install_requires += ["subprocess32"]
14711474
return install_requires

0 commit comments

Comments
 (0)