-
-
Notifications
You must be signed in to change notification settings - Fork 7.5k
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
#24050 No error was thrown even number of handles mismatched labels #24061
Conversation
…d labels user named haferburg. used plot method bunch of times and then called legend. with less handles than labels. program didn't raise any error. now it should raise Value error
Your PR would need a test that checks that the exception is raised. This should probably go into https://github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/tests/test_legend.py Here is a similar test to see how to check for an exception: matplotlib/lib/matplotlib/tests/test_legend.py Lines 255 to 260 in fd5cf5c
(Also, note that #24063 solves the same issue.) |
@oscargus is ValueError the right type of error to raise? |
So raising here is an API change. Are we ok raising without deprecating mismatched list lengths? |
@@ -1260,6 +1260,8 @@ def _parse_legend_args(axs, *args, handles=None, labels=None, **kwargs): | |||
elif len(args) >= 2: | |||
handles, labels = args[:2] | |||
extra_args = args[2:] | |||
elif len(handles)!= len(labels): |
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 condition will never be evaluated because the one of the other conditionals in this if/elif chain will always be True
first.
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 I see that now.
An entirely new block would do the trick or we should rethink like you said. This issue was tagged as good first issue so and solution seemed pretty straightforward at the time.will analyslze along your directives
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 an entirely new block should be enough. This conditional statement (L1222:L1262) is to assign values to labels
and handles
. Checking the validity of handles
and labels
should come in a new conditional statement after that.
There is also an explicit bit of code on L1226 that ensures that if handles and labels are passed as keywords they are trimmed to the same length. Given that we currently are positively discarding excess labels or handles, we will need to warn for one version before we start to raise. @tusharkulkarni008 Can you look back at the git-blame of when L1226 came in to see if we had any discussion about it at the time? We may want to change our minds about supporting un-equal numbers of handles/labels but we should understand why we used to support it and make sure we no longer agree with those reasons. While there are some things in Matplotlib that are they way they are because that was the first way someone thought to do something, most things in Matplotlib are there because someone at one point had a good reason for wanting it that way. It is important to understand why things are they way they are before we change them to avoid unintended side effects. |
Will do |
Also, currently we accept iterables, so you have to handle the case that Please add tests as well. |
Can probably do this with from itertools import count
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
for j in range(5):
ax.plot(np.arange(5) + j)
ax.legend(ax.lines, (f'line {j}' for j in count())) works. |
IMHO the simplest solution is the following:
|
I wonder if a warning that an input is being truncated would be enough for the user who requested an exception? I think that would avoid worries about api changes, and any user who wants to pass e.g. a generator can just suppress the warning if they wish. |
I think this is not easy in this case as the code is old and has moved around. The code to truncate when both handles and labels were passed was added within a bugfix to ensure passing both in was handled at all. I can’t see any discussion of the truncation there but my guess is to make it consistent with the case when only labels are passed in. That code can be traced all the way back to here. The commit that produced that appears to be where Matplotlib moved from subversion to git. |
When the svn -> git conversion was done we lost like the first 6 commits (the first commit we have has The original svn commits can be accessed at https://sourceforge.net/p/matplotlib/code/1 etc, but I think it is impossible to graft those back into the tree in a useful way at this point. It also looks like there was a CVS -> SVN transition before the SVN -> git transition. I think the combination of @timhoffm and @rcomer 's comments is best. We should warn if labels and handles have different lengths only if they have lengths and leave it as just a warning rather than a deprecation warning. |
@@ -1260,6 +1260,8 @@ def _parse_legend_args(axs, *args, handles=None, labels=None, **kwargs): | |||
elif len(args) >= 2: | |||
handles, labels = args[:2] | |||
extra_args = args[2:] | |||
elif len(handles)!= len(labels): |
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 an entirely new block should be enough. This conditional statement (L1222:L1262) is to assign values to labels
and handles
. Checking the validity of handles
and labels
should come in a new conditional statement after that.
@@ -1260,6 +1260,8 @@ def _parse_legend_args(axs, *args, handles=None, labels=None, **kwargs): | |||
elif len(args) >= 2: | |||
handles, labels = args[:2] | |||
extra_args = args[2:] | |||
elif len(handles)!= len(labels): | |||
raise ValueError("fewer handles than labels or vice versa") |
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.
It would be helpful to provide a better error message. Maybe include the length of handles and labels to make it easier for the developer to understand what they did wrong.
raise ValueError("fewer handles than labels or vice versa") | |
raise ValueError(f"Mismatched number of handles and labels. len(handles)={len(handles)} and len(labels)={len(lables)}.") |
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 didn't mean to set myself as a reviewer. I just wanted to give my comments to @tusharkulkarni008 since it is their first PR ever.
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.
@aqeelat the developer guide encourages you to review 🙂
https://matplotlib.org/stable/devel/triage.html#working-on-prs-to-help-review
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 didn't mean to set myself as a reviewer. I just wanted to give my comments to @tusharkulkarni008 since it is their first PR ever.
Yes @aqeelat this is my first PR ever and earlier in this conversation other senior member pointed out some important in points in very detailed explanation. Since then I am observing PRs other people make to gain some footing to make more meaningful PRs.
Certainly your error message is more consistent with raised issue
I converted this to draft and moved it to the 3.8 milestone. Re-reading the comments I think the work that needs to be done is:
|
@tusharkulkarni008 Are you still interested in working on this? If so can we help you to move this forward? |
Now replaced by #27004 |
user named haferburg. used plot method bunch of times and then called legend. with less handles than labels. program didn't raise any error. now it should raise Value error
PR Summary
PR Checklist
Tests and Styling
pytest
passes).flake8-docstrings
and runflake8 --docstring-convention=all
).Documentation
doc/users/next_whats_new/
(follow instructions in README.rst there).doc/api/next_api_changes/
(follow instructions in README.rst there).