8000 Support PEP 612 in typing_extensions (Python 3) by Fidget-Spinner · Pull Request #774 · python/typing · GitHub
[go: up one dir, main page]

Skip to content

Support PEP 612 in typing_extensions (Python 3) #774

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

Merged
merged 14 commits into from
Apr 10, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added runtime introspection for Concatenate
  • Loading branch information
Fidget-Spinner committed Apr 6, 2021
commit a46cf7c8e6db154f37bb3190363e4f682ac6817e
9 changes: 8 additions & 1 deletion typing_extensions/src_py3/test_typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ def test_valid_uses(self):
def test_pickle(self):
global P, P_co, P_contra
for proto in range(pickle.HIGHEST_PROTOCOL):
with self.subTest(f"Pickle protocol {proto}"):
with self.subTest('Pickle protocol {proto}'.format(proto=proto)):
for paramspec in (P, P_co, P_contra):
z = pickle.loads(pickle.dumps(paramspec, proto))
self.assertEqual(z.__name__, paramspec.__name__)
Expand Down Expand Up @@ -1952,6 +1952,13 @@ def test_valid_uses(self):
C3 = collections.abc.Callable[Concatenate[int, P], int]
C4 = collections.abc.Callable[Concatenate[int, T, P], T]

def test_basic_introspection(self):
C1 = Concatenate[int, P]
C2 = Concatenate[int, T, P]
self.assertEqual(C1.__origin__, Concatenate)
self.assertEqual(C1.__args__, (int, P))
self.assertEqual(C2.__origin__, Concatenate)
self.assertEqual(C2.__args__, (int, T, P))

class AllTests(BaseTestCase):

Expand Down
30 changes: 25 additions & 5 deletions typing_extensions/src_py3/typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2187,8 +2187,9 @@ class ParamSpec(list):
type checkers. They are used to forward the parameter types of one
callable to another callable, a pattern commonly found in higher order
functions and decorators. They are only valid when used in ``Concatenate``,
or s the first argument to ``Callable``, or as parameters for user-defined
Generics. See class Generic for more information on generic types. An
or s the first argument to ``Callable``. In Python 3.10 and higher,
they are also supported in user-defined Generics at runtime.
See class Generic for more information on generic types. An
example for annotating a decorator::

T = TypeVar('T')
Expand Down Expand Up @@ -2229,7 +2230,7 @@ def __init__(self, name, *, bound=None, covariant=False, contravariant=False):
self.__covariant__ = bool(covariant)
self.__contravariant__ = bool(contravariant)
if bound:
self.__bound__ = typing._type_check(bound, "Bound must be a type.")
self.__bound__ = typing._type_check(bound, 'Bound must be a type.')
else:
self.__bound__ = None

Expand All @@ -2253,10 +2254,27 @@ def __repr__(self):
def __reduce__(self):
return self.__name__

# Hack to get typing._type_check to pass.
def __call__(self, *args, **kwargs):
pass

# Note: Can't fake ParamSpec as a TypeVar to get it to work
# with Generics. ParamSpec isn't an instance of TypeVar in 3.10.
# So encouraging code like isinstance(ParamSpec('P'), TypeVar))
# will lead to breakage in 3.10.
# This also means no accurate __parameters__ for GenericAliases.

# Inherits from list as a workaround for Callable checks in Python < 3.9.2.
class _ConcatenateGenericAlias(list):
def __init__(self, *args, **kwargs):
pass
def __init__(self, origin, args):
self.__origin__ = origin
self.__args__ = args

def __repr__(self):
_type_repr = typing._type_repr
return '{origin}[{args}]' \
.format(origin=_type_repr(self.__origin__),
args=', '.join(_type_repr(arg) for arg in self.__args__))

@_tp_cache
def _concatenate_getitem(self, parameters):
Expand All @@ -2267,6 +2285,8 @@ def _concatenate_getitem(self, parameters):
if not isinstance(parameters[-1], ParamSpec):
raise TypeError("The last parameter to Concatenate should be a "
"ParamSpec variable.")
msg = "Concatenate[arg, ...]: each arg must be a type."
parameters = tuple(typing._type_check(p, msg) for p in parameters)
return _ConcatenateGenericAlias(self, parameters)


Expand Down
0