Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime-checkable protocols are broken on py312 (the sequel) #104935

Closed
AlexWaygood opened this issue May 25, 2023 · 0 comments
Closed

Runtime-checkable protocols are broken on py312 (the sequel) #104935

AlexWaygood opened this issue May 25, 2023 · 0 comments
Assignees
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes topic-typing type-bug An unexpected behavior, bug, or error

Comments

@AlexWaygood
Copy link
Member

AlexWaygood commented May 25, 2023

Bug report

On 3.8-3.11, all subclasses of typing.Generic were guaranteed to have an _is_protocol class attribute, which is used as an internal marker:

_is_protocol = False

Two places in typing.py rely on all subclasses of Generic having this marker:

cpython/Lib/typing.py

Lines 1895 to 1897 in dbc8216

if (isinstance(annotations, collections.abc.Mapping) and
attr in annotations and
issubclass(other, Generic) and other._is_protocol):

cpython/Lib/typing.py

Lines 2062 to 2064 in dbc8216

if not issubclass(cls, Generic) or not cls._is_protocol:
raise TypeError('@runtime_checkable can be only applied to protocol classes,'
' got %r' % cls)

However, on Python 3.12 (due to the implementation of PEP-695), subclasses of Generic no longer have this marker:

>>> class Foo[T]: ...
...
>>> Foo._is_protocol
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Foo' has no attribute '_is_protocol'

This leads to AttributeError being raised in two situations where it shouldn't be:

Python 3.13.0a0 (heads/main:1080c4386d, May 25 2023, 13:11:38) [MSC v.1932 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from typing import Protocol, runtime_checkable
>>> @runtime_checkable
... class Foo[T]: ...
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 2062, in runtime_checkable
    if not issubclass(cls, Generic) or not cls._is_protocol:
                                           ^^^^^^^^^^^^^^^^
AttributeError: type object 'Foo' has no attribute '_is_protocol'
>>> @runtime_checkable
... class HasX(Protocol):
...     x: int
...
>>> class Bar[T]:
...     x: T
...     def __init__(self, x):
...         self.x = x
...
>>> isinstance(Bar(42), HasX)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1810, in __instancecheck__
    if super().__instancecheck__(instance):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\coding\cpython\Lib\abc.py", line 119, in __instancecheck__
    return _abc_instancecheck(cls, instance)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1794, in __subclasscheck__
    return super().__subclasscheck__(other)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\coding\cpython\Lib\abc.py", line 123, in __subclasscheck__
    return _abc_subclasscheck(cls, subclass)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1897, in _proto_hook
    issubclass(other, Generic) and other._is_protocol):
                                   ^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Bar' has no attribute '_is_protocol'

Cc. @JelleZijlstra for PEP-695

Linked PRs

@AlexWaygood AlexWaygood added type-bug An unexpected behavior, bug, or error topic-typing 3.12 bugs and security fixes 3.13 bugs and security fixes labels May 25, 2023
@JelleZijlstra JelleZijlstra self-assigned this May 25, 2023
JelleZijlstra added a commit to JelleZijlstra/cpython that referenced this issue May 25, 2023
AlexWaygood added a commit that referenced this issue May 25, 2023
…`Generic` (#104939)

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue May 25, 2023
…` and `Generic` (pythonGH-104939)

---------

(cherry picked from commit 2b7027d)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue May 25, 2023
…` and `Generic` (pythonGH-104939)

---------

(cherry picked from commit 2b7027d)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
AlexWaygood added a commit that referenced this issue May 25, 2023
…e` and `Generic` (GH-104939) (#104941)

gh-104935: typing: Fix interactions between `@runtime_checkable` and `Generic` (GH-104939)

---------

(cherry picked from commit 2b7027d)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes topic-typing type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants