gh-149828: make Protocol compatible with Enum instantiation#149830
gh-149828: make Protocol compatible with Enum instantiation#149830randolf-scholz wants to merge 2 commits into
Conversation
sobolevn
left a comment
There was a problem hiding this comment.
Looks fine to me! Let's wait for @ethanfurman :)
|
🤖 New build scheduled with the buildbot fleet by @AlexWaygood for commit 5ab82ba 🤖 Results will be shown at: https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F149830%2Fmerge If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again. |
|
|
||
| class ProtoEnum(Example, Enum, metaclass=CompatEnumType): | ||
| __qualname__ = 'ProtoEnum' # needed for pickle protocol 4 | ||
| impl = Impl() |
There was a problem hiding this comment.
I'm not sure the ()'s are needed -- can someone test it both ways and verify which version results in the expected enum member and value?
impl = Impl vs impl = Impl()
There was a problem hiding this comment.
Without the () the enum member would be the class Impl, not an instance of the class.
>>> from enum import Enum, EnumType
... from typing import Protocol
...
... class Example(Protocol):
... def method(self) -> None: ...
...
... class Impl(Example):
... def method(self) -> None: ...
...
... class CompatEnumType(type(Protocol), EnumType): ...
...
... class ProtoEnumA(Example, Enum, metaclass=CompatEnumType):
... impl = Impl
...
... class ProtoEnumB(Example, Enum, metaclass=CompatEnumType):
... impl = Impl()
...
... print(repr(ProtoEnumA.impl))
... print(repr(ProtoEnumB.impl))
...
<ProtoEnumA.impl: <class '__main__.Impl'>>
<ProtoEnumB.impl: <__main__.Impl object at 0x74e096376660>>|
Had to update the PR title since I copy-pasted the wrong issue number. The |
Fixes #149828
This was surprisingly easy, the issue is that with enums,
__init_subclass__is only called afterEnumType.__new__is finished.However, when subclassing from
typing.Protocol,_is_protocolis only set during__init_subclass__. The fix is to replace the lookup of_is_protocolinside_no_init_or_replace_initwith the actual check.A more robust solution would probably be for
_is_protocolto be a lazy class property, but that would be a larger change and class-properties are not natively supported...cc @sobolevn