diff options
Diffstat (limited to 'Lib/typing.py')
-rw-r--r-- | Lib/typing.py | 43 |
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. |