Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6342bed

Browse filesBrowse files
committed
help
1 parent a44290f commit 6342bed
Copy full SHA for 6342bed

File tree

5 files changed

+50
-87
lines changed
Filter options

5 files changed

+50
-87
lines changed

‎lib/matplotlib/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/__init__.py
+6-10Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -765,8 +765,12 @@ def __getitem__(self, key):
765765
plt.switch_backend(rcsetup._auto_backend_sentinel)
766766

767767
elif key == "path.effects" and self is globals().get("rcParams"):
768-
# to avoid circular imports
769-
return self._load_path_effects()
768+
# defers loading of patheffects to avoid circular imports
769+
import matplotlib.patheffects as path_effects
770+
771+
return [pe if isinstance(pe, path_effects.AbstractPathEffect)
772+
else getattr(path_effects, pe[0])(**pe[1])
773+
for pe in self._get('path.effects')]
770774

771775
return self._get(key)
772776

@@ -818,14 +822,6 @@ def copy(self):
818822
rccopy._set(k, self._get(k))
819823
return rccopy
820824

821-
def _load_path_effects(self):
822-
"""defers loading of patheffects to avoid circular imports"""
823-
import matplotlib.patheffects as path_effects
824-
825-
return [pe if isinstance(pe, path_effects.AbstractPathEffect)
826-
else getattr(path_effects, pe.pop('name'))(**pe)
827-
for pe in copy.deepcopy(self._get('path.effects'))]
828-
829825

830826
def rc_params(fail_on_error=False):
831827
"""Construct a `RcParams` instance from the default Matplotlib rc file."""

‎lib/matplotlib/mpl-data/stylelib/xkcd.mplstyle

Copy file name to clipboardExpand all lines: lib/matplotlib/mpl-data/stylelib/xkcd.mplstyle
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ figure.facecolor: white
2727

2828
# path
2929
path.sketch : 1, 100, 2
30-
path.effects: {'name': 'withStroke', 'linewidth': 4, 'foreground': 'w' }
30+
path.effects: ('withStroke', {'linewidth': 4, 'foreground': 'w' })

‎lib/matplotlib/rcsetup.py

Copy file name to clipboardExpand all lines: lib/matplotlib/rcsetup.py
+30-34Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -133,31 +133,6 @@ def validate_any(s):
133133
validate_anylist = _listify_validator(validate_any)
134134

135135

136-
def validate_anydict(allow_none=True, required_keys=None):
137-
"""Validate dictionary, check if keys are missing"""
138-
139-
required_keys = required_keys if required_keys else set()
140-
141-
def _validate_dict(d):
142-
try:
143-
d = ast.literal_eval(d)
144-
except ValueError:
145-
pass
146-
147-
if allow_none and d is None:
148-
return d
149-
150-
if isinstance(d, dict):
151-
if missing_keys := (required_keys - d.keys()):
152-
raise ValueError(f"Missing required key: {missing_keys!r}")
153-
return d
154-
155-
raise ValueError(f"Input {d!r} must be a dictionary {{'k': v}} "
156-
f"{'or None' if allow_none else ''}")
157-
158-
return _validate_dict
159-
160-
161136
def _validate_date(s):
162137
try:
163138
np.datetime64(s)
@@ -599,18 +574,39 @@ def validate_path_effects(s):
599574
if not s:
600575
return []
601576

602-
_validate = validate_anydict(allow_none=True, required_keys={'name'})
603-
# string list of dict {k1: 1, k2:2}, {k1:2}
604-
# validate_anylist relies on , for parsing so parse here instead
605-
if isinstance(s, str) and s.startswith("{"):
577+
if isinstance(s, str) and s.startswith("("):
606578
s = ast.literal_eval(s)
607-
if isinstance(s, dict):
608-
# list of one dict
609-
return _validate(s)
610579

611-
return [pe if getattr(pe, '__module__', "") == 'matplotlib.patheffects'
612-
else _validate(pe) for pe in validate_anylist(s)]
580+
if not isinstance(s, list): #string tuple list mostly
581+
s = [s]
582+
583+
_validate_name = ValidateInStrings("path.effects",
584+
["Normal",
585+
"PathPatchEffect",
586+
"SimpleLineShadow",
587+
"SimplePatchShadow",
588+
"Stroke",
589+
"TickedStroke",
590+
"withSimplePatchShadow",
591+
"withStroke",
592+
"withTickedStroke"])
593+
path_effects = []
594+
595+
for pe in s:
596+
#patheffects objects
597+
if getattr(pe, '__module__', "") == 'matplotlib.patheffects':
598+
path_effects.append(pe)
599+
continue
600+
601+
if not isinstance(pe, (tuple)):
602+
raise ValueError("Expected a list of tuples of the form: ('function name', {**kwargs})")
603+
604+
if len(pe) == 1:
605+
pe == (pe[0], {})
606+
path_effects.append((_validate_name(pe[0]), pe[1]))
607+
613608

609+
return path_effects
614610

615611
def _validate_greaterthan_minushalf(s):
616612
s = validate_float(s)

‎lib/matplotlib/rcsetup.pyi

Copy file name to clipboardExpand all lines: lib/matplotlib/rcsetup.pyi
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ class ValidateInStrings:
2929

