[Python-checkins] bpo-44807: Allow Protocol classes to define __init__ (GH-31628)
JelleZijlstra
webhook-mailer at python.org
Mon Apr 11 10:51:37 EDT 2022
https://github.com/python/cpython/commit/5f2abae61ec69264b835dcabe2cdabe57b9a990e
commit: 5f2abae61ec69264b835dcabe2cdabe57b9a990e
branch: main
author: Adrian Garcia Badaracco <1755071+adriangb at users.noreply.github.com>
committer: JelleZijlstra <jelle.zijlstra at gmail.com>
date: 2022-04-11T07:51:25-07:00
summary:
bpo-44807: Allow Protocol classes to define __init__ (GH-31628)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra at gmail.com>
files:
A Misc/NEWS.d/next/Library/2022-03-02-04-25-58.bpo-44807.gHNC9J.rst
M Lib/test/test_typing.py
M Lib/typing.py
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index e09f8aa3fb849..b884f7b2cced3 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -1598,6 +1598,32 @@ class CG(PG[T]): pass
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):
diff --git a/Lib/typing.py b/Lib/typing.py
index 26c6b8c278b73..ec8cbbd8b20a3 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1997,7 +1997,8 @@ def _proto_hook(other):
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):
diff --git a/Misc/NEWS.d/next/Library/2022-03-02-04-25-58.bpo-44807.gHNC9J.rst b/Misc/NEWS.d/next/Library/2022-03-02-04-25-58.bpo-44807.gHNC9J.rst
new file mode 100644
index 0000000000000..4757d3420caf8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-02-04-25-58.bpo-44807.gHNC9J.rst
@@ -0,0 +1 @@
+:class:`typing.Protocol` no longer silently replaces :meth:`__init__` methods defined on subclasses. Patch by Adrian Garcia Badaracco.
More information about the Python-checkins
mailing list