Skip to content

Commit

Permalink
add infer_variance for ParamSpec (#172)
Browse files Browse the repository at this point in the history
For compatibility with Python 3.12, which adds this undocumented
parameter along with the existing covariant/contravariant ones.
Intentionally leaving this undocumented: it's here in case we want
to make variance on ParamSpec mean something later, but it currently
has no supported use.
  • Loading branch information
JelleZijlstra authored May 22, 2023
1 parent f2fc4cb commit 9648c6f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
26 changes: 25 additions & 1 deletion src/test_typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3314,6 +3314,7 @@ def test_repr(self):
P = ParamSpec('P')
P_co = ParamSpec('P_co', covariant=True)
P_contra = ParamSpec('P_contra', contravariant=True)
P_infer = ParamSpec('P_infer', infer_variance=True)
P_2 = ParamSpec('P_2')
self.assertEqual(repr(P), '~P')
self.assertEqual(repr(P_2), '~P_2')
Expand All @@ -3322,6 +3323,30 @@ def test_repr(self):
# just follow CPython.
self.assertEqual(repr(P_co), '+P_co')
self.assertEqual(repr(P_contra), '-P_contra')
# On other versions we use typing.ParamSpec, but it is not aware of
# infer_variance=. Not worth creating our own version of ParamSpec
# for this.
if hasattr(typing, 'TypeAliasType') or not hasattr(typing, 'ParamSpec'):
self.assertEqual(repr(P_infer), 'P_infer')
else:
self.assertEqual(repr(P_infer), '~P_infer')

def test_variance(self):
P_co = ParamSpec('P_co', covariant=True)
P_contra = ParamSpec('P_contra', contravariant=True)
P_infer = ParamSpec('P_infer', infer_variance=True)

self.assertIs(P_co.__covariant__, True)
self.assertIs(P_co.__contravariant__, False)
self.assertIs(P_co.__infer_variance__, False)

self.assertIs(P_contra.__covariant__, False)
self.assertIs(P_contra.__contravariant__, True)
self.assertIs(P_contra.__infer_variance__, False)

self.assertIs(P_infer.__covariant__, False)
self.assertIs(P_infer.__contravariant__, False)
self.assertIs(P_infer.__infer_variance__, True)

def test_valid_uses(self):
P = ParamSpec('P')
Expand All @@ -3333,7 +3358,6 @@ def test_valid_uses(self):
self.assertEqual(C2.__args__, (P, T))
self.assertEqual(C2.__parameters__, (P, T))


# Test collections.abc.Callable too.
if sys.version_info[:2] >= (3, 9):
# Note: no tests for Callable.__parameters__ here
Expand Down
23 changes: 18 additions & 5 deletions src/typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1475,9 +1475,19 @@ class _ParamSpecMeta(_TypeVarLikeMeta):

def __call__(self, name, *, bound=None,
covariant=False, contravariant=False,
default=_marker):
paramspec = typing.ParamSpec(name, bound=bound,
covariant=covariant, contravariant=contravariant)
infer_variance=False, default=_marker):
if hasattr(typing, "TypeAliasType"):
# PEP 695 implemented, can pass infer_variance to typing.TypeVar
paramspec = typing.ParamSpec(name, bound=bound,
covariant=covariant,
contravariant=contravariant,
infer_variance=infer_variance)
else:
paramspec = typing.ParamSpec(name, bound=bound,
covariant=covariant,
contravariant=contravariant)
paramspec.__infer_variance__ = infer_variance

_set_default(paramspec, default)
_set_module(paramspec)
return paramspec
Expand Down Expand Up @@ -1551,11 +1561,12 @@ def kwargs(self):
return ParamSpecKwargs(self)

def __init__(self, name, *, bound=None, covariant=False, contravariant=False,
default=_marker):
infer_variance=False, default=_marker):
super().__init__([self])
self.__name__ = name
self.__covariant__ = bool(covariant)
self.__contravariant__ = bool(contravariant)
self.__infer_variance__ = bool(infer_variance)
if bound:
self.__bound__ = typing._type_check(bound, 'Bound must be a type.')
else:
Expand All @@ -1568,7 +1579,9 @@ def __init__(self, name, *, bound=None, covariant=False, contravariant=False,
self.__module__ = def_mod

def __repr__(self):
if self.__covariant__:
if self.__infer_variance__:
prefix = ''
elif self.__covariant__:
prefix = '+'
elif self.__contravariant__:
prefix = '-'
Expand Down

0 comments on commit 9648c6f

Please sign in to comment.