This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Created on 2021-09-01 21:06 by julianfortune, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
test.py icgood, 2021-09-11 21:01 Example of another issue with Protocol subclassing
Pull Requests
URL Status Linked Edit
PR 28121 merged uriyyo, 2021-09-02 09:45
PR 28131 merged miss-islington, 2021-09-02 16:17
PR 28132 merged miss-islington, 2021-09-02 16:17
Messages (7)
msg400868 - (view) Author: Julian Fortune (julianfortune) Date: 2021-09-01 21:06
I believe [`bpo-44806: Fix __init__ in subclasses of protocols`](https://github.com/python/cpython/pull/27545) has caused a regression when using a Dataclass. In Python `3.9.7`, a `dataclass` that inherits from a subclass of `typing.Protocol` (i.e., a user-defined protocol), does not have the correct `__init__`. ### Demonstration ```python from dataclasses import dataclass from typing import Protocol class P(Protocol): pass @dataclass class B(P): value: str print(B("test")) ``` In `3.9.7`: ```shell Traceback (most recent call last): File "test.py", line 11, in <module> print(B("test")) TypeError: B() takes no arguments ``` In `3.9.6`: ```shell B(value='test') ``` ### Affected Projects - [dbt](https://github.com/dbt-labs/dbt/issues/3843)
msg400936 - (view) Author: Łukasz Langa (lukasz.langa) * (Python committer) Date: 2021-09-02 16:17
 New changeset 0635e201beaf52373f776ff32702795e38f43ae3 by Yurii Karabas in branch 'main': bpo-45081: Fix __init__ method generation when inheriting from Protocol (GH-28121) https://github.com/python/cpython/commit/0635e201beaf52373f776ff32702795e38f43ae3 
msg400939 - (view) Author: Łukasz Langa (lukasz.langa) * (Python committer) Date: 2021-09-02 17:01
 New changeset 98eb40828af97760badfa7b8ff84bd4f7a079839 by Miss Islington (bot) in branch '3.9': bpo-45081: Fix __init__ method generation when inheriting from Protocol (GH-28121) (GH-28132) https://github.com/python/cpython/commit/98eb40828af97760badfa7b8ff84bd4f7a079839 
msg400979 - (view) Author: miss-islington (miss-islington) Date: 2021-09-03 06:27
 New changeset 79e9f5a58427c73dc546cb571819d50defe2e14f by Miss Islington (bot) in branch '3.10': bpo-45081: Fix __init__ method generation when inheriting from Protocol (GH-28121) https://github.com/python/cpython/commit/79e9f5a58427c73dc546cb571819d50defe2e14f 
msg401647 - (view) Author: Ian Good (icgood) * Date: 2021-09-11 21:01
I believe this was a deeper issue that affected all classes inheriting Protocol, causing a TypeError on even the most basic case (see attached): Traceback (most recent call last): File "/.../test.py", line 14, in <module> MyClass() File "/.../test.py", line 11, in __init__ super().__init__() File "/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 1083, in _no_init raise TypeError('Protocols cannot be instantiated') TypeError: Protocols cannot be instantiated This was a new regression in 3.9.7 and seems to be resolved by this fix. The desired behavior should be supported according to PEP 544: https://www.python.org/dev/peps/pep-0544/#explicitly-declaring-implementation
msg401671 - (view) Author: Julian Fortune (julianfortune) Date: 2021-09-12 20:42
Ian, `MyProtocol` does not provide an `__init__()`, and thus ``` super().__init__() ``` is calling the `__init__()` from `Protocol`. This results in the `TypeError`. Simply remove `super().__init__()` to resolve your issue. This behavior was changed in https://github.com/python/cpython/pull/27545 (see `Lib/typing.py:1384`); I don't see what you are reporting as a regression, I see it as correct behavior that I would expect. Apologies if you feel differently. Cheers, Julian
msg401672 - (view) Author: Ian Good (icgood) * Date: 2021-09-12 21:38
Julian, That is certainly a workaround, however the behavior you are describing is inconsistent with PEP-544 in both word and intention. From the PEP: > To explicitly declare that a certain class implements a given protocol, it can be used as a regular base class. It further describes the semantics of inheriting as "unchanged" from a "regular base class". If the semantics are "unchanged" then it should follow that super().__init__() would pass through the protocol to the object.__init__, just like a "regular base class" would if it does not override __init__. Furthermore, the intention of inheriting a Protocol as described in the PEP: > Static analysis tools are expected to automatically detect that a class implements a given protocol. So while it's possible to subclass a protocol explicitly, it's not necessary to do so for the sake of type-checking. The purpose of adding a Protocol sub-class as an explicit base class is thus only to improve static analysis, it should *not* to modify the runtime semantics. Consider the case where a package maintainer wants to enhance the flexibility of their types by transitioning from using an ABC to using structural sub-typing. That simple typing change would be a breaking change to the package consumers, who must now remove a super().__init__() call. Ian
History
Date User Action Args
2022-04-11 14:59:49adminsetgithub: 89244
2021-09-12 21:38:03icgoodsetmessages: + msg401672
2021-09-12 20:42:53julianfortunesetmessages: + msg401671
2021-09-11 21:01:11icgoodsetfiles: + test.py
nosy: + icgood
messages: + msg401647

2021-09-03 06:28:16lukasz.langasetversions: + Python 3.10, Python 3.11
2021-09-03 06:27:22miss-islingtonsetmessages: + msg400979
2021-09-02 18:46:32julianfortunesetstatus: open -> closed
stage: patch review -> resolved
2021-09-02 17:01:40lukasz.langasetmessages: + msg400939
2021-09-02 16:17:27miss-islingtonsetpull_requests: + pull_request26570
2021-09-02 16:17:23miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request26569
2021-09-02 16:17:21lukasz.langasetmessages: + msg400936
2021-09-02 11:26:13kjsetnosy: + lukasz.langa, serhiy.storchaka, kj
2021-09-02 09:45:45uriyyosetkeywords: + patch
nosy: + uriyyo

pull_requests: + pull_request26562
stage: patch review
2021-09-02 06:17:56shriksetnosy: + shrik
2021-09-01 23:46:54edgarrmondragonsetnosy: + edgarrmondragon
2021-09-01 22:46:46eric.smithsetnosy: + eric.smith
2021-09-01 21:06:11julianfortunecreate