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

Skip to content

Commit b38d518

Browse files
committed
ENH: let unpack_labeled_data handle var-length *args
1 parent 722fbd9 commit b38d518

File tree

2 files changed

+47
-24
lines changed

2 files changed

+47
-24
lines changed

lib/matplotlib/__init__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,7 +1529,8 @@ def _replacer(data, key):
15291529
return key
15301530

15311531

1532-
def unpack_labeled_data(replace_names=None, label_namer="y", positional_parameter_names=None):
1532+
def unpack_labeled_data(replace_names=None, replace_all_args=False, label_namer="y",
1533+
positional_parameter_names=None):
15331534
"""
15341535
A decorator to add a 'data' kwarg to any a function. The signature
15351536
of the input function must include the ax argument at the first position ::
@@ -1543,14 +1544,18 @@ def foo(ax, *args, **kwargs)
15431544
replace_names : list of strings, optional, default: None
15441545
The list of parameter names which arguments should be replaced by `data[name]`. If None,
15451546
all arguments are replaced if they are included in `data`.
1547+
replace_all_args : bool, default: False
1548+
If True, all arguments in *args get replaced, even if they are not in replace_names.
1549+
NOTE: this should be used only when the order of the names depends on the number of *args.
15461550
label_namer : string, optional, default: 'y'
15471551
The name of the parameter which argument should be used as label, if label is not set. If
15481552
None, the label keyword argument is not set.
1553+
NOTE: you MUST pass ``label_namer=None`` if the function can't handle a ``label`` kwarg!
15491554
positional_parameter_names : list of strings, optional, default: None
15501555
The full list of positional parameter names (including the `ax` argument at the first place
15511556
and including all possible positional parameter in `*args`), in the right order. Can also
15521557
include all other keyword parameter. Only needed if the wrapped function does contain
1553-
`*args` and replace_names is not None.
1558+
`*args` and (replace_names is not None or replace_all_args is False).
15541559
"""
15551560
if replace_names is not None:
15561561
replace_names = set(replace_names)
@@ -1579,7 +1584,8 @@ def param(func):
15791584
# No argnames should be replaced
15801585
arg_names = []
15811586
else:
1582-
assert not (positional_parameter_names is None), "Got replace_names and wrapped function uses *args, need positional_parameter_names!"
1587+
assert not (positional_parameter_names is None or not replace_all_args), \
1588+
"Got replace_names and wrapped function uses *args, need positional_parameter_names!"
15831589
# remove ax arg
15841590
arg_names = positional_parameter_names[1:]
15851591

lib/matplotlib/tests/test_labled_data_unpacking.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66

77
from .. import unpack_labeled_data
88

9+
910
# these two get used in multiple tests, so define them here
1011
@unpack_labeled_data(replace_names=["x","y"])
1112
def plot_func(ax, x, y, ls="x", label=None, w="xyz"):
1213
return "x: %s, y: %s, ls: %s, w: %s, label: %s" % (list(x),list(y),ls, w, label)
1314

1415

15-
@unpack_labeled_data(replace_names=["x","y"], positional_parameter_names=["ax", "x", "y", "ls", "label", "w"])
16+
@unpack_labeled_data(replace_names=["x","y"], positional_parameter_names=["x", "y", "ls", "label", "w"])
1617
def plot_func_varags(ax, *args, **kwargs):
1718
all_args = [None, None, "x", None, "xyz"]
1819
for i, v in enumerate(args):
@@ -26,25 +27,6 @@ def plot_func_varags(ax, *args, **kwargs):
2627

2728
all_funcs = [plot_func, plot_func_varags]
2829

29-
d# these two get used in multiple tests, so define them here
30-
@unpack_labeled_data(replace_names=["x","y"])
31-
def plot_func(ax, x, y, ls="x", label=None, w="xyz"):
32-
return "x: %s, y: %s, ls: %s, w: %s, label: %s" % (list(x),list(y),ls, w, label)
33-
34-
35-
@unpack_labeled_data(replace_names=["x","y"], positional_parameter_names=["ax", "x", "y", "ls", "label", "w"])
36-
def plot_func_varags(ax, *args, **kwargs):
37-
all_args = [None, None, "x", None, "xyz"]
38-
for i, v in enumerate(args):
39-
all_args[i] = v
40-
for i, k in enumerate(["x", "y", "ls", "label", "w"]):
41-
if k in kwargs:
42-
all_args[i] = kwargs[k]
43-
x, y, ls, label, w = all_args
44-
return "x: %s, y: %s, ls: %s, w: %s, label: %s" % (list(x),list(y),ls, w, label)
45-
46-
47-
all_funcs = [plot_func, plot_func_varags]
4830

