bpo-44793: Fix checking the number of arguments when subscribe a generic type with ParamSpec parameter. (GH-27515)


For example Callable[P, T][[int], str, float] will now raise an error.

Use also term "arguments" instead of "parameters" in error
message for too few/many arguments.
(cherry picked from commit f92b9133ef67e77605cbd315b6b6c81036ce110e)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
diff --git a/Lib/typing.py b/Lib/typing.py
index bcb22b2..e492bd2 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -220,7 +220,7 @@ def _check_generic(cls, parameters, elen):
         raise TypeError(f"{cls} is not a generic class")
     alen = len(parameters)
     if alen != elen:
-        raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};"
+        raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};"
                         f" actual {alen}, expected {elen}")
 
 def _prepare_paramspec_params(cls, params):
@@ -231,6 +231,7 @@ def _prepare_paramspec_params(cls, params):
     if len(cls.__parameters__) == 1 and len(params) > 1:
         return (params,)
     else:
+        _check_generic(cls, params, len(cls.__parameters__))
         _params = []
         # Convert lists to tuples to help other libraries cache the results.
         for p, tvar in zip(params, cls.__parameters__):
@@ -1020,10 +1021,11 @@ def __getitem__(self, params):
         if not isinstance(params, tuple):
             params = (params,)
         params = tuple(_type_convert(p) for p in 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__))
+        if (self._paramspec_tvars
+                and any(isinstance(t, ParamSpec) for t in self.__parameters__)):
+            params = _prepare_paramspec_params(self, params)
+        else:
+            _check_generic(self, params, len(self.__parameters__))
 
         subst = dict(zip(self.__parameters__, params))
         new_args = []
@@ -1290,7 +1292,8 @@ def __class_getitem__(cls, params):
             # Subscripting a regular Generic subclass.
             if any(isinstance(t, ParamSpec) for t in cls.__parameters__):
                 params = _prepare_paramspec_params(cls, params)
-            _check_generic(cls, params, len(cls.__parameters__))
+            else:
+                _check_generic(cls, params, len(cls.__parameters__))
         return _GenericAlias(cls, params,
                              _typevar_types=(TypeVar, ParamSpec),
                              _paramspec_tvars=True)