summaryrefslogtreecommitdiffstats
path: root/Lib/typing.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/typing.py')
-rw-r--r--Lib/typing.py43
1 files changed, 29 insertions, 14 deletions
diff --git a/Lib/typing.py b/Lib/typing.py
index 26efe4a..639feee 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -195,15 +195,17 @@ def _type_repr(obj):
return repr(obj)
-def _collect_type_vars(types):
- """Collect all type variable-like variables contained
+def _collect_type_vars(types, typevar_types=None):
+ """Collect all type variable contained
in types in order of first appearance (lexicographic order). For example::
_collect_type_vars((T, List[S, T])) == (T, S)
"""
+ if typevar_types is None:
+ typevar_types = TypeVar
tvars = []
for t in types:
- if isinstance(t, _TypeVarLike) and t not in tvars:
+ if isinstance(t, typevar_types) and t not in tvars:
tvars.append(t)
if isinstance(t, (_GenericAlias, GenericAlias)):
tvars.extend([t for t in t.__parameters__ if t not in tvars])
@@ -932,7 +934,8 @@ class _BaseGenericAlias(_Final, _root=True):
raise AttributeError(attr)
def __setattr__(self, attr, val):
- if _is_dunder(attr) or attr in ('_name', '_inst', '_nparams'):
+ if _is_dunder(attr) or attr in {'_name', '_inst', '_nparams',
+ '_typevar_types', '_paramspec_tvars'}:
super().__setattr__(attr, val)
else:
setattr(self.__origin__, attr, val)
@@ -957,14 +960,18 @@ class _BaseGenericAlias(_Final, _root=True):
class _GenericAlias(_BaseGenericAlias, _root=True):
- def __init__(self, origin, params, *, inst=True, name=None):
+ def __init__(self, origin, params, *, inst=True, name=None,
+ _typevar_types=TypeVar,
+ _paramspec_tvars=False):
super().__init__(origin, inst=inst, name=name)
if not isinstance(params, tuple):
params = (params,)
self.__args__ = tuple(... if a is _TypingEllipsis else
() if a is _TypingEmpty else
a for a in params)
- self.__parameters__ = _collect_type_vars(params)
+ self.__parameters__ = _collect_type_vars(params, typevar_types=_typevar_types)
+ self._typevar_types = _typevar_types
+ self._paramspec_tvars = _paramspec_tvars
if not name:
self.__module__ = origin.__module__
@@ -991,14 +998,15 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
if not isinstance(params, tuple):
params = (params,)
params = tuple(_type_convert(p) for p in params)
- if any(isinstance(t, ParamSpec) for t in self.__parameters__):
- params = _prepare_paramspec_params(self, params)
+ if self._paramspec_tvars:
+ if any(isinstance(t, ParamSpec) for t in self.__parameters__):
+ params = _prepare_paramspec_params(self, params)
_check_generic(self, params, len(self.__parameters__))
subst = dict(zip(self.__parameters__, params))
new_args = []
for arg in self.__args__:
- if isinstance(arg, _TypeVarLike):
+ if isinstance(arg, self._typevar_types):
arg = subst[arg]
elif isinstance(arg, (_GenericAlias, GenericAlias)):
subparams = arg.__parameters__
@@ -1115,7 +1123,9 @@ class _CallableGenericAlias(_GenericAlias, _root=True):
class _CallableType(_SpecialGenericAlias, _root=True):
def copy_with(self, params):
return _CallableGenericAlias(self.__origin__, params,
- name=self._name, inst=self._inst)
+ name=self._name, inst=self._inst,
+ _typevar_types=(TypeVar, ParamSpec),
+ _paramspec_tvars=True)
def __getitem__(self, params):
if not isinstance(params, tuple) or len(params) != 2:
@@ -1208,7 +1218,10 @@ class _LiteralGenericAlias(_GenericAlias, _root=True):
class _ConcatenateGenericAlias(_GenericAlias, _root=True):
- pass
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs,
+ _typevar_types=(TypeVar, ParamSpec),
+ _paramspec_tvars=True)
class Generic:
@@ -1244,7 +1257,7 @@ class Generic:
params = tuple(_type_convert(p) for p in params)
if cls in (Generic, Protocol):
# Generic and Protocol can only be subscripted with unique type variables.
- if not all(isinstance(p, _TypeVarLike) for p in params):
+ if not all(isinstance(p, (TypeVar, ParamSpec)) for p in params):
raise TypeError(
f"Parameters to {cls.__name__}[...] must all be type variables "
f"or parameter specification variables.")
@@ -1256,7 +1269,9 @@ class Generic:
if any(isinstance(t, ParamSpec) for t in cls.__parameters__):
params = _prepare_paramspec_params(cls, params)
_check_generic(cls, params, len(cls.__parameters__))
- return _GenericAlias(cls, params)
+ return _GenericAlias(cls, params,
+ _typevar_types=(TypeVar, ParamSpec),
+ _paramspec_tvars=True)
def __init_subclass__(cls, *args, **kwargs):
super().__init_subclass__(*args, **kwargs)
@@ -1268,7 +1283,7 @@ class Generic:
if error:
raise TypeError("Cannot inherit from plain Generic")
if '__orig_bases__' in cls.__dict__:
- tvars = _collect_type_vars(cls.__orig_bases__)
+ tvars = _collect_type_vars(cls.__orig_bases__, (TypeVar, ParamSpec))
# Look for Generic[T1, ..., Tn].
# If found, tvars must be a subset of it.
# If not found, tvars is it.