3030
def validate_any(s: Any) -> Any: ...
3131
def validate_anylist(s: Any) -> list[Any]: ...
32-
def validate_anydict(allow_none: bool = True, required_keys: set[str]|None = None
33-
) -> Callable[[dict[str, Any]|None], dict[str, Any]]: ...
3432
def validate_bool(b: Any) -> bool: ...
3533
def validate_axisbelow(s: Any) -> bool | Literal["line"]: ...
3634
def validate_dpi(s: Any) -> Literal["figure"] | float: ...
@@ -143,7 +141,8 @@ def _validate_linestyle(s: Any) -> LineStyleType: ...
143141
def validate_markeverylist(s: Any) -> list[MarkEveryType]: ...
144142
def validate_bbox(s: Any) -> Literal["tight", "standard"] | None: ...
145143
def validate_sketch(s: Any) -> None | tuple[float, float, float]: ...
146-
def validate_path_effects(s: Any) -> list[AbstractPathEffect] | list[dict]: ...
144+
def validate_path_effects(s: str | list[AbstractPathEffect, Tuple[str,dict]])
145+
-> list[AbstractPathEffect | [Tuple[str, dict]]]: ...
147146
def validate_hatch(s: Any) -> str: ...
148147
def validate_hatchlist(s: Any) -> list[str]: ...
149148
def validate_dashlist(s: Any) -> list[list[float]]: ...

‎lib/matplotlib/tests/test_rcparams.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_rcparams.py
+11-39Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import numpy as np
1919
from matplotlib.rcsetup import (
20-
validate_anydict,
2120
validate_bool,
2221
validate_color,
2322
validate_colorlist,
@@ -635,35 +634,9 @@ def test_rcparams_legend_loc_from_file(tmpdir, value):
635634
with mpl.rc_context(fname=rc_path):
636635
assert mpl.rcParams["legend.loc"] == value
637636

638-
639-
@pytest.mark.parametrize("allow_none", [True, False])
640-
def test_validate_dict(allow_none):
641-
fval = validate_anydict(allow_none)
642-
assert fval("{'a': 1, 'b': 2}") == {'a': 1, 'b': 2}
643-
with pytest.raises(ValueError, match=r"Input \['a', 'b'\] "):
644-
fval(['a', 'b'])
645-
646-
fval = validate_anydict(allow_none, required_keys={'a'})
647-
assert fval({'a': 1}) == {'a': 1}
648-
with pytest.raises(ValueError, match="Missing required key: {'a'}"):
649-
fval({'b': 1})
650-
651-
652-
def test_validate_dict_none():
653-
assert validate_anydict()(None) is None
654-
assert validate_anydict(required_keys={'a'})(None) is None
655-
656-
with pytest.raises(ValueError,
657-
match=r"Input None must be a dictionary "):
658-
validate_anydict(False)(None)
659-
with pytest.raises(ValueError,
660-
match=r"Input 0 must be a dictionary {'k': v} or None"):
661-
validate_anydict(True)(0)
662-
663-
664-
ped = [{'name': 'Normal'},
665-
{'name': 'Stroke', 'offset': (1, 2)},
666-
{'name': 'withStroke', 'linewidth': 4, 'foreground': 'w'}]
637+
ped = [('Normal', {}),
638+
('Stroke', {'offset': (1, 2)}),
639+
('withStroke', {'linewidth': 4, 'foreground': 'w'})]
667640

668641
pel = [path_effects.Normal(),
669642
path_effects.Stroke((1, 2)),
@@ -677,11 +650,11 @@ def test_path_effects(value):
677650
assert validate_path_effects(value) == value
678651

679652

680-
def test_path_effects_string_dict():
653+
def test_path_effects_string():
681654
"""test list of dicts properly parsed"""
682-
pstr = "{'name': 'Normal'},"
683-
pstr += "{'name': 'Stroke', 'offset': (1, 2)},"
684-
pstr += "{'name': 'withStroke', 'linewidth': 4, 'foreground': 'w'}"
655+
pstr = "('Normal', ), "
656+
pstr += "('Stroke', : {'offset': (1, 2)}),"
657+
pstr += "('withStroke', {'linewidth': 4, 'foreground': 'w'})"
685658
assert validate_path_effects(pstr) == ped
686659

687660

@@ -701,10 +674,10 @@ def test_path_effects_picture(fig_test, fig_ref, fdict, flist):
701674

702675

703676
def test_path_effect_errors():
704-
with pytest.raises(ValueError, match="Missing required key: {'name'}"):
705-
mpl.rcParams['path.effects'] = [{'kwargs': {1, 2, 3}}]
677+
with pytest.raises(ValueError, match=r"Key path.effects: 'Happy'"):
678+
mpl.rcParams['path.effects'] = [("Happy", {'a': 1})]
706679

707-
with pytest.raises(ValueError, match=r"Key path.effects: Input 1 "):
680+
with pytest.raises(ValueError, match="Expected a list of tuples of the form: ('function name', {**kwargs})"):
708681
mpl.rcParams['path.effects'] = [1, 2, 3]
709682

710683

@@ -713,8 +686,7 @@ def test_path_effects_from_file(tmpdir):
713686
# if any of these are not allowed, an exception will be raised.
714687
# test for gh issue #22338
715688
rc_path = tmpdir.join("matplotlibrc")
716-
rc_path.write("path.effects: "
717-
"{'name': 'Normal'}, {'name': 'withStroke', 'linewidth': 2}")
689+
rc_path.write("path.effects: ('Normal', {}), ('withStroke', {'linewidth': 2})")
718690

719691
with mpl.rc_context(fname=rc_path):
720692
assert isinstance(mpl.rcParams["path.effects"][0], path_effects.Normal)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.