gh-104873: Add typing.get_protocol_members and typing.is_protocol (#104878)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Jelle Zijlstra 2023-06-14 05:35:06 -07:00 committed by GitHub
parent ba516e70c6
commit fc8037d84c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 2 deletions

View file

@ -131,7 +131,9 @@ __all__ = [
'get_args',
'get_origin',
'get_overloads',
'get_protocol_members',
'get_type_hints',
'is_protocol',
'is_typeddict',
'LiteralString',
'Never',
@ -3337,3 +3339,43 @@ def override[F: _Func](method: F, /) -> F:
# read-only property, TypeError if it's a builtin class.
pass
return method
def is_protocol(tp: type, /) -> bool:
"""Return True if the given type is a Protocol.
Example::
>>> from typing import Protocol, is_protocol
>>> class P(Protocol):
... def a(self) -> str: ...
... b: int
>>> is_protocol(P)
True
>>> is_protocol(int)
False
"""
return (
isinstance(tp, type)
and getattr(tp, '_is_protocol', False)
and tp != Protocol
)
def get_protocol_members(tp: type, /) -> frozenset[str]:
"""Return the set of members defined in a Protocol.
Example::
>>> from typing import Protocol, get_protocol_members
>>> class P(Protocol):
... def a(self) -> str: ...
... b: int
>>> get_protocol_members(P)
frozenset({'a', 'b'})
Raise a TypeError for arguments that are not Protocols.
"""
if not is_protocol(tp):
raise TypeError(f'{tp!r} is not a Protocol')
return frozenset(tp.__protocol_attrs__)