summaryrefslogtreecommitdiffstats
path: root/Lib/typing.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-08-04 18:07:01 (GMT)
committerGitHub <noreply@github.com>2021-08-04 18:07:01 (GMT)
commit3875a6954741065b136650db67ac533bc70a3eac (patch)
tree14347458795f0017b39dad3c686b4459c6e6a904 /Lib/typing.py
parent10faada709561663d6b1f623d308ff45e3808cca (diff)
downloadcpython-3875a6954741065b136650db67ac533bc70a3eac.zip
cpython-3875a6954741065b136650db67ac533bc70a3eac.tar.gz
cpython-3875a6954741065b136650db67ac533bc70a3eac.tar.bz2
bpo-44801: Check arguments in substitution of ParamSpec in Callable (GH-27585)
Diffstat (limited to 'Lib/typing.py')
-rw-r--r--Lib/typing.py26
1 files changed, 18 insertions, 8 deletions
diff --git a/Lib/typing.py b/Lib/typing.py
index 7a12d31..9c595ae 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -182,6 +182,11 @@ def _type_check(arg, msg, is_argument=True, module=None):
return arg
+def _is_param_expr(arg):
+ return arg is ... or isinstance(arg,
+ (tuple, list, ParamSpec, _ConcatenateGenericAlias))
+
+
def _type_repr(obj):
"""Return the repr() of an object, special-casing types (internal helper).
@@ -236,7 +241,9 @@ def _prepare_paramspec_params(cls, params):
variables (internal helper).
"""
# Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612.
- if len(cls.__parameters__) == 1 and len(params) > 1:
+ if (len(cls.__parameters__) == 1
+ and params and not _is_param_expr(params[0])):
+ assert isinstance(cls.__parameters__[0], ParamSpec)
return (params,)
else:
_check_generic(cls, params, len(cls.__parameters__))
@@ -1033,7 +1040,13 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
new_args = []
for arg in self.__args__:
if isinstance(arg, self._typevar_types):
- arg = subst[arg]
+ if isinstance(arg, ParamSpec):
+ arg = subst[arg]
+ if not _is_param_expr(arg):
+ raise TypeError(f"Expected a list of types, an ellipsis, "
+ f"ParamSpec, or Concatenate. Got {arg}")
+ else:
+ arg = subst[arg]
elif isinstance(arg, (_GenericAlias, GenericAlias, types.UnionType)):
subparams = arg.__parameters__
if subparams:
@@ -1131,8 +1144,7 @@ class _CallableGenericAlias(_GenericAlias, _root=True):
def __repr__(self):
assert self._name == 'Callable'
args = self.__args__
- if len(args) == 2 and (args[0] is Ellipsis
- or isinstance(args[0], (ParamSpec, _ConcatenateGenericAlias))):
+ if len(args) == 2 and _is_param_expr(args[0]):
return super().__repr__()
return (f'typing.Callable'
f'[[{", ".join([_type_repr(a) for a in args[:-1]])}], '
@@ -1140,8 +1152,7 @@ class _CallableGenericAlias(_GenericAlias, _root=True):
def __reduce__(self):
args = self.__args__
- if not (len(args) == 2 and (args[0] is Ellipsis
- or isinstance(args[0], (ParamSpec, _ConcatenateGenericAlias)))):
+ if not (len(args) == 2 and _is_param_expr(args[0])):
args = list(args[:-1]), args[-1]
return operator.getitem, (Callable, args)
@@ -1864,8 +1875,7 @@ def get_args(tp):
if isinstance(tp, (_GenericAlias, GenericAlias)):
res = tp.__args__
if (tp.__origin__ is collections.abc.Callable
- and not (res[0] is Ellipsis
- or isinstance(res[0], (ParamSpec, _ConcatenateGenericAlias)))):
+ and not (len(res) == 2 and _is_param_expr(res[0]))):
res = (list(res[:-1]), res[-1])
return res
if isinstance(tp, types.UnionType):