4931
def test_compiletime_checks():
5032
"""test decorator invocations -> no replacements"""
@@ -112,6 +94,7 @@ def f():
11294
# This sets a label although the function can't handle it.
11395
assert_raises(TypeError, f)
11496

97+
11598
def test_function_call_without_data():
11699
"""test without data -> no replacements"""
117100
for func in all_funcs:
@@ -192,13 +175,18 @@ def func_varags_replace_all(ax, *args, **kwargs):
192175
return "x: %s, y: %s, ls: %s, w: %s, label: %s" % (list(x),list(y),ls, w, label)
193176

194177
# in the first case, we can't get a "y" argument, as we don't know the names of the *args
195-
assert_equal(func_varags_replace_all(None, "a","b", w="x", data=data), "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: None")
196178
assert_equal(func_varags_replace_all(None, x="a",y="b", w="x", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: b")
197179
assert_equal(func_varags_replace_all(None, "a","b", w="x", label="", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: ")
198180
assert_equal(func_varags_replace_all(None, "a","b", w="x", label="text", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")
199181
assert_equal(func_varags_replace_all(None, x="a",y="b", w="x", label="", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: ")
200182
assert_equal(func_varags_replace_all(None, x="a",y="b", w="x", label="text", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")
201183

184+
try:
185+
from pandas.util.testing import assert_produces_warning
186+
assert_equal(func_varags_replace_all(None, "a","b", w="x", data=data), "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: None")
187+
except ImportError:
188+
pass
189+
202190

203191
def test_no_label_replacements():
204192
"""Test without "label_namer=None" -> no label replacement at all"""
@@ -213,6 +201,7 @@ def func_no_label(ax, x, y, ls="x", label=None, w="xyz"):
213201
assert_equal(func_no_label(None, "a","b", label="", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: ")
214202
assert_equal(func_no_label(None, "a","b", label="text", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")
215203

204+
216205
def test_more_args_than_pos_parameter():
217206
@unpack_labeled_data(replace_names=["x","y"])
218207
def func(ax, x, y, z=1):
@@ -222,3 +211,31 @@ def func(ax, x, y, z=1):
222211
def f():
223212
func(None, "a","b", "z", "z", data=data)
224213
assert_raises(RuntimeError, f)
214+
215+
216+
def test_function_call_with_replace_all_args():
217+
"""Test with a "replace_all_args" argument, all *args should be replaced"""
218+
data = {"a":[1,2],"b":[8,9], "x":"xyz"}
219+
220+
def funcy(ax, *args, **kwargs):
221+
all_args = [None, None, "x", None, "NOT"]
222+
for i, v in enumerate(args):
223+
all_args[i] = v
224+
for i, k in enumerate(["x", "y", "ls", "label", "w"]):
225+
if k in kwargs:
226+
all_args[i] = kwargs[k]
227+
x, y, ls, label, w = all_args
228+
return "x: %s, y: %s, ls: %s, w: %s, label: %s" % (list(x),list(y),ls, w, label)
229+
230+
func = unpack_labeled_data(replace_all_args=True, replace_names=["w"])(funcy)
231+
232+
#assert_equal(func(None, "a","b", w="x", data=data), "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: None")
233+
assert_equal(func(None, "a","b", w="x", label="", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: ")
234+
assert_equal(func(None, "a","b", w="x", label="text", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")
235+
236+
func2 = unpack_labeled_data(replace_all_args=True, replace_names=["w"],
237+
positional_parameter_names=["x", "y", "ls", "label", "w"])(funcy)
238+
239+
assert_equal(func2(None, "a","b", w="x", data=data), "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: b")
240+
assert_equal(func2(None, "a","b", w="x", label="", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: ")
241+
assert_equal(func2(None, "a","b", w="x", label="text", data=data) , "x: [1, 2], y: [8, 9], ls: x, w: xyz, label: text")

0 commit comments

Comments
 (0)