Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 56fc4d6

Browse files
committed
Remove namespaces and keep chainmap for settings.
As per @timhoffm's suggestion, decreasing scope of this PR to first just remove the dict inheritance and add a ChainMap to maintain settings. This is a fairly straightforward change and doesn't change the interface. Furthermore, the keys are still dotted and don't support namespacing as defining namespaces might take a little more discussion.
1 parent 68a16c9 commit 56fc4d6

File tree

3 files changed

+36
-121
lines changed

3 files changed

+36
-121
lines changed

lib/matplotlib/__init__.py

Lines changed: 26 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -662,35 +662,11 @@ class RcParams(MutableMapping):
662662
:ref:`customizing-with-matplotlibrc-files`
663663
"""
664664
validate = rcsetup._validators
665-
_namespaces = ("backends", "lines", "patches", "hatches", "boxplot", "font", "text",
666-
"latex", "axes", "date", "xtick", "ytick", "grid", "legend",
667-
"figure", "image", "contour", "errorbar", "hist", "scatter", "agg",
668-
"path", "savefig", "tk", "ps", "pdf", "svg", "pgf", "docstring",
669-
"keymap", "animation", "_internal", "webagg", "markers", "pcolor",
670-
"pcolormesh", "patch", "hatch", "mathtext", "polaraxes", "axes3d",
671-
"xaxis", "yaxis", "default")
672-
673-
_single_key_set = {"backend", "toolbar", "interactive",
674-
"timezone", "backend_fallback"}
675665

676666
def __init__(self, *args, **kwargs):
677-
self._namespace_maps = {name: ChainMap({}) for name in self._namespaces}
667+
self._rcvalues = ChainMap({})
678668
self.update(*args, **kwargs)
679-
self._new_child()
680-
681-
@staticmethod
682-
@functools.lru_cache
683-
def _split_key(key, sep="."):
684-
keys = key.split(sep, maxsplit=1)
685-
return keys, len(keys)
686-
687-
def _new_child(self):
688-
for space in self._namespace_maps.keys():
689-
self._namespace_maps[space] = self._namespace_maps[space].new_child()
690-
691-
def _parents(self):
692-
for space in self._namespace_maps.keys():
693-
self._namespace_maps[space] = self._namespace_maps[space].parents
669+
self._rcvalues.new_child()
694670

695671
def _set(self, key, val):
696672
"""
@@ -710,25 +686,7 @@ def _set(self, key, val):
710686
711687
:meta public:
712688
"""
713-
keys, depth = self._split_key(key)
714-
if depth == 1:
715-
if key in self._single_key_set:
716-
self._namespace_maps["default"][key] = val
717-
# Uncomment the following line and remove the raise statement
718-
# to enable setting namespaces.
719-
# else:
720-
# if isinstance(val, dict):
721-
# self._namespace_maps[key] = ChainMap({}, val)
722-
# else:
723-
# raise ValueError(
724-
# f"{key} should be set using a dictionary but found "
725-
# f"{type(val)}")
726-
else:
727-
raise KeyError(
728-
f"{key} is not a valid rc parameter (see rcParams.keys() for "
729-
f"a list of valid parameters)")
730-
elif depth == 2:
731-
self._namespace_maps[keys[0]][keys[1]] = val
689+
self._rcvalues[key] = val
732690

733691
def _get(self, key):
734692
"""
@@ -749,19 +707,7 @@ def _get(self, key):
749707
750708
:meta public:
751709
"""
752-
keys, depth = self._split_key(key)
753-
if depth == 1:
754-
if key in self._single_key_set:
755-
return self._namespace_maps["default"].get(key)
756-
# Uncomment the following line and remove the raise statement
757-
# to enable getting namespace parameters.
758-
# return self._namespace_maps[key]
759-
else:
760-
raise KeyError(
761-
f"{key} is not a valid rc parameter (see rcParams.keys() for "
762-
f"a list of valid parameters)")
763-
elif depth == 2:
764-
return self._namespace_maps[keys[0]].get(keys[1])
710+
return self._rcvalues[key]
765711

766712
def __setitem__(self, key, val):
767713
try:
@@ -785,8 +731,8 @@ def __setitem__(self, key, val):
785731
return
786732
try:
787733
cval = self.validate[key](val)
788-
if key in self._single_key_set:
789-
key = f"default.{key}"
734+
# if key in self._single_key_set:
735+
# key = f"default.{key}"
790736
except ValueError as ve:
791737
raise ValueError(f"Key {key}: {ve}") from None
792738
self._set(key, cval)
@@ -819,21 +765,9 @@ def __getitem__(self, key):
819765
return self._get(key)
820766

821767
def _get_default(self, key):
822-
keys, depth = self._split_key(key)
823-
if depth == 1:
824-
if key in self._single_key_set:
825-
return self._namespace_maps["default"].get(key)
826-
# Uncomment the following line and remove the raise statement
827-
# to enable getting namespace parameters.
828-
# return self._namespace_maps[key]
829-
else:
830-
raise KeyError(
831-
f"{key} is not a valid rc parameter (see rcParams.keys() for "
832-
f"a list of valid parameters)")
833-
elif depth == 2:
834-
return self._namespace_maps[keys[0]].maps[-1].get(keys[1])
768+
return self._rcvalues.maps[-1][key]
835769

836-
def getdefault(self, key):
770+
def get_default(self, key):
837771
if key in _deprecated_map:
838772
version, alt_key, alt_val, inverse_alt = _deprecated_map[key]
839773
_api.warn_deprecated(
@@ -848,7 +782,7 @@ def getdefault(self, key):
848782

849783
return self._get_default(key)
850784

851-
def getdefaults(self):
785+
def get_defaults(self):
852786
"""Return default values set during initialization."""
853787
defaults = self.copy()
854788
defaults.clear()
@@ -860,54 +794,35 @@ def _get_backend_or_none(self):
860794
return None if backend is rcsetup._auto_backend_sentinel else backend
861795

862796
def __delitem__(self, key):
863-
keys, depth = self._split_key(key)
864797
try:
865-
if depth == 1:
866-
if key in self._single_key_set:
867-
del self._namespace_maps["default"][key]
868-
else:
869-
raise KeyError
870-
elif depth == 2:
871-
del self._namespace_maps[keys[0]][keys[1]]
798+
del self._rcvalues[key]
872799
except KeyError as err:
873800
raise KeyError(
874801
f"{key} is not a valid rc parameter (see rcParams.keys() for "
875802
f"a list of valid parameters)") from err
876803

877804
def __contains__(self, key):
878-
keys, depth = self._split_key(key)
879-
if depth == 1:
880-
if key in self._single_key_set:
881-
return key in self._namespace_maps["default"]
882-
else:
883-
return False
884-
elif depth == 2:
885-
return any(key in mapping for mapping in self._namespace_maps)
805+
return key in self._rcvalues
886806

887807
def __iter__(self):
888808
"""Yield from sorted list of keys"""
889-
keys = (
890-
".".join((space, key)) if space != 'default' else key
891-
for space, mapping in self._namespace_maps.items()
892-
for key in mapping.keys()
893-
)
894809
with _api.suppress_matplotlib_deprecation_warning():
895-
yield from sorted(keys)
810+
yield from sorted(self._rcvalues.keys())
896811

897812
def __len__(self):
898-
return sum(len(mapping) for mapping in self._namespace_maps)
813+
return len(self._rcvalues)
899814

900815
def __repr__(self):
901816
class_name = self.__class__.__name__
902817
indent = len(class_name) + 1
903818
with _api.suppress_matplotlib_deprecation_warning():
904-
repr_split = pprint.pformat(dict(self.items()), indent=1,
819+
repr_split = pprint.pformat(dict(self._rcvalues.items()), indent=1,
905820
width=80 - indent).split('\n')
906821
repr_indented = ('\n' + ' ' * indent).join(repr_split)
907822
return f'{class_name}({repr_indented})'
908823

909824
def __str__(self):
910-
return '\n'.join(map('{0[0]}: {0[1]}'.format, sorted(self.items())))
825+
return '\n'.join(map('{0[0]}: {0[1]}'.format, sorted(self._rcvalues.items())))
911826

912827
def pop(self, key):
913828
keys, depth = self._split_key(key)
@@ -926,8 +841,7 @@ def popitem(self):
926841
"popitem is not implemented for RcParams.")
927842

928843
def clear(self):
929-
for namespace in self._namespace_maps:
930-
self._namespace_maps[namespace].clear()
844+
self._rcvalues.clear()
931845

932846
def setdefault(self, key, default=None):
933847
"""Insert key with a value of default if key is not in the dictionary.
@@ -1062,8 +976,7 @@ def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False):
1062976
fname)
1063977
raise
1064978

