bpo-44807: Allow Protocol classes to define __init__ (GH-31628)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
Adrian Garcia Badaracco 2022-04-11 09:51:25 -05:00 committed by GitHub
parent b0b836b20c
commit 5f2abae61e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 1 deletions

View File

@ -1598,6 +1598,32 @@ class ProtocolTests(BaseTestCase):
with self.assertRaises(TypeError):
CG[int](42)
def test_protocol_defining_init_does_not_get_overridden(self):
# check that P.__init__ doesn't get clobbered
# see https://bugs.python.org/issue44807
class P(Protocol):
x: int
def __init__(self, x: int) -> None:
self.x = x
class C: pass
c = C()
P.__init__(c, 1)
self.assertEqual(c.x, 1)
def test_concrete_class_inheriting_init_from_protocol(self):
class P(Protocol):
x: int
def __init__(self, x: int) -> None:
self.x = x
class C(P): pass
c = C(1)
self.assertIsInstance(c, C)
self.assertEqual(c.x, 1)
def test_cannot_instantiate_abstract(self):
@runtime_checkable
class P(Protocol):

View File

@ -1997,7 +1997,8 @@ class Protocol(Generic, metaclass=_ProtocolMeta):
issubclass(base, Generic) and base._is_protocol):
raise TypeError('Protocols can only inherit from other'
' protocols, got %r' % base)
cls.__init__ = _no_init_or_replace_init
if cls.__init__ is Protocol.__init__:
cls.__init__ = _no_init_or_replace_init
class _AnnotatedAlias(_GenericAlias, _root=True):

View File

@ -0,0 +1 @@
:class:`typing.Protocol` no longer silently replaces :meth:`__init__` methods defined on subclasses. Patch by Adrian Garcia Badaracco.