@@ -1246,8 +1246,7 @@ def rc_file(fname):
12461246 rcParams .update (rc_params_from_file (fname ))
12471247
12481248
1249- @contextlib .contextmanager
1250- def rc_context (rc = None , fname = None ):
1249+ class rc_context :
12511250 """
12521251 Return a context manager for managing rc settings.
12531252
@@ -1277,19 +1276,33 @@ def rc_context(rc=None, fname=None):
12771276 ax.plot(range(3), range(3))
12781277 fig.savefig('A.png', format='png')
12791278 plt.close(fig)
1280-
12811279 """
1280+ # While it may seem natural to implement rc_context using
1281+ # contextlib.contextmanager, that would entail always calling the finally:
1282+ # clause of the contextmanager (which restores the original rcs) including
1283+ # during garbage collection; as a result, something like `plt.xkcd();
1284+ # gc.collect()` would result in the style being lost (as `xkcd()` is
1285+ # implemented on top of rc_context, and nothing is holding onto context
1286+ # manager except possibly circular references.
1287+
1288+ def __init__ (self , rc = None , fname = None ):
1289+ self ._orig = rcParams .copy ()
1290+ try :
1291+ if fname :
1292+ rc_file (fname )
1293+ if rc :
1294+ rcParams .update (rc )
1295+ except Exception :
1296+ # If anything goes wrong, revert to the original rcs.
1297+ dict .update (rcParams , self ._orig )
1298+ raise
12821299
1283- orig = rcParams .copy ()
1284- try :
1285- if fname :
1286- rc_file (fname )
1287- if rc :
1288- rcParams .update (rc )
1289- yield
1290- finally :
1300+ def __enter__ (self ):
1301+ return self
1302+
1303+ def __exit__ (self , exc_type , exc_value , exc_tb ):
12911304 # No need to revalidate the original values.
1292- dict .update (rcParams , orig )
1305+ dict .update (rcParams , self . _orig )
12931306
12941307
12951308_use_error_msg = """
0 commit comments