-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Convert **kwargs to named arguments for a clearer API #11137
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
Conversation
lib/matplotlib/axes/_axes.py
Outdated
@@ -1433,7 +1433,8 @@ def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False, | |||
|
|||
# @_preprocess_data() # let 'plot' do the unpacking.. | |||
@docstring.dedent_interpd | |||
def loglog(self, *args, **kwargs): | |||
def loglog(self, *args, basex=10, basey=10, subsx=None, subsy=None, | |||
nonposx='mask', nonposy='mask', **kwargs): |
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.
I think it looks slightly better (though semantically identical) to have e.g.
def loglog(self, *args,
basex=..., subsx=..., ...
basey=..., ...
**kwargs):
(but ymmv)
lib/matplotlib/pyplot.py
Outdated
@@ -1552,7 +1552,7 @@ def yscale(scale, **kwargs): | |||
gca().set_yscale(scale, **kwargs) | |||
|
|||
|
|||
def xticks(*args, **kwargs): | |||
def xticks(locs=None, labels=None, **kwargs): |
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.
What are the names of these arguments in other similar parts of the API? (i.e. are "locs" and "labels" what we want to call these?)
Same for yticks.
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.
I couldn't see a directly analogous part of the API, but these names are taken directly from the docstring where it describes the call signatures.
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.
Actually the argument for Axes.set_xticks
and Axis.set_ticks
is named ticks
, so let's stay consistent and change the docstring accordingly (remember that argument names effectively become part of the public API).
The argument for Axes.set_xticklabels
is named labels
but the one for Axis.set_ticklabels
is ticklabels
, which is unfortunate but I think labels
is fine.
lib/mpl_toolkits/mplot3d/axes3d.py
Outdated
@@ -1357,11 +1360,6 @@ def ticklabel_format( | |||
sb = True | |||
elif style in ['plain', 'comma']: | |||
sb = False | |||
if style == 'plain': |
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.
just drop support for 'comma' style (deprecation, yada yada)? that doesn't exist for regular axes either.
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 actually drop support for anything - the cb
variable was never used after being assigned!
944a0e3
to
21e9e65
Compare
Turns out the default behaviour for |
I would argue that that's a behavioral bug (the intent is certainly that both behave in the same way...) |
I actually agree, but fixing bugs is out of scope for this PR - it's large enough already! I've therefore just removed the log-related changes, with an aspiration to do them later. |
21e9e65
to
623b98d
Compare
We should somehow mention the additional parameters in the docstring. Suggestion: Add them to the existing params:
alternatively use a separate entry:
What is our recommendation? Are they equally or do we recommend one and the other is just there for backward compatibility. If so, that should be documented as well. |
@@ -3016,7 +3016,8 @@ def _validate_converted_limits(self, limit, convert): | |||
raise ValueError("Axis limits cannot be NaN or Inf") | |||
return converted_limit | |||
|
|||
def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw): | |||
def set_xlim(self, left=None, right=None, emit=True, auto=False, | |||
*, xmin=None, xmax=None): |
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.
Would it be worth deprecating xmin and xmax or left or right? Seems a bit silly having two ways of specifying what is really the same argument.
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.
+1 that two ways are a bit silly. Not sure if we have to go as far as deprecating (but wouldn‘t object either. Maybe go slow with a PendingDeprecation). Anyway, there should be one recommended way and the other only is only a backward compatible fallback.
The question is which to recommend:
- xmin, xmax is more generic and easy to transfer, e.g. ymin rmin
- left, right is more semantic
To me +0.5 for keeping xmin, xmax
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.
Actually, left/right is clearly better IMO: one can pass left > right for inverted axes, which sounds less silly that xmin > xmax...
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.
lib/matplotlib/axes/_base.py
Outdated
if right is None and iterable(left): | ||
left, right = left | ||
if xmin is not None: | ||
if left is not None: | ||
raise ValueError('Cannot use argument xmin=%r; would ' |
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 technically breaks backwards compatibility I think - previously passing xmin
and left
would silently use the value in xmin
, whereas now it raises an error.
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.
Yes. Should just issue a warning. But what to be done in this context depends on the decision on deprecation.
623b98d
to
1ea943f
Compare
OK, update on the xmin/xmax situation:
|
🎉 Everything passes! If there are no additional review items, I'd like to get this merged soon so I can open the next PR in the sequence 😄 |
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.
per https://github.com/matplotlib/matplotlib/pull/11137/files#r184865106
anyone can dismiss this once the comment is handled.
@@ -2744,8 +2744,6 @@ def ticklabel_format(self, *, axis='both', style='', scilimits=None, | |||
sb = True | |||
elif style == 'plain': | |||
sb = False | |||
elif style == 'comma': | |||
raise NotImplementedError("comma style remains to be added") |
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.
Can you add an API changes note for this? I don't think we need to anything about it code-wise, but should document that an exception type has changed.
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.
Done.
@@ -558,9 +555,6 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True, | |||
self.set_xbound(x0, x1) | |||
|
|||
if scaley and self._autoscaleYon: | |||
yshared = self._shared_y_axes.get_siblings(self) |
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.
Are we sure that these have no side-effects?
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.
I've just gone back and traced through carefully - it does have the effect of self._shared_y_axes.clean()
, so I've replaced the block with that. Not sure if this is actually needed, but better safe than sorry!
@@ -3016,7 +3016,8 @@ def _validate_converted_limits(self, limit, convert): | |||
raise ValueError("Axis limits cannot be NaN or Inf") | |||
return converted_limit | |||
|
|||
def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw): | |||
def set_xlim(self, left=None, right=None, emit=True, auto=False, | |||
*, xmin=None, xmax=None): |
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.
Thanks @Zac-HD ! I am very happy to see this sort of work going in. We are probably going to be picking about API changes and while that may be frustrating / slow with your developer hat on, hopefully you appreciate it with your user hat on! |
Also happy and much more appreciative than frustrated - the quick reviews make it a pleasure to contribute. |
d0e746b
to
4dc70e5
Compare
If the build passes, I think I'm done (again 😉). |
4dc70e5
to
d43b0fe
Compare
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.
Sorry, still some comments. But you're almost there. 😄
We now have enough things ruled out of scope that I need a list to keep track! After this is merged, I'll open an issue for each of them:
|
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 looks good to me. Thanks!
... though I'm a little concerned that the codecov scores dropped... |
This is one of the problems with percent coverage as a metric! It's not that there are more lines without coverage - instead there are fewer lines with coverage, because e.g. all the (The only generally useful metric for coverage is "what behaviour has not been executed by my test suite?", and percentage measures can be usefully broken down into "100%" and "less than 100%" but not much further. /rant over, sorry.) |
That's not entirely true; there are some new lines without coverage, e.g., all the checks for |
The deprecation and error are new, true, and I could write trivial tests that they're emitted if someone thinks that's really necessary. I do think most of this is because dead-but-covered code was removed though. |
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 is fine by me. The new uncovered code lines are basically the code for handling the deprecated xmin/xmax attributes. I don't think it's neccessary to add tests for these. These code segments are simple enough that I trust them without a test and they will be gone in a while.
I'll still leave this open for a short time in case somebody insists on tests.
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.
Blocking just on @efiring review request from @tacaswell. Feel free to clear this once he has looked at it, I don't have any problems w/ this.
I don't think its necessary. Just hadn't thought it through enough to know if it was going to impact other PRs after this is merged. |
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.
Looks good to me!
Rebased on master to remove merge conflict from #11145; no other changes. |
Ping for @efiring - we're just waiting on your approval to merge (or comments to fix), which will unblock another sequence from me 😄 |
Ping @timhoffm @jklymak @tacaswell - this has been waiting for a review from @efiring for a full week now, and having it sit here unmerged is blocking some other refactoring I'd like to do. I'm also getting pretty sick of rebasing it on master to fix merge conflicts! Could someone contact him and ask for this to be prioritised, or just bite the bullet and merge it with only three approvals? (@jklymak's change request is really "approved, but wait for Eric") |
@efiring Should only need to comment on the deprecation of the |
Sorry to have been AWOL on this. I think I need to reconfigure my email notifications so that I automatically get only the ones that mention me or that I have weighed in on, instead of getting one for absolutely everything. |
No worries Eric! I disabled email updates entirely a while ago, and personally I've found sticking to the web interface for notifications has helped a lot. And thanks to everyone in the thread for your feedback - the result has been a much better patch 😄 |
These were originally documented and deprecated in matplotlib#11137 however in later discussion we learned: - the 'left, right' / 'top, bottom' names don't make sense in the context of non-rectangular plots - we have at least one frustrated user The original names were `xmin, xmax` but were changed to `left, right` in 9ca5db0 (pre 1.0) and the kwarg popping was added for back-compatibility.
This pull request converts
*args, **kwargs
to use named arguments in a variety of places, as suggested in #9912.There are no changes to the API; this is just using a Python-3-only syntax to make the existing API more explicit. There is a small amount of related refactoring, where I clarified a method or removed a unused variable.
CC @timhoffm, who opened the issue 😄