|
35 | 35 | implicit and explicit interfaces. |
36 | 36 | """ |
37 | 37 |
|
| 38 | +from contextlib import ExitStack |
38 | 39 | from enum import Enum |
39 | 40 | import functools |
40 | 41 | import importlib |
@@ -438,58 +439,6 @@ def isinteractive(): |
438 | 439 | return matplotlib.is_interactive() |
439 | 440 |
|
440 | 441 |
|
441 | | -class _IoffContext: |
442 | | - """ |
443 | | - Context manager for `.ioff`. |
444 | | -
|
445 | | - The state is changed in ``__init__()`` instead of ``__enter__()``. The |
446 | | - latter is a no-op. This allows using `.ioff` both as a function and |
447 | | - as a context. |
448 | | - """ |
449 | | - |
450 | | - def __init__(self): |
451 | | - self.wasinteractive = isinteractive() |
452 | | - matplotlib.interactive(False) |
453 | | - uninstall_repl_displayhook() |
454 | | - |
455 | | - def __enter__(self): |
456 | | - pass |
457 | | - |
458 | | - def __exit__(self, exc_type, exc_value, traceback): |
459 | | - if self.wasinteractive: |
460 | | - matplotlib.interactive(True) |
461 | | - install_repl_displayhook() |
462 | | - else: |
463 | | - matplotlib.interactive(False) |
464 | | - uninstall_repl_displayhook() |
465 | | - |
466 | | - |
467 | | -class _IonContext: |
468 | | - """ |
469 | | - Context manager for `.ion`. |
470 | | -
|
471 | | - The state is changed in ``__init__()`` instead of ``__enter__()``. The |
472 | | - latter is a no-op. This allows using `.ion` both as a function and |
473 | | - as a context. |
474 | | - """ |
475 | | - |
476 | | - def __init__(self): |
477 | | - self.wasinteractive = isinteractive() |
478 | | - matplotlib.interactive(True) |
479 | | - install_repl_displayhook() |
480 | | - |
481 | | - def __enter__(self): |
482 | | - pass |
483 | | - |
484 | | - def __exit__(self, exc_type, exc_value, traceback): |
485 | | - if not self.wasinteractive: |
486 | | - matplotlib.interactive(False) |
487 | | - uninstall_repl_displayhook() |
488 | | - else: |
489 | | - matplotlib.interactive(True) |
490 | | - install_repl_displayhook() |
491 | | - |
492 | | - |
493 | 442 | def ioff(): |
494 | 443 | """ |
495 | 444 | Disable interactive mode. |
@@ -519,11 +468,15 @@ def ioff(): |
519 | 468 | fig2 = plt.figure() |
520 | 469 | # ... |
521 | 470 |
|
522 | | - To enable usage as a context manager, this function returns an |
523 | | - ``_IoffContext`` object. The return value is not intended to be stored |
524 | | - or accessed by the user. |
| 471 | + To enable optional usage as a context manager, this function returns a |
| 472 | + `~contextlib.ExitStack` object, which is not intended to be stored or |
| 473 | + accessed by the user. |
525 | 474 | """ |
526 | | - return _IoffContext() |
| 475 | + stack = ExitStack() |
| 476 | + stack.callback(ion if isinteractive() else ioff) |
| 477 | + matplotlib.interactive(False) |
| 478 | + uninstall_repl_displayhook() |
| 479 | + return stack |
527 | 480 |
|
528 | 481 |
|
529 | 482 | def ion(): |
@@ -555,11 +508,15 @@ def ion(): |
555 | 508 | fig2 = plt.figure() |
556 | 509 | # ... |
557 | 510 |
|
558 | | - To enable usage as a context manager, this function returns an |
559 | | - ``_IonContext`` object. The return value is not intended to be stored |
560 | | - or accessed by the user. |
| 511 | + To enable optional usage as a context manager, this function returns a |
| 512 | + `~contextlib.ExitStack` object, which is not intended to be stored or |
| 513 | + accessed by the user. |
561 | 514 | """ |
562 | | - return _IonContext() |
| 515 | + stack = ExitStack() |
| 516 | + stack.callback(ion if isinteractive() else ioff) |
| 517 | + matplotlib.interactive(True) |
| 518 | + install_repl_displayhook() |
| 519 | + return stack |
563 | 520 |
|
564 | 521 |
|
565 | 522 | def pause(interval): |
@@ -658,46 +615,38 @@ def xkcd(scale=1, length=100, randomness=2): |
658 | 615 | # This figure will be in regular style |
659 | 616 | fig2 = plt.figure() |
660 | 617 | """ |
661 | | - return _xkcd(scale, length, randomness) |
662 | | - |
663 | | - |
664 | | -class _xkcd: |
665 | | - # This cannot be implemented in terms of rc_context() because this needs to |
666 | | - # work as a non-contextmanager too. |
667 | | - |
668 | | - def __init__(self, scale, length, randomness): |
669 | | - self._orig = rcParams.copy() |
670 | | - |
671 | | - if rcParams['text.usetex']: |
672 | | - raise RuntimeError( |
673 | | - "xkcd mode is not compatible with text.usetex = True") |
674 | | - |
675 | | - from matplotlib import patheffects |
676 | | - rcParams.update({ |
677 | | - 'font.family': ['xkcd', 'xkcd Script', 'Humor Sans', 'Comic Neue', |
678 | | - 'Comic Sans MS'], |
679 | | - 'font.size': 14.0, |
680 | | - 'path.sketch': (scale, length, randomness), |
681 | | - 'path.effects': [ |
682 | | - patheffects.withStroke(linewidth=4, foreground="w")], |
683 | | - 'axes.linewidth': 1.5, |
684 | | - 'lines.linewidth': 2.0, |
685 | | - 'figure.facecolor': 'white', |
686 | | - 'grid.linewidth': 0.0, |
687 | | - 'axes.grid': False, |
688 | | - 'axes.unicode_minus': False, |
689 | | - 'axes.edgecolor': 'black', |
690 | | - 'xtick.major.size': 8, |
691 | | - 'xtick.major.width': 3, |
692 | | - 'ytick.major.size': 8, |
693 | | - 'ytick.major.width': 3, |
694 | | - }) |
695 | | - |
696 | | - def __enter__(self): |
697 | | - return self |
698 | | - |
699 | | - def __exit__(self, *args): |
700 | | - dict.update(rcParams, self._orig) |
| 618 | + # This cannot be implemented in terms of contextmanager() or rc_context() |
| 619 | + # because this needs to work as a non-contextmanager too. |
| 620 | + |
| 621 | + if rcParams['text.usetex']: |
| 622 | + raise RuntimeError( |
| 623 | + "xkcd mode is not compatible with text.usetex = True") |
| 624 | + |
| 625 | + stack = ExitStack() |
| 626 | + stack.callback(dict.update, rcParams, rcParams.copy()) |
| 627 | + |
| 628 | + from matplotlib import patheffects |
| 629 | + rcParams.update({ |
| 630 | + 'font.family': ['xkcd', 'xkcd Script', 'Humor Sans', 'Comic Neue', |
| 631 | + 'Comic Sans MS'], |
| 632 | + 'font.size': 14.0, |
| 633 | + 'path.sketch': (scale, length, randomness), |
| 634 | + 'path.effects': [ |
| 635 | + patheffects.withStroke(linewidth=4, foreground="w")], |
| 636 | + 'axes.linewidth': 1.5, |
| 637 | + 'lines.linewidth': 2.0, |
| 638 | + 'figure.facecolor': 'white', |
| 639 | + 'grid.linewidth': 0.0, |
| 640 | + 'axes.grid': False, |
| 641 | + 'axes.unicode_minus': False, |
| 642 | + 'axes.edgecolor': 'black', |
| 643 | + 'xtick.major.size': 8, |
| 644 | + 'xtick.major.width': 3, |
| 645 | + 'ytick.major.size': 8, |
| 646 | + 'ytick.major.width': 3, |
| 647 | + }) |
| 648 | + |
| 649 | + return stack |
701 | 650 |
|
702 | 651 |
|
703 | 652 | ## Figures ## |
|
0 commit comments