mirror of
https://github.com/python/cpython.git
synced 2026-01-03 22:12:27 +00:00
[3.11] gh-103171: Revert undocumented behaviour change for runtime-checkable protocols decorated with @final (#105445)
This commit is contained in:
parent
2ffeb0ecc7
commit
18e9fd80d9
3 changed files with 70 additions and 1 deletions
|
|
@ -3349,6 +3349,71 @@ def __init__(self):
|
|||
|
||||
Foo() # Previously triggered RecursionError
|
||||
|
||||
def test_empty_protocol_decorated_with_final(self):
|
||||
@final
|
||||
@runtime_checkable
|
||||
class EmptyProtocol(Protocol): ...
|
||||
|
||||
self.assertIsSubclass(object, EmptyProtocol)
|
||||
self.assertIsInstance(object(), EmptyProtocol)
|
||||
|
||||
def test_protocol_decorated_with_final_callable_members(self):
|
||||
@final
|
||||
@runtime_checkable
|
||||
class ProtocolWithMethod(Protocol):
|
||||
def startswith(self, string: str) -> bool: ...
|
||||
|
||||
self.assertIsSubclass(str, ProtocolWithMethod)
|
||||
self.assertNotIsSubclass(int, ProtocolWithMethod)
|
||||
self.assertIsInstance('foo', ProtocolWithMethod)
|
||||
self.assertNotIsInstance(42, ProtocolWithMethod)
|
||||
|
||||
def test_protocol_decorated_with_final_noncallable_members(self):
|
||||
@final
|
||||
@runtime_checkable
|
||||
class ProtocolWithNonCallableMember(Protocol):
|
||||
x: int
|
||||
|
||||
class Foo:
|
||||
x = 42
|
||||
|
||||
only_callable_members_please = (
|
||||
r"Protocols with non-method members don't support issubclass()"
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, only_callable_members_please):
|
||||
issubclass(Foo, ProtocolWithNonCallableMember)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, only_callable_members_please):
|
||||
issubclass(int, ProtocolWithNonCallableMember)
|
||||
|
||||
self.assertIsInstance(Foo(), ProtocolWithNonCallableMember)
|
||||
self.assertNotIsInstance(42, ProtocolWithNonCallableMember)
|
||||
|
||||
def test_protocol_decorated_with_final_mixed_members(self):
|
||||
@final
|
||||
@runtime_checkable
|
||||
class ProtocolWithMixedMembers(Protocol):
|
||||
x: int
|
||||
def method(self) -> None: ...
|
||||
|
||||
class Foo:
|
||||
x = 42
|
||||
def method(self) -> None: ...
|
||||
|
||||
only_callable_members_please = (
|
||||
r"Protocols with non-method members don't support issubclass()"
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, only_callable_members_please):
|
||||
issubclass(Foo, ProtocolWithMixedMembers)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, only_callable_members_please):
|
||||
issubclass(int, ProtocolWithMixedMembers)
|
||||
|
||||
self.assertIsInstance(Foo(), ProtocolWithMixedMembers)
|
||||
self.assertNotIsInstance(42, ProtocolWithMixedMembers)
|
||||
|
||||
|
||||
class GenericTests(BaseTestCase):
|
||||
|
||||
|
|
|
|||
|
|
@ -1883,7 +1883,7 @@ class _TypingEllipsis:
|
|||
|
||||
|
||||
_TYPING_INTERNALS = ['__parameters__', '__orig_bases__', '__orig_class__',
|
||||
'_is_protocol', '_is_runtime_protocol']
|
||||
'_is_protocol', '_is_runtime_protocol', '__final__']
|
||||
|
||||
_SPECIAL_NAMES = ['__abstractmethods__', '__annotations__', '__dict__', '__doc__',
|
||||
'__init__', '__module__', '__new__', '__slots__',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
Revert undocumented behaviour change with runtime-checkable protocols
|
||||
decorated with :func:`typing.final` in Python 3.11. The behaviour change had
|
||||
meant that objects would not be considered instances of these protocols at
|
||||
runtime unless they had a ``__final__`` attribute. Patch by Alex Waygood.
|
||||
Loading…
Add table
Add a link
Reference in a new issue