| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7c377c5 commit 85159ce
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -693,6 +693,12 @@ class RcParams(MutableMapping, dict): | |||
| 693 | 693 | ||
| 694 | 694 | validate = rcsetup._validators | |
| 695 | 695 | ||
| 696 | + # Class-level backend state: shared across all RcParams instances because | ||
| 697 | + # there can only be one active backend at a time. None of the three | ||
| 698 | + # RcParams instances (rcParams, rcParamsDefault, rcParamsOrig) stores | ||
| 699 | + # "backend" as a dict key; reads/writes are all redirected here. | ||
| 700 | + _backend = rcsetup._auto_backend_sentinel | ||
| 701 | + | ||
| 696 | 702 | # validate values on the way in | |
| 697 | 703 | def __init__(self, *args, **kwargs): | |
| 698 | 704 | self.update(*args, **kwargs) | |
@@ -715,6 +721,9 @@ def _set(self, key, val): | |||
| 715 | 721 | ||
| 716 | 722 | :meta public: | |
| 717 | 723 | """ | |
| 724 | + if key == "backend": | ||
| 725 | + RcParams._backend = val | ||
| 726 | + return | ||
| 718 | 727 | dict.__setitem__(self, key, val) | |
| 719 | 728 | ||
| 720 | 729 | def _get(self, key): | |
@@ -736,6 +745,8 @@ def _get(self, key): | |||
| 736 | 745 | ||
| 737 | 746 | :meta public: | |
| 738 | 747 | """ | |
| 748 | + if key == "backend": | ||
| 749 | + return RcParams._backend | ||
| 739 | 750 | return dict.__getitem__(self, key) | |
| 740 | 751 | ||
| 741 | 752 | def _update_raw(self, other_params): | |
@@ -752,25 +763,27 @@ def _update_raw(self, other_params): | |||
| 752 | 763 | The input mapping from which to update. | |
| 753 | 764 | """ | |
| 754 | 765 | if isinstance(other_params, RcParams): | |
| 766 | + # RcParams never stores "backend" in its dict; skip it here too. | ||
| 755 | 767 | other_params = dict.items(other_params) | |
| 768 | + else: | ||
| 769 | + if "backend" in other_params: | ||
| 770 | + raise ValueError( | ||
| 771 | + "'backend' should not be passed anymore in internal calls " | ||
| 772 | + "to _update_raw" | ||
| 773 | + ) | ||
| 756 | 774 | dict.update(self, other_params) | |
| 757 | 775 | ||
| 758 | - def _ensure_has_backend(self): | ||
| 759 | - """ | ||
| 760 | - Ensure that a "backend" entry exists. | ||
| 761 | - | ||
| 762 | - Normally, the default matplotlibrc file contains *no* entry for "backend" (the | ||
| 763 | - corresponding line starts with ##, not #; we fill in _auto_backend_sentinel | ||
| 764 | - in that case. However, packagers can set a different default backend | ||
| 765 | - (resulting in a normal `#backend: foo` line) in which case we should *not* | ||
| 766 | - fill in _auto_backend_sentinel. | ||
| 767 | - """ | ||
| 768 | - dict.setdefault(self, "backend", rcsetup._auto_backend_sentinel) | ||
| 769 | - | ||
| 770 | 776 | def __setitem__(self, key, val): | |
| 771 | - if (key == "backend" | ||
| 772 | - and val is rcsetup._auto_backend_sentinel | ||
| 773 | - and "backend" in self): | ||
| 777 | + if (key == "backend" and val is rcsetup._auto_backend_sentinel): | ||
| 778 | + # Don't let caller silently overwrite a real backend with the auto-sentinel | ||
| 779 | + # (only internal code via _set() may do that). | ||
| 780 | + # | ||
| 781 | + # The primary reason for existence was covering internal rcParams logic | ||
| 782 | + # since end-users do not have direct access to | ||
| 783 | + # rcsetup._auto_backend_sentinel. It is likely that this is not needed | ||
| 784 | + # anymore due to removind "backend" from the dict and making it | ||
| 785 | + # a class attribute RcParams._backend`. But to be on the safe side, we | ||
| 786 | + # keep this as long as "backend" is a valid key for rcParams. | ||
| 774 | 787 | return | |
| 775 | 788 | valid_key = _api.getitem_checked( | |
| 776 | 789 | self.validate, rcParam=key, _error_cls=KeyError | |
@@ -784,18 +797,19 @@ def __setitem__(self, key, val): | |||
| 784 | 797 | self._set(key, cval) | |
| 785 | 798 | ||
| 786 | 799 | def __getitem__(self, key): | |
| 787 | - # In theory, this should only ever be used after the global rcParams | ||
| 788 | - # has been set up, but better be safe e.g. in presence of breakpoints. | ||
| 789 | - if key == "backend" and self is globals().get("rcParams"): | ||
| 790 | - val = self._get(key) | ||
| 791 | - if val is rcsetup._auto_backend_sentinel: | ||
| 800 | + if key == "backend": | ||
| 801 | + # In theory, this should only ever be used after the global rcParams | ||
| 802 | + # has been set up, but better be safe e.g. in presence of breakpoints. | ||
| 803 | + if (self is globals().get("rcParams") | ||
| 804 | + and RcParams._backend is rcsetup._auto_backend_sentinel): | ||
| 792 | 805 | from matplotlib import pyplot as plt | |
| 793 | 806 | plt.switch_backend(rcsetup._auto_backend_sentinel) | |
| 794 | - return self._get(key) | ||
| 807 | + return RcParams._backend | ||
| 808 | + return dict.__getitem__(self, key) | ||
| 795 | 809 | ||
| 796 | 810 | def _get_backend_or_none(self): | |
| 797 | 811 | """Get the requested backend, if any, without triggering resolution.""" | |
| 798 | - backend = self._get("backend") | ||
| 812 | + backend = RcParams._backend | ||
| 799 | 813 | return None if backend is rcsetup._auto_backend_sentinel else backend | |
| 800 | 814 | ||
| 801 | 815 | def __repr__(self): | |
@@ -992,7 +1006,6 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True): | |||
| 992 | 1006 | transform=lambda line: line[1:] if line.startswith("#") else line, | |
| 993 | 1007 | fail_on_error=True) | |
| 994 | 1008 | rcParamsDefault._update_raw(rcsetup._hardcoded_defaults) | |
| 995 | - rcParamsDefault._ensure_has_backend() | ||
| 996 | 1009 | ||
| 997 | 1010 | rcParams = RcParams() # The global instance. | |
| 998 | 1011 | rcParams._update_raw(rcParamsDefault) | |
@@ -1201,8 +1214,7 @@ def rc_context(rc=None, fname=None): | |||
| 1201 | 1214 | plt.plot(x, y) | |
| 1202 | 1215 | ||
| 1203 | 1216 | """ | |
| 1204 | - orig = dict(rcParams.copy()) | ||
| 1205 | - del orig['backend'] | ||
| 1217 | + orig = rcParams.copy() | ||
| 1206 | 1218 | try: | |
| 1207 | 1219 | if fname: | |
| 1208 | 1220 | rc_file(fname) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -78,7 +78,6 @@ class RcParams(dict[RcKeyType, Any]): | |||
| 78 | 78 | ||
| 79 | 79 | def _update_raw(self, other_params: dict | RcParams) -> None: ... | |
| 80 | 80 | ||
| 81 | - def _ensure_has_backend(self) -> None: ... | ||
| 82 | 81 | def __setitem__(self, key: RcKeyType, val: Any) -> None: ... | |
| 83 | 82 | def __getitem__(self, key: RcKeyType) -> Any: ... | |
| 84 | 83 | def __iter__(self) -> Generator[RcKeyType, None, None]: ... | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -686,7 +686,13 @@ def test_rc_aliases(group, option, alias, value): | |||
| 686 | 686 | ||
| 687 | 687 | ||
| 688 | 688 | def test_all_params_defined_as_code(): | |
| 689 | - assert set(p.name for p in rcsetup._params_list()) == set(mpl.rcParams.keys()) | ||
| 689 | + params_in_code = {p.name for p in rcsetup._params_list()} | ||
| 690 | + # 'backend' is stored in RcParams._backend (a class variable) rather than | ||
| 691 | + # in the underlying dict, so it does not appear in rcParams.keys() / | ||
| 692 | + # __iter__. It is still accessible via rcParams['backend'] and | ||
| 693 | + # 'backend' in rcParams; it just doesn't show up during iteration. | ||
| 694 | + params_in_code.remove("backend") | ||
| 695 | + assert params_in_code == set(mpl.rcParams.keys()) | ||
| 690 | 696 | ||
| 691 | 697 | ||
| 692 | 698 | def test_validators_defined_as_code(): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -104,6 +104,15 @@ def test_rcparam_stubs(): | |||
| 104 | 104 | if not name.startswith('_') | |
| 105 | 105 | } | |
| 106 | 106 | ||
| 107 | + # backend is not a regular dict key anymore, but we have special logic to ensure | ||
| 108 | + # read and write access to it. | ||
| 109 | + # The _get('backend') is just a smoke test that 'backend' is still supported, and | ||
| 110 | + # it is thus justified to add 'backend' to the keys. This will fail in the future | ||
| 111 | + # when we remove 'backend' as accepted key and will remind us that we have to | ||
| 112 | + # remove it from the stubs. | ||
| 113 | + plt.rcParamsDefault._get('backend') | ||
| 114 | + runtime_rc_keys.add('backend') | ||
| 115 | + | ||
| 107 | 116 | assert {*typing.get_args(RcKeyType)} == runtime_rc_keys | |
| 108 | 117 | ||
| 109 | 118 | runtime_rc_group_keys = set() | |
| Back | FazBrowse Home | New Git URL |
0 commit comments