-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
ENH: first draft of ensure_ax decorator #4488
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 1 commit
ffdbe6e
a7918be
d271189
3501059
8351ceb
5feeb53
fe8eb34
9c0859b
f9ace37
c44b7dd
e398ad8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Not sure if this is a good idea. It is different that the current behavior and still a bit too magical/implicit.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -205,6 +205,22 @@ def uninstall_repl_displayhook(): | |
""" | ||
|
||
|
||
_ENSURE_AX_NEW_DOC = """ | ||
This function has been decorated by pyplot to create a new | ||
axes if one is not explicitly passed. | ||
|
||
The wrapped function can be called as any of :: | ||
|
||
{obj}{func}(*args, **kwargs) | ||
{obj}{func}(ax, *args, **kwargs) | ||
{obj}{func}(.., ax=ax) | ||
|
||
The first will make a new figure and axes, the other two | ||
will add to the axes passed in. | ||
|
||
""" | ||
|
||
|
||
def ensure_ax(func): | ||
"""Decorator to ensure that the function gets an `Axes` object. | ||
|
||
|
@@ -254,6 +270,34 @@ def inner(*args, **kwargs): | |
return inner | ||
|
||
|
||
def ensure_new_ax(func): | ||
"""Decorator to ensure that the function gets a new `Axes` object. | ||
|
||
Same as ensure_ax expect that a new figure and axes are created | ||
if an Axes is not explicitly passed. | ||
|
||
""" | ||
@wraps(func) | ||
def inner(*args, **kwargs): | ||
if 'ax' in kwargs: | ||
ax = kwargs.pop('ax') | ||
elif len(args) > 0 and isinstance(args[0], Axes): | ||
ax = args[0] | ||
args = args[1:] | ||
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 just pop? One line instead of two... ax = args.pop(0) 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. Because 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. Erm... good point, I always thought of args as a list, upon reading the docs I see it as as a tuple 😊. |
||
else: | ||
ax = quick_axes() | ||
return func(ax, *args, **kwargs) | ||
pre_doc = inner.__doc__ | ||
if pre_doc is None: | ||
pre_doc = '' | ||
else: | ||
pre_doc = dedent(pre_doc) | ||
inner.__doc__ = (_ENSURE_AX_NEW_DOC.format(func=func.__name__, obj='') + | ||
pre_doc) | ||
|
||
return inner | ||
|
||
|
||
def ensure_ax_meth(func): | ||
""" | ||
The same as ensure axes, but for class methods :: | ||
|
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.
As I read this line, having not read the source yet, I was expecting this decorator to create a figure/axes pair (
fig, ax = plt.subplots()
) and then pass the axes to the wrapped function. After reading the source I was initially surprised that this function does not create an axes and it seems like this could result in unexpected behaviour of this decorator. Is there any utility in allowing this decorator to create an axes via a kwarg to the decorator if one is not passed in? Though as I type that out it seems like, if this is a reasonable idea, to just have a different decorator that does that?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.
If these catch on, that is probably worth it's own decorator.
This mimics the expected behavior of
pyplot
(which is to use the current axes if it exists or create a new one). Eventually I want to replace the implementation of a majority of pyplot with