1065-
config = RcParams()
1066-
config._parents()
979+
config = dict()
1067980

1068981
for key, (val, line, line_no) in rc_temp.items():
1069982
if key in rcsetup._validators:
@@ -1092,8 +1005,7 @@ def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False):
10921005
or from the matplotlib source distribution""",
10931006
dict(key=key, fname=fname, line_no=line_no,
10941007
line=line.rstrip('\n'), version=version))
1095-
config._new_child()
1096-
return config
1008+
return RcParams(config)
10971009

10981010

10991011
def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
@@ -1117,7 +1029,7 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
11171029
return config_from_file
11181030

11191031
with _api.suppress_matplotlib_deprecation_warning():
1120-
config = RcParams({**rcParams.getdefaults(), **config_from_file})
1032+
config = RcParams({**rcParams.get_defaults(), **config_from_file})
11211033

11221034
if "".join(config['text.latex.preamble']):
11231035
_log.info("""
@@ -1137,10 +1049,10 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
11371049
# Strip leading comment.
11381050
transform=lambda line: line[1:] if line.startswith("#") else line,
11391051
fail_on_error=True)
1140-
for key in rcsetup._hardcoded_defaults:
1141-
space, subkey = key.split(".")
1142-
if not rcParams._namespace_maps[space]:
1143-
rcParams._namespace_maps[space] = ChainMap({})
1052+
# for key in rcsetup._hardcoded_defaults:
1053+
# space, subkey = key.split(".")
1054+
# if not rcParams._namespace_maps[space]:
1055+
# rcParams._namespace_maps[space] = ChainMap({})
11441056
rcParams.update(rcsetup._hardcoded_defaults)
11451057
# Normally, the default matplotlibrc file contains *no* entry for backend (the
11461058
# corresponding line starts with ##, not #; we fill on _auto_backend_sentinel
@@ -1156,7 +1068,7 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
11561068
defaultParams = rcsetup.defaultParams = {
11571069
# We want to resolve deprecated rcParams, but not backend...
11581070
key: [(rcsetup._auto_backend_sentinel if key == "backend" else
1159-
rcParams.getdefault(key)),
1071+
rcParams.get_default(key)),
11601072
validator]
11611073
for key, validator in rcsetup._validators.items()}
11621074
if rcParams['axes.formatter.use_locale']:
@@ -1349,10 +1261,7 @@ def rc_context(rc=None, fname=None):
13491261
13501262
"""
13511263
try:
1352-
for space in rcParams._namespace_maps.keys():
1353-
rcParams._namespace_maps[space] = rcParams._namespace_maps[
1354-
space
1355-
].new_child()
1264+
rcParams._rcvalues = rcParams._rcvalues.new_child()
13561265
if fname:
13571266
rc_file(fname)
13581267
if rc:
@@ -1361,7 +1270,7 @@ def rc_context(rc=None, fname=None):
13611270
finally:
13621271
# Revert to the original rcs.
13631272
backend = rcParams["backend"]
1364-
rcParams._parents()
1273+
rcParams._rcvalues = rcParams._rcvalues.parents
13651274
rcParams["backend"] = backend
13661275

13671276

lib/matplotlib/style/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def use(style):
114114
# rcParamsDefault, no need to reemit them here.
115115
with _api.suppress_matplotlib_deprecation_warning():
116116
# don't trigger RcParams.__getitem__('backend')
117-
style = {k: mpl.rcParams.getdefault(k) for k in mpl.rcParams
117+
style = {k: mpl.rcParams.get_default(k) for k in mpl.rcParams
118118
if k not in STYLE_BLACKLIST}
119119
elif style in library:
120120
style = library[style]

lib/matplotlib/tests/test_rcparams.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,12 +601,12 @@ def test_rcparams_legend_loc():
601601

602602
def test_rcparams_getdefault():
603603
with mpl.rc_context({"image.lut": 128}):
604-
assert mpl.rcParams.getdefault("image.lut") == 256
604+
assert mpl.rcParams.get_default("image.lut") == 256
605605

606606

607607
def test_rcparams_getdefaults():
608608
mpl.rc("image", lut=128)
609-
defaults = mpl.rcParams.getdefaults()
609+
defaults = mpl.rcParams.get_defaults()
610610
mpl.rcParams.clear()
611611
assert defaults == mpl.rcParams
612612

@@ -618,8 +618,14 @@ def test_rcdefaults():
618618
# lines.linewidth is not a style blacklisted key and should be
619619
# reset to the default value.
620620
# breakpoint()
621-
lw = mpl.rcParams.getdefault("lines.linewidth")
621+
lw = mpl.rcParams.get_default("lines.linewidth")
622622
mpl.rcParams["lines.linewidth"] = lw + 1
623623
mpl.rcdefaults()
624624
assert mpl.rcParams["webagg.port"] == 9000
625625
assert mpl.rcParams["lines.linewidth"] == lw
626+
627+
628+
def test_rcparams_clear():
629+
mpl.rcParams["image.lut"] = 128
630+
mpl.rcParams.clear()
631+
assert mpl.rcParams["image.lut"] == 256

0 commit comments

Comments
 (0)