-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
gh-112903: Handle non-types in _BaseGenericAlias.__mro_entries__() #115191
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
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.
There are several too long lines, otherwise LGTM.
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!
So if I understand correctly, for every instance of _BaseGenericAlias
in __orig_bases__
, we iterate over all the following items in __orig_bases__
to see if any of them might like to insert Generic
into the resulting __bases__
tuple. If any of them would, we decline to insert Generic
into the __bases__
tuple now; we try to ensure Generic
appears at most once in the final __bases__
tuple, and we try to ensure it appears as late in the __bases__
tuple as possible.
Is that correct? If so, would you mind expanding a little bit in your comment on line 1139? :)
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 great overall.
A few more nitpicks to do with the tests. I also agree with all of Serhiy's remarks ;)
You could also test @JelleZijlstra's example from #112926 (review) and assert that Generic
does not appear in the __bases__
tuple. With this new PR, there's no reason why it would, but it seems like a useful invariant to assert regardless
Misc/NEWS.d/next/Library/2024-02-08-17-04-58.gh-issue-112903.SN_vUs.rst
Outdated
Show resolved
Hide resolved
Yes, and done.
Done, though note the correct behavior we are testing for is that Generic should appear in the bases tuple. |
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.
A few more nitpicks regarding comments, but this LGTM now. Thanks!
Misc/NEWS.d/next/Library/2024-02-08-17-04-58.gh-issue-112903.SN_vUs.rst
Outdated
Show resolved
Hide resolved
…N_vUs.rst Co-authored-by: Alex Waygood <[email protected]>
Any opinions on whether this should be backported? Technically it fixes a bug that was present in both 3.11 and 3.12 (with arbitrary non-types in bases), but that bug has not been encountered in the wild (that we know of). The issue that was encountered (with specifically types.GenericAlias) is only present in 3.13, since that's where types.GenericAlias was changed to no longer act like a type in I'm inclined to backport it all the way to 3.11, since it does fix a known bug, but open to suggestions otherwise. |
I was wondering about this. I agree that there's been a latent bug here for a while, so it's definitely eligible for backporting. I lean towards not backporting, though. The fact that this hasn't come up until now suggests very few people are defining |
That makes sense to me. I will not backport for now. |
I am for backporting. We haven't had any reports of this bug, possibly because people trying to do something clever with |
There are risks both ways. @JelleZijlstra, as another |
I'd lean towards no. There is always a risk that changes to typing.py break some existing use case, and it feels unlikely for people to run into this issue on their own. |
@serhiy-storchaka I will go with the preference of the typing maintainers. If we get bug reports about this against 3.11 when it is too late to backport the fix, you will retain "told you so" rights ;) |
Another potential consideration in favor of backporting is user expectations and reliance on incorrect / buggy behavior. |
@itamaro The buggy behavior is an exception when there should not be an exception, so it's not a behavior users will rely on. (On the other hand, this also means the fix itself should not break anyone's code; the concerns about backporting are about unintended side effects of the fix that we haven't realized.) Also, the bug has been present for quite a long time, probably since Python 3.7. |
…_() (python#115191) Co-authored-by: Alex Waygood <[email protected]>
The tuple of bases passed to an
__mro_entries__()
method is the original set of bases. This means that it can validly include non-type objects which define an__mro_entries__()
method themselves. So it is not safe for an__mro_entries__()
implementation to assume that all the bases passed to it are types. But_BaseGenericAlias
currently wrongly assumes this (it callsissubclass()
on them.)In this PR, we avoid calling
issubclass
on anything that is not a type.We also have to maintain the intended invariant that we only add
typing.Generic
to the MRO if nothing else in the MRO will be a subclass ofGeneric
(otherwise we will run into "can't form consistent MRO" errors.) In order to do this reliably, we must ourselves call__mro_entries__()
on non-types inbases
, to see if the replacement MRO entries include anyGeneric
subclasses.