Closed
Description
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:
Line 1790 in 76873ca
Two places in typing.py
rely on all subclasses of Generic
having this marker:
Lines 1895 to 1897 in dbc8216
Lines 2062 to 2064 in dbc8216
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