From 00bcb11e199251c4313c74bac77083d3e98eb88a Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 7 Sep 2021 17:14:35 +0300 Subject: [PATCH 1/5] bpo-45121: Fix issue when Protocol.__init__ raise RecursionError --- Lib/test/test_typing.py | 10 ++++++++++ Lib/typing.py | 6 ++++++ .../2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst | 2 ++ 3 files changed, 18 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 847d583cdafb9a..36327bd40dbe1c 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1610,6 +1610,16 @@ class P(Protocol): with self.assertRaisesRegex(TypeError, "@runtime_checkable"): isinstance(1, P) + def test_super_call_init(self): + class P(Protocol): + x: int + + class Foo(P): + def __init__(self): + super().__init__() + + Foo() + class GenericTests(BaseTestCase): diff --git a/Lib/typing.py b/Lib/typing.py index 892f1b3506851d..c8422ce022cfa9 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1406,6 +1406,12 @@ def _no_init_or_replace_init(self, *args, **kwargs): if cls._is_protocol: raise TypeError('Protocols cannot be instantiated') + # When `_no_init_or_replace_init` called using super() there are no + # need to calculate correct `__init__` method to call. + # see bpo-45121 + if cls.__init__ is not _no_init_or_replace_init: + return + # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`. # The first instantiation of the subclass will call `_no_init_or_replace_init` which # searches for a proper new `__init__` in the MRO. The new `__init__` diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst new file mode 100644 index 00000000000000..9eef91c5d99e3c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst @@ -0,0 +1,2 @@ +Fix issue when ``Protocol.__init__`` raise ``RecursionError`` when it called +using ``super()``. Patch provided by Yurii Karabas. From 54ec43d97d22e546320bf53865f0c75cc1fdb5b3 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 7 Sep 2021 17:52:39 +0300 Subject: [PATCH 2/5] Update Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> --- .../Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst index 9eef91c5d99e3c..ce4a513d130371 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst @@ -1,2 +1,2 @@ -Fix issue when ``Protocol.__init__`` raise ``RecursionError`` when it called +Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when called using ``super()``. Patch provided by Yurii Karabas. From 79cfef0566c6c4d3ee01df8dd86d80a1dfe84bbe Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 7 Sep 2021 18:06:34 +0300 Subject: [PATCH 3/5] Add comment --- Lib/test/test_typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 36327bd40dbe1c..fa49b90886c302 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1618,7 +1618,7 @@ class Foo(P): def __init__(self): super().__init__() - Foo() + Foo() # Previously triggered RecursionError class GenericTests(BaseTestCase): From 77d9c607b185bbc18b069518fd4d6c8204631e57 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 7 Sep 2021 22:54:06 +0300 Subject: [PATCH 4/5] Update comments --- Lib/typing.py | 5 ++--- .../2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/typing.py b/Lib/typing.py index c8422ce022cfa9..e29d699283dfec 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1406,9 +1406,8 @@ def _no_init_or_replace_init(self, *args, **kwargs): if cls._is_protocol: raise TypeError('Protocols cannot be instantiated') - # When `_no_init_or_replace_init` called using super() there are no - # need to calculate correct `__init__` method to call. - # see bpo-45121 + # Already using a custom `__init__`. No need to calculate correct + # `__init__` to call. This can lead to RecursionError. See bpo-45121. if cls.__init__ is not _no_init_or_replace_init: return diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst index ce4a513d130371..8959dafcfd6586 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst @@ -1,2 +1,2 @@ -Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when called -using ``super()``. Patch provided by Yurii Karabas. +Fix issue when ``Protocol.__init__`` raises ``RecursionError`` when it +called directly or via ``super()``. Patch provided by Yurii Karabas. From 9eae697b5385058c4ad2e145e8b7f6e21ca64c3b Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 8 Sep 2021 17:47:08 +0800 Subject: [PATCH 5/5] Fix news grammar --- .../Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst index 8959dafcfd6586..19eb3314125167 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst @@ -1,2 +1,2 @@ -Fix issue when ``Protocol.__init__`` raises ``RecursionError`` when it +Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when it's called directly or via ``super()``. Patch provided by Yurii Karabas.