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

[spec] Formalize excluded Protocol members #1833

Open
randolf-scholz opened this issue Aug 6, 2024 · 2 comments
Open

[spec] Formalize excluded Protocol members #1833

randolf-scholz opened this issue Aug 6, 2024 · 2 comments
Labels
topic: documentation Documentation-related issues and PRs

Comments

@randolf-scholz
Copy link

randolf-scholz commented Aug 6, 2024

At runtime, the following members are currently excluded by Protocol: (source)

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


_SPECIAL_NAMES = frozenset({
    '__abstractmethods__', '__annotations__', '__dict__', '__doc__',
    '__init__', '__module__', '__new__', '__slots__',
    '__subclasshook__', '__weakref__', '__class_getitem__',
    '__match_args__', '__static_attributes__', '__firstlineno__',
    '__annotate__',
})


# These special attributes will be not collected as protocol members.
EXCLUDED_ATTRIBUTES = _TYPING_INTERNALS | _SPECIAL_NAMES | {'_MutableMapping__marker'}

However, neither PEP 544 nor the typing spec formalize this list, which leads to diverging behavior between different type checkers:

Code sample in pyright playground, mypy playground

from typing import TypeIs, Protocol

class MyProtocol(Protocol):
    @classmethod
    def __subclasshook__(cls, other: type, /) -> TypeIs[type["MyProtocol"]]:
        ...

x: MyProtocol = int(1)  # mypy: ✅ pyright: ❌

Code sample in pyright playground, mypy playground

from typing import Protocol

class MyProtocol(Protocol):
    __abstractmethods__: frozenset[str]
    
x: MyProtocol = int(1)  # mypy: ✅ pyright: ❌

A real-world example where this matters is for instance a Protocol for NamedTuple Instances, that checks whether types.get_original_bases(cls) includes typing.NamedTuple inside __subclasshook__.

@randolf-scholz randolf-scholz added the topic: documentation Documentation-related issues and PRs label Aug 6, 2024
@erictraut
Copy link
Collaborator

I think this would be a good addition to the spec. @randolf-scholz, would you be willing to write a proposed modification to the spec and start a discussion thread to solicit comments from the broader community?

@randolf-scholz
Copy link
Author

I can post something in discourse in the next days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: documentation Documentation-related issues and PRs
Projects
None yet
Development

No branches or pull requests

2 participants