Skip to content

Typing: undocumented behaviour change for protocols decorated with @final and @runtime_checkable in 3.11 #103171

Closed
@AlexWaygood

Description

@AlexWaygood

Python 3.11 introduced an undocumented behaviour change for protocols decorated with both @final and @runtime_checkable. On 3.10:

>>> from typing import *
>>> @final
... @runtime_checkable
... class Foo(Protocol):
...     def bar(self): ...
...
>>> class Spam:
...     def bar(self): ...
...
>>> issubclass(Spam, Foo)
True
>>> isinstance(Spam(), Foo)
True

On 3.11:

>>> from typing import *
>>> @final
... @runtime_checkable
... class Foo(Protocol):
...     def bar(self): ...
...
>>> class Spam:
...     def bar(self): ...
...
>>> issubclass(Spam, Foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<frozen abc>", line 123, in __subclasscheck__
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1547, in _proto_hook
    raise TypeError("Protocols with non-method members"
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Protocols with non-method members don't support issubclass()
>>> isinstance(Spam(), Foo)
False

This is because, following 0bbf30e (by @JelleZijlstra), the @final decorator sets a __final__ attribute wherever it can, so that it is introspectable by runtime tools. But the runtime-checkable-protocol isinstance() machinery doesn't know anything about the __final__ attribute, so it assumes that the __final__ attribute is just a regular protocol member.

This should be pretty easy to fix: we just need to add __final__ to the set of "special attributes" ignored by runtime-checkable-protocol isinstance()/issubclass() checks here:

cpython/Lib/typing.py

Lines 1906 to 1909 in 848bdbe

_TYPING_INTERNALS = frozenset({
'__parameters__', '__orig_bases__', '__orig_class__',
'_is_protocol', '_is_runtime_protocol'
})

@JelleZijlstra do you agree with that course of action?

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.11only security fixesstdlibPython modules in the Lib dirtopic-typingtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions