Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

#24050 No error was thrown even number of handles mismatched labels#24061

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed

Conversation

tusharkulkarni008
Copy link

@tusharkulkarni008tusharkulkarni008 commentedOct 1, 2022
edited
Loading

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

  • Has pytest style unit tests (andpytest passes).
  • IsFlake 8 compliant (installflake8-docstrings and runflake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry indoc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented indoc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs shouldbuild without error).

…d labelsuser 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
@oscargus
Copy link
Member

Your PR would need a test that checks that the exception is raised. This should probably go intohttps://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:

deftest_legend_positional_handles_only(self):
lines=plt.plot(range(10))
withpytest.raises(TypeError,match='but found an Artist'):
# a single arg is interpreted as labels
# it's a common error to just pass handles
plt.legend(lines)

(Also, note that#24063 solves the same issue.)

tusharkulkarni008 reacted with thumbs up emoji

@tusharkulkarni008
Copy link
Author

@oscargus is ValueError the right type of error to raise?
I have never written tests before I will analyse the suggested tests and write accordingly

@jklymak
Copy link
Member

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):
Copy link
Member

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 beTrue first.

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

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 tolabels andhandles. Checking the validity ofhandles andlabels should come in a new conditional statement after that.

@tacaswell
Copy link
Member

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.

tusharkulkarni008 reacted with thumbs up emoji

@tacaswelltacaswell added this to thev3.7.0 milestoneOct 1, 2022
@tusharkulkarni008
Copy link
Author

Will do

@timhoffm
Copy link
Member

timhoffm commentedOct 2, 2022
edited
Loading

Also, currently we accept iterables, so you have to handle the case thathandles and/orlabels don’t support__len__.

Please add tests as well.

@tacaswell
Copy link
Member

so you have to handle the case that handles and/or labels don’t supportlen.

Can probably do this withzip_longest + aobject() sentinel + checking to make sure we do not see the sentinel. That said, if we take iterators there may some usage where the labels are an infinite generators for the labels. Currently

fromitertoolsimportcountimportmatplotlib.pyplotaspltimportnumpyasnpfig,ax=plt.subplots()forjinrange(5):ax.plot(np.arange(5)+j)ax.legend(ax.lines, (f'line{j}'forjincount()))

works.

@timhoffm
Copy link
Member

so you have to handle the case that handles and/or labels don’t supportlen.

Can probably do this withzip_longest + aobject() sentinel + checking to make sure we do not see the sentinel. That said, if we take iterators there may some usage where the labels are an infinite generators for the labels. Currently

IMHO the simplest solution is the following:

  • Postpone the len-check to the very end of the function, wherehandles andlabels variables are resolved. That way, we cover all sources of thehandles andlabels.
  • Wrap the len-check in atry-except block, and do nothing if you cannot determine the length. We need to continue accepting iterators for compatibility, but we don't need to jump arbitrary complex hoops to try and find out how may elements they will give only to be able to give a warning.

@rcomer
Copy link
Member

rcomer commentedOct 3, 2022
edited
Loading

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.

timhoffm and aqeelat reacted with thumbs up emoji

@rcomer
Copy link
Member

look back at the git-blame

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 bugfixto 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 tohere. The commit that produced that appears to be where Matplotlib moved from subversion to git.

tacaswell reacted with thumbs up emoji

@tacaswell
Copy link
Member

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 hassvn path=/trunk/matplotlib/; revision=7 in it). My current theory is that because svn only gives diffs we see a whole lot of commits adding docs and examples that claim to fix bugs with no code changes. That commit is one where all the files got moved so there was a huge diff and we finally start to see the library.

The original svn commits can be accessed athttps://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.

rcomer and timhoffm reacted with thumbs up emoji

@@ -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):

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 tolabels andhandles. Checking the validity ofhandles andlabels 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")

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.

Suggested change
raiseValueError("fewerhandlesthan labels or vice versa")
raiseValueError(f"Mismatched number ofhandlesand labels. len(handles)={len(handles)} and len(labels)={len(lables)}.")

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.

tusharkulkarni008 reacted with thumbs up emoji
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

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

@tacaswelltacaswell marked this pull request as draftDecember 16, 2022 19:15
@tacaswelltacaswell modified the milestones:v3.7.0,v3.8.0Dec 16, 2022
@tacaswell
Copy link
Member

tacaswell commentedDec 16, 2022
edited by timhoffm
Loading

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:

  • only check the length if the inputs actually have length
  • only warn because this previously "worked" and we do not want to suddenly start raising exceptions in user code that was running
  • add tests of all of the behavior
melissawm and timhoffm reacted with thumbs up emoji

@timhoffm
Copy link
Member

@tusharkulkarni008 Are you still interested in working on this? If so can we help you to move this forward?

@rcomer
Copy link
Member

Now replaced by#27004

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@tacaswelltacaswelltacaswell left review comments

@rcomerrcomerrcomer left review comments

@aqeelataqeelatAwaiting requested review from aqeelat

Assignees
No one assigned
Projects
Milestone
v3.9.0
Development

Successfully merging this pull request may close these issues.

No error message in matplotlib.axes.Axes.legend() if there are more labels than handles
9 participants
@tusharkulkarni008@oscargus@jklymak@tacaswell@timhoffm@rcomer@aqeelat@QuLogic@ksunden

[8]ページ先頭

©2009-2025 Movatter.jp