8000 bpo-44807: Allow Protocol classes to define __init__ (GH-31628) · python/cpython@5f2abae · GitHub
[go: up one dir, main page]

Skip to content

Commit 5f2abae

Browse files
bpo-44807: Allow Protocol classes to define __init__ (GH-31628)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent b0b836b commit 5f2abae

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

Lib/test/test_typing.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,32 @@ class CG(PG[T]): pass
15981598
with self.assertRaises(TypeError):
15991599
CG[int](42)
16001600

1601+
def test_protocol_defining_init_does_not_get_overridden(self):
1602+
# check that P.__init__ doesn't get clobbered
1603+
# see https://bugs.python.org/issue44807
1604+
1605+
class P(Protocol):
1606+
x: int
1607+
def __init__(self, x: int) -> None:
1608+
self.x = x
1609+
class C: pass
1610+
1611+
c = C()
1612+
P.__init__(c, 1)
1613+
self.assertEqual(c.x, 1)
1614+
1615+
def test_concrete_class_inheriting_init_from_protocol(self):
1616+
class P(Protocol):
1617+
x: int
1618+
def __init__(self, x: int) -> None:
1619+
self.x = x
1620+
1621+
class C(P): pass
1622+
1623+
c = C(1)
1624+
self.assertIsInstance(c, C)
1625+
self.assertEqual(c.x, 1)
1626+
16011627
def test_cannot_instantiate_abstract(self):
16021628
@runtime_checkable
16031629
class P(Protocol):

Lib/typing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1997,7 +1997,8 @@ def _proto_hook(other):
19971997
issubclass(base, Generic) and base._is_protocol):
19981998
raise TypeError('Protocols can only inherit from other'
19991999
' protocols, got %r' % base)
2000-
cls.__init__ = _no_init_or_replace_init
2000+
if cls.__init__ is Protocol.__init__:
2001+
cls.__init__ = _no_init_or_replace_init
20012002

20022003

20032004
class _AnnotatedAlias(_GenericAlias, _root=True):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:class:`typing.Protocol` no longer silently replaces :meth:`__init__` methods defined on subclasses. Patch by Adrian Garcia Badaracco.

0 commit comments

Comments
 (0)
0