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

Skip to content

Commit e431d01

Browse files
committed
Make _preprocess_data stricter regarding label_namer.
Assert that label_namer (if given) is a parameter in the function signature (not "possibly" present via `**kwargs`). This seems more consistent with the expectations of the check later; in fact we can now just remove that check.
1 parent ec13742 commit e431d01

File tree

2 files changed

+23
-78
lines changed

2 files changed

+23
-78
lines changed

lib/matplotlib/__init__.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1586,9 +1586,17 @@ def func(ax, *args, **kwargs): ...
15861586
The list of parameter names for which lookup into *data* should be
15871587
attempted. If None, replacement is attempted for all arguments.
15881588
label_namer : string, optional, default: None
1589-
If set e.g. to "namer", if a ``namer`` kwarg is passed as a string, and
1590-
a ``label`` kwarg is not passed, then pass the value of the ``namer``
1591-
kwarg as the ``label`` kwarg as well.
1589+
If set e.g. to "namer" (which must be a kwarg in the function's
1590+
signature -- not as ``**kwargs``), if the *namer* argument passed in is
1591+
a (string) key of *data* and no *label* kwarg is passed, then use the
1592+
(string) value of the *namer* as *label*. ::
1593+
1594+
@_preprocess_data(label_namer="foo")
1595+
def func(foo, label=None): ...
1596+
1597+
func("key", data={"key": value})
1598+
# is equivalent to
1599+
func.__wrapped__(value, label="key")
15921600
"""
15931601

15941602
if func is None: # Return the actual decorator.
@@ -1622,7 +1630,7 @@ def func(ax, *args, **kwargs): ...
16221630
assert (replace_names or set()) <= set(arg_names) or varkwargs_name, (
16231631
"Matplotlib internal error: invalid replace_names ({!r}) for {!r}"
16241632
.format(replace_names, func.__name__))
1625-
assert label_namer is None or label_namer in arg_names or varkwargs_name, (
1633+
assert label_namer is None or label_namer in arg_names, (
16261634
"Matplotlib internal error: invalid label_namer ({!r}) for {!r}"
16271635
.format(label_namer, func.__name__))
16281636

@@ -1653,26 +1661,19 @@ def inner(ax, *args, data=None, **kwargs):
16531661
bound.apply_defaults()
16541662
del bound.arguments["data"]
16551663

1656-
all_kwargs = {**bound.arguments, **bound.kwargs}
16571664
if needs_label:
1658-
if label_namer not in all_kwargs:
1659-
cbook._warn_external(
1660-
"Tried to set a label via parameter {!r} in func {!r} but "
1661-
"couldn't find such an argument.\n(This is a programming "
1662-
"error, please report to the Matplotlib list!)".format(
1663-
label_namer, func.__name__),
1664-
RuntimeWarning)
1665+
all_kwargs = {**bound.arguments, **bound.kwargs}
1666+
# label_namer will be in all_kwargs as we asserted above that
1667+
# `label_namer is None or label_namer in arg_names`.
1668+
label = _label_from_arg(all_kwargs[label_namer], auto_label)
1669+
if "label" in arg_names:
1670+
bound.arguments["label"] = label
1671+
try:
1672+
bound.arguments.move_to_end(varkwargs_name)
1673+
except KeyError:
1674+
pass
16651675
else:
1666-
label = _label_from_arg(all_kwargs[label_namer], auto_label)
1667-
if "label" in arg_names:
1668-
bound.arguments["label"] = label
1669-
try:
1670-
bound.arguments.move_to_end(varkwargs_name)
1671-
except KeyError:
1672-
pass
1673-
else:
1674-
bound.arguments.setdefault(
1675-
varkwargs_name, {})["label"] = label
1676+
bound.arguments.setdefault(varkwargs_name, {})["label"] = label
16761677

16771678
return func(*bound.args, **bound.kwargs)
16781679

lib/matplotlib/tests/test_preprocess_data.py

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,6 @@ def func_no_ax_args(*args, **kwargs): pass
5858
with pytest.raises(AssertionError):
5959
_preprocess_data(label_namer="z")(func_args)
6060

61-
# but "ok-ish", if func has kwargs -> will show up at runtime :-(
62-
_preprocess_data(label_namer="z")(func_kwargs)
63-
_preprocess_data(label_namer="z")(func_no_ax_args)
64-
65-
66-
def test_label_namer_only_if_data():
67-
"""label_namer should only apply when data is passed."""
68-
69-
def real_func(x, y):
70-
pass
71-
72-
@_preprocess_data(label_namer="x")
73-
def func(*args, **kwargs):
74-
real_func(**kwargs)
75-
76-
func(None, x="a", y="b")
77-
with pytest.raises(TypeError):
78-
# This sets a label although the function can't handle it.
79-
func(None, x="a", y="b", data={"a": "A", "b": "B"})
80-
8161

8262
@pytest.mark.parametrize('func', all_funcs, ids=all_func_ids)
8363
def test_function_call_without_data(func):
@@ -178,42 +158,6 @@ def func_replace_all(ax, x, y, ls="x", label=None, w="NOT"):
178158
func_replace_all(None, x="a", y="b", w="x", label="text", data=data) ==
179159
"x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")
180160

181-
@_preprocess_data(label_namer="y")
182-
def func_varags_replace_all(ax, *args, **kwargs):
183-
all_args = [None, None, "x", None, "xyz"]
184-
for i, v in enumerate(args):
185-
all_args[i] = v
186-
for i, k in enumerate(["x", "y", "ls", "label", "w"]):
187-
if k in kwargs:
188-
all_args[i] = kwargs[k]
189-
x, y, ls, label, w = all_args
190-
return "x: %s, y: %s, ls: %s, w: %s, label: %s" % (
191-
list(x), list(y), ls, w, label)
192-
193-
# in the first case, we can't get a "y" argument,
194-
# as we don't know the names of the *args
195-
assert (func_varags_replace_all(None, x="a", y="b", w="x", data=data) ==
196-
"x: [1, 2], y: [8, 9], ls: x, w: xyz, label: b")
197-
assert (
198-
func_varags_replace_all(None, "a", "b", w="x", label="", data=data) ==
199-
"x: [1, 2], y: [8, 9], ls: x, w: xyz, label: ")
200-
assert (
201-
func_varags_replace_all(None, "a", "b", w="x", label="text",
202-
data=data) ==
203-
"x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")
204-
assert (
205-
func_varags_replace_all(None, x="a", y="b", w="x", label="",
206-
data=data) ==
207-
"x: [1, 2], y: [8, 9], ls: x, w: xyz, label: ")
208-
assert (
209-
func_varags_replace_all(None, x="a", y="b", w="x", label="text",
210-
data=data) ==
211-
"x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")
212-
213-
with pytest.warns(RuntimeWarning):
214-
assert (func_varags_replace_all(None, "a", "b", w="x", data=data) ==
215-
"x: [1, 2], y: [8, 9], ls: x, w: xyz, label: None")
216-
217161

218162
def test_no_label_replacements():
219163
"""Test with "label_namer=None" -> no label replacement at all"""

0 commit comments

Comments
 (0)