Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Change return type of ion and ioff to fix unbound variable errors with Pyright #27667

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

Merged
merged 4 commits into from
Feb 23, 2024

Conversation

FeldrinH
Copy link
Contributor

@FeldrinH FeldrinH commented Jan 18, 2024

PR summary

Closes #27659.

By changing the return type annotation to AbstractContextManager, Pyright considers the context managers returned by ion and ioff as not supressing errors and does not give warnings about possibly unbound variables after the with block.

This change has absolutely no effect on runtime behavior.

It might cause type errors for users who store the return value of ion or ioff and attempt to call ExitStack-specific methods on it. However, the runtime behavior of such usage has not changed and the number of users who actually do this should be very small, given that the documentation explicitly forbids "storing or accessing" the returned context manager.

PR checklist

PS: I couldn't figure out from the developer documentation if changing a type hint constitutes an API change. Let me know if I need to add something to release notes.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide

We strive to be a welcoming and open project. Please follow our Code of Conduct.

@ksunden
Copy link
Member

ksunden commented Jan 18, 2024

I'm confused by how this changes the behavior of pyright:

reveal_type(AbstractContextManager.__exit__)

Gives:

Type of "AbstractContextManager.__exit__" is "(self: AbstractContextManager[Unknown], __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None, /) -> (bool | None)"

Which still has the bool | None return type, which I thought was the problem. (I'll note that the return type on ExitStack is just bool)

Now... emperically, it does not error, I'm just confused why... and worry that it is actually a bug (most likely related to the union return type?) that it does not (and thus will have to do the more complicated fix originally proposed or something like it).

@FeldrinH
Copy link
Contributor Author

FeldrinH commented Jan 18, 2024

Which still has the bool | None return type, which I thought was the problem. (I'll note that the return type on ExitStack is just bool)

Now... emperically, it does not error, I'm just confused why... and worry that it is actually a bug (most likely related to the union return type?) that it does not (and thus will have to do the more complicated fix originally proposed or something like it).

Pyright currently assumes that errors may be supressed if the return type is either bool or Literal[True], which is why bool | None does not trigger the assumption. I think your concern about this being a bug/unintended quirk in Pyright is valid. I will try to check this with a Pyright maintainer.

As stated in microsoft/pyright#7009 (comment), the typing rules w.r.t. context managers supressing exceptions have not been formalized (yet), so there is definitely a possibility that at some point in the future the rules change and this fix will no longer work.

@FeldrinH
Copy link
Contributor Author

Pyright currently assumes that errors may be supressed if the return type is either bool or Literal[True], which is why bool | None does not trigger the assumption. I think your concern about this being a bug/unintended quirk in Pyright is valid. I will try to check this with a Pyright maintainer.

FWIW I checked mypy and mypy also has the same behavior (it assumes errors may be supressed with __exit__ -> bool, but assumes errors will not be supressed with __exit__ -> bool | None).

@FeldrinH
Copy link
Contributor Author

FeldrinH commented Jan 18, 2024

According to a Pyright maintainer (see microsoft/pyright#7009 (comment)), the current logic for these checks originates from mypy, so we would have to go to mypy maintainers to find out if this is deliberate. I think at this point the pragmatic thing to do is to ship this fix and revisit this if/when things break. I doubt things will change much before the rules of how static analyzers should deal with context managers supressing errors are formalized (see microsoft/pyright#7009 (comment)).

@FeldrinH
Copy link
Contributor Author

This pull request has been open for a while now. Is there anything else I should do to help get this merged, or is it simply a question of waiting?

@QuLogic QuLogic added this to the v3.9.0 milestone Feb 23, 2024
@QuLogic QuLogic merged commit b6f7a68 into matplotlib:main Feb 23, 2024
@QuLogic
Copy link
Member

QuLogic commented Feb 23, 2024

Thanks @FeldrinH! Congratulations on your first PR to Matplotlib 🎉 We hope to hear from you again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[MNT]: Improve return type of ioff and ion to improve Pyright analysis of bound variables
4 participants