-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
ENH: plotting methods can unpack labeled data [MOVED TO #4829] #4787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1e21903
1cf0f38
676eeb4
9e6e7b4
5ace465
e90d859
6646545
4059b44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,7 +115,7 @@ | |
import warnings | ||
import contextlib | ||
import distutils.sysconfig | ||
|
||
import functools | ||
# cbook must import matplotlib only within function | ||
# definitions, so it is safe to import from it here. | ||
from matplotlib.cbook import is_string_like, mplDeprecation | ||
|
@@ -1515,6 +1515,74 @@ def test(verbosity=1): | |
|
||
test.__test__ = False # nose: this function is not a test | ||
|
||
|
||
def _replacer(data, key): | ||
# if key isn't a string don't bother | ||
if not isinstance(key, six.string_types): | ||
return key | ||
# try to use __getitem__ | ||
try: | ||
return data[key] | ||
# key does not exist, silently fall back to key | ||
except KeyError: | ||
return key | ||
|
||
|
||
def unpack_labeled_data(wl_args=None, wl_kwargs=None, label_pos=None): | ||
""" | ||
A decorator to add a 'data' kwarg to any a function. The signature | ||
of the input function must be :: | ||
|
||
def foo(ax, *args, **kwargs) | ||
|
||
so this is suitable for use with Axes methods. | ||
""" | ||
if label_pos is not None: | ||
label_arg, label_kwarg = label_pos | ||
|
||
if wl_kwargs is not None: | ||
wl_kwargs = set(wl_kwargs) | ||
if wl_args is not None: | ||
wl_args = set(wl_args) | ||
|
||
def param(func): | ||
@functools.wraps(func) | ||
def inner(ax, *args, **kwargs): | ||
data = kwargs.pop('data', None) | ||
if data is not None: | ||
if wl_args is None: | ||
new_args = tuple(_replacer(data, a) for a in args) | ||
else: | ||
new_args = tuple(_replacer(data, a) if j in wl_args else a | ||
for j, a in enumerate(args)) | ||
|
||
if wl_kwargs is None: | ||
new_kwargs = dict((k, _replacer(data, v)) | ||
for k, v in six.iteritems(kwargs)) | ||
else: | ||
new_kwargs = dict( | ||
(k, _replacer(data, v) if k in wl_kwargs else v) | ||
for k, v in six.iteritems(kwargs)) | ||
else: | ||
new_args, new_kwargs = args, kwargs | ||
|
||
if (label_pos is not None and ('label' not in kwargs or | ||
kwargs['label'] is None)): | ||
if len(args) > label_arg: | ||
try: | ||
kwargs['label'] = args[label_arg].name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use @mwaskom's suggestion of using the text label instead of the
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should probably be changed to use either. I was trying to make this work for cases where the user is currently doing |
||
except AttributeError: | ||
pass | ||
elif label_kwarg in kwargs: | ||
try: | ||
new_kwargs['label'] = kwargs[label_kwarg].name | ||
except AttributeError: | ||
pass | ||
|
||
return func(ax, *new_args, **new_kwargs) | ||
return inner | ||
return param | ||
|
||
verbose.report('matplotlib version %s' % __version__) | ||
verbose.report('verbose.level %s' % verbose.level) | ||
verbose.report('interactive is %s' % is_interactive()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't check against the case that a user called the function with args alone (aka: the new label is in args). Not sure how frequent that is...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, but I am not super worried about that in this case because in order for this code path to be hit they have to be using the
data
kwarg so we won't break un-touched user code.Some of the methods take
label
as an explicit input, but many take it through a blind**kwargs
. I suspect that we will have to inspectfunc
on the way in.