diff options
author | kj <28750310+Fidget-Spinner@users.noreply.github.com> | 2020-12-13 18:38:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-13 18:38:24 (GMT) |
commit | 463c7d3d149283814d879a9bb8411af64e656c8e (patch) | |
tree | 204f9b460e5740291fd33d03908131bad317a922 /Lib/typing.py | |
parent | 43c4fb6c90c013a00cb820cb61e4990cd8ec7f5e (diff) | |
download | cpython-463c7d3d149283814d879a9bb8411af64e656c8e.zip cpython-463c7d3d149283814d879a9bb8411af64e656c8e.tar.gz cpython-463c7d3d149283814d879a9bb8411af64e656c8e.tar.bz2 |
bpo-42195: Ensure consistency of Callable's __args__ in collections.abc and typing (GH-23060)
Diffstat (limited to 'Lib/typing.py')
-rw-r--r-- | Lib/typing.py | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/Lib/typing.py b/Lib/typing.py index 148a505..7f07321 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -120,6 +120,16 @@ __all__ = [ # namespace, but excluded from __all__ because they might stomp on # legitimate imports of those modules. + +def _type_convert(arg): + """For converting None to type(None), and strings to ForwardRef.""" + if arg is None: + return type(None) + if isinstance(arg, str): + return ForwardRef(arg) + return arg + + def _type_check(arg, msg, is_argument=True): """Check that the argument is a type, and return it (internal helper). @@ -136,10 +146,7 @@ def _type_check(arg, msg, is_argument=True): if is_argument: invalid_generic_forms = invalid_generic_forms + (ClassVar, Final) - if arg is None: - return type(None) - if isinstance(arg, str): - return ForwardRef(arg) + arg = _type_convert(arg) if (isinstance(arg, _GenericAlias) and arg.__origin__ in invalid_generic_forms): raise TypeError(f"{arg} is not valid as type argument") @@ -900,13 +907,13 @@ class _CallableType(_SpecialGenericAlias, _root=True): raise TypeError("Callable must be used as " "Callable[[arg, ...], result].") args, result = params - if args is Ellipsis: - params = (Ellipsis, result) - else: - if not isinstance(args, list): - raise TypeError(f"Callable[args, result]: args must be a list." - f" Got {args}") + # This relaxes what args can be on purpose to allow things like + # PEP 612 ParamSpec. Responsibility for whether a user is using + # Callable[...] properly is deferred to static type checkers. + if isinstance(args, list): params = (tuple(args), result) + else: + params = (args, result) return self.__getitem_inner__(params) @_tp_cache @@ -916,8 +923,9 @@ class _CallableType(_SpecialGenericAlias, _root=True): result = _type_check(result, msg) if args is Ellipsis: return self.copy_with((_TypingEllipsis, result)) - msg = "Callable[[arg, ...], result]: each arg must be a type." - args = tuple(_type_check(arg, msg) for arg in args) + if not isinstance(args, tuple): + args = (args,) + args = tuple(_type_convert(arg) for arg in args) params = args + (result,) return self.copy_with(params) |