From 67cc05926b037243b71e857a394318c3a09d1daf Mon Sep 17 00:00:00 2001 From: Ali Hamdan Date: Sun, 9 Jul 2023 17:54:29 +0200 Subject: [PATCH] stubgen: Support `ParamSpec` and `TypeVarTuple` (#15626) These are treated the same way as `TypeVar` except imported from `typing_extensions` instead of `typing` by default. --- mypy/stubgen.py | 8 ++++++-- test-data/unit/stubgen.test | 26 ++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/mypy/stubgen.py b/mypy/stubgen.py index 229559ac8120..e7fa65d7f949 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -660,7 +660,7 @@ def visit_mypy_file(self, o: MypyFile) -> None: "_typeshed": ["Incomplete"], "typing": ["Any", "TypeVar", "NamedTuple"], "collections.abc": ["Generator"], - "typing_extensions": ["TypedDict"], + "typing_extensions": ["TypedDict", "ParamSpec", "TypeVarTuple"], } for pkg, imports in known_imports.items(): for t in imports: @@ -1158,10 +1158,14 @@ def is_alias_expression(self, expr: Expression, top_level: bool = True) -> bool: Used to know if assignments look like type aliases, function alias, or module alias. """ - # Assignment of TypeVar(...) are passed through + # Assignment of TypeVar(...) and other typevar-likes are passed through if isinstance(expr, CallExpr) and self.get_fullname(expr.callee) in ( "typing.TypeVar", "typing_extensions.TypeVar", + "typing.ParamSpec", + "typing_extensions.ParamSpec", + "typing.TypeVarTuple", + "typing_extensions.TypeVarTuple", ): return True elif isinstance(expr, EllipsisExpr): diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index e1818dc4c4bc..9c7221e7ec54 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -1036,11 +1036,16 @@ y: C [case testTypeVarPreserved] tv = TypeVar('tv') +ps = ParamSpec('ps') +tvt = TypeVarTuple('tvt') [out] from typing import TypeVar +from typing_extensions import ParamSpec, TypeVarTuple tv = TypeVar('tv') +ps = ParamSpec('ps') +tvt = TypeVarTuple('tvt') [case testTypeVarArgsPreserved] tv = TypeVar('tv', int, str) @@ -1052,29 +1057,37 @@ tv = TypeVar('tv', int, str) [case testTypeVarNamedArgsPreserved] tv = TypeVar('tv', bound=bool, covariant=True) +ps = ParamSpec('ps', bound=bool, covariant=True) [out] from typing import TypeVar +from typing_extensions import ParamSpec tv = TypeVar('tv', bound=bool, covariant=True) +ps = ParamSpec('ps', bound=bool, covariant=True) [case TypeVarImportAlias] -from typing import TypeVar as t_TV -from typing_extensions import TypeVar as te_TV +from typing import TypeVar as t_TV, ParamSpec as t_PS +from typing_extensions import TypeVar as te_TV, TypeVarTuple as te_TVT from x import TypeVar as x_TV T = t_TV('T') U = te_TV('U') V = x_TV('V') +PS = t_PS('PS') +TVT = te_TVT('TVT') + [out] from _typeshed import Incomplete -from typing import TypeVar as t_TV -from typing_extensions import TypeVar as te_TV +from typing import ParamSpec as t_PS, TypeVar as t_TV +from typing_extensions import TypeVar as te_TV, TypeVarTuple as te_TVT T = t_TV('T') U = te_TV('U') V: Incomplete +PS = t_PS('PS') +TVT = te_TVT('TVT') [case testTypeVarFromImportAlias] import typing as t @@ -1085,6 +1098,9 @@ T = t.TypeVar('T') U = te.TypeVar('U') V = x.TypeVar('V') +PS = t.ParamSpec('PS') +TVT = te.TypeVarTuple('TVT') + [out] import typing as t import typing_extensions as te @@ -1093,6 +1109,8 @@ from _typeshed import Incomplete T = t.TypeVar('T') U = te.TypeVar('U') V: Incomplete +PS = t.ParamSpec('PS') +TVT = te.TypeVarTuple('TVT') [case testTypeAliasPreserved] alias = str