Files
openide/python/testSrc/com/jetbrains/python/PyTypingTest.java
2024-10-03 12:19:06 +00:00

6024 lines
164 KiB
Java

/*
* Copyright 2000-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Tests for a type system based on mypy's typing module.
*
*/
public class PyTypingTest extends PyTestCase {
public void testClassType() {
doTest("Foo",
"""
class Foo: pass
def f(expr: Foo):
pass
""");
}
public void testClassReturnType() {
doTest("Foo",
"""
class Foo: pass
def f() -> Foo:
pass
expr = f()
""");
}
public void testNoneType() {
doTest("None",
"""
def f(expr: None):
pass
""");
}
public void testNoneReturnType() {
doTest("None",
"""
def f() -> None:
return 0
expr = f()
""");
}
public void testUnionType() {
doTest("int | str",
"""
from typing import Union
def f(expr: Union[int, str]):
pass
""");
}
public void testBuiltinList() {
doTest("list",
"""
from typing import List
def f(expr: List):
pass
""");
}
public void testBuiltinListWithParameter() {
doTest("list[int]",
"""
from typing import List
def f(expr: List[int]):
pass
""");
}
public void testBuiltinDictWithParameters() {
doTest("dict[str, int]",
"""
from typing import Dict
def f(expr: Dict[str, int]):
pass
""");
}
public void testBuiltinTuple() {
doTest("tuple",
"""
from typing import Tuple
def f(expr: Tuple):
pass
""");
}
public void testBuiltinTupleWithParameters() {
doTest("tuple[int, str]",
"""
from typing import Tuple
def f(expr: Tuple[int, str]):
pass
""");
}
public void testAnyType() {
doTest("Any",
"""
from typing import Any
def f(expr: Any):
pass
""");
}
public void testGenericType() {
doTest("A",
"""
from typing import TypeVar
T = TypeVar('A')
def f(expr: T):
pass
""");
}
public void testGenericBoundedType() {
doTest("T",
"""
from typing import TypeVar
T = TypeVar('T', int, str)
def f(expr: T):
pass
""");
}
public void testParameterizedClass() {
doTest("C[int]",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class C(Generic[T]):
def __init__(self, x: T):
pass
expr = C(10)
""");
}
public void testParameterizedClassWithConstructorNone() {
doTest("C[int]",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class C(Generic[T]):
def __init__(self, x: T) -> None:
pass
expr = C(10)
""");
}
public void testParameterizedClassMethod() {
doTest("int",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class C(Generic[T]):
def __init__(self, x: T):
pass
def foo(self) -> T:
pass
expr = C(10).foo()
""");
}
public void testParameterizedClassInheritance() {
doTest("int",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class B(Generic[T]):
def foo(self) -> T:
pass
class C(B[T]):
def __init__(self, x: T):
pass
expr = C(10).foo()
""");
}
public void testAnyStrUnification() {
doTest("bytes",
"""
from typing import AnyStr
def foo(x: AnyStr) -> AnyStr:
pass
expr = foo(b'bar')
""");
}
public void testAnyStrForUnknown() {
doTest("str | bytes | Any",
"""
from typing import AnyStr
def foo(x: AnyStr) -> AnyStr:
pass
def bar(x):
expr = foo(x)
""");
}
public void testCallableType() {
doTest("(int, str) -> str",
"""
from typing import Callable
def foo(expr: Callable[[int, str], str]):
pass
""");
}
public void testTypeInStringLiteral() {
doTest("C",
"""
class C:
def foo(self, expr: 'C'):
pass
""");
}
public void testQualifiedTypeInStringLiteral() {
doTest("str",
"""
import typing
def foo(x: 'typing.AnyStr') -> typing.AnyStr:
pass
expr = foo('bar')
""");
}
public void testOptionalType() {
doTest("int | None",
"""
from typing import Optional
def foo(expr: Optional[int]):
pass
""");
}
// PY-28032
public void testOptionalOfAny() {
doTest("Any | None",
"""
from typing import Optional, Any
x = None # type: Optional[Any]
expr = x
""");
}
public void testOptionalFromDefaultNone() {
doTest("int | None",
"""
def foo(expr: int = None):
pass
""");
}
public void testFlattenUnions() {
doTest("int | str | list",
"""
from typing import Union
def foo(expr: Union[int, Union[str, list]]):
pass
""");
}
public void testCast() {
doTest("str",
"""
from typing import cast
def foo(x):
expr = cast(str, x)
""");
}
public void testComment() {
doTest("int",
"""
def foo(x):
expr = x # type: int
""");
}
public void testMultiAssignmentComment() {
doTest("tuple[int, str]",
"""
def foo(x):
c1, c2 = x # type: int, str
expr = c1, c2
""");
}
// PY-19220
public void testMultiLineAssignmentComment() {
doTest("list[str]",
"""
from typing import List
expr = [
a,
b,
] # type: List[str]""");
}
public void testForLoopComment() {
doTest("int",
"""
def foo(xs):
for expr, x in xs: # type: int, str
pass
""");
}
public void testWithComment() {
doTest("int",
"""
def foo(x):
with x as expr: # type: int
pass
""");
}
// PY-21191
public void testTypeCommentWithParenthesizedTuple() {
doTest("int",
"expr, x = undefined() # type: (int, str) ");
}
// PY-21191
public void testTypeCommentWithNestedTuplesInAssignment() {
doTest("int",
"_, (_, expr) = undefined() # type: str, (str, int)");
}
// PY-21191
public void testTypeCommentStructuralMismatch1() {
doTest("Any",
"expr = undefined() # type: str, int");
}
// PY-21191
public void testTypeCommentStructuralMismatch2() {
doTest("Any",
"_, (_, expr) = undefined() # type: str, (str, str, int)");
}
// PY-21191
public void testTypeCommentStructuralMismatch3() {
doTest("Any",
"_, (_, expr) = undefined() # type: (str, str), int");
}
// PY-21191
public void testTypeCommentWithNestedTuplesInWithStatement() {
doTest("int",
"with undefined() as (_, (_, expr)): # type: str, (str, int)\n" +
" pass");
}
// PY-21191
public void testTypeCommentWithNestedTuplesInForStatement() {
doTest("int",
"for (_, (_, expr)) in undefined(): # type: str, (str, int)\n" +
" pass");
}
// PY-16585
public void testCommentAfterComprehensionInAssignment() {
doTest("int",
"""
from typing import List
xs = [expr for expr in range(10)] # type: List[int]""");
}
// PY-16585
public void testCommentAfterComprehensionInForLoop() {
doTest("int",
"for _ in [str(expr) for expr in range(10)]: # type: str\n" +
" pass");
}
// PY-16585
public void testCommentAfterComprehensionInWithStatement() {
doTest("int",
"with f([expr for expr in range(10)]) as _: # type: str\n" +
" pass");
}
public void testStringLiteralInjection() {
doTestInjectedText("""
class C:
def foo(self, expr: '<caret>C'):
pass
""",
"C");
}
public void testStringLiteralInjectionParameterizedType() {
doTestInjectedText("""
from typing import Union, List
class C:
def foo(self, expr: '<caret>Union[List[C], C]'):
pass
""",
"Union[List[C], C]");
}
// PY-37515
public void testNoStringLiteralInjectionUnderCall() {
doTestNoInjectedText("class Model:\n" +
" field: call('<caret>List[str]')");
}
// PY-15810
public void testNoStringLiteralInjectionForNonTypingStrings() {
doTestNoInjectedText("""
class C:
def foo(self, expr: '<caret>foo bar'):
pass
""");
}
// PY-42334
public void testStringLiteralInjectionForExplicitTypeAlias() {
doTestInjectedText("""
from typing import TypeAlias
Alias: TypeAlias = 'any + <caret>text'""",
"any + text");
}
// PY-42334
public void testStringLiteralInjectionForExplicitTypeAliasUsingTypeComment() {
doTestInjectedText("""
from typing import TypeAlias
Alias = 'any + <caret>text' # type: TypeAlias""",
"any + text");
}
// PY-22620
public void testVariableTypeCommentInjectionTuple() {
doTestInjectedText("x, y = undefined() # type: int,<caret> int",
"int, int");
}
// PY-21195
public void testVariableTypeCommentWithSubsequentComment() {
doTestInjectedText("x, y = undefined() # type: int,<caret> str # comment",
"int, str");
}
// PY-21195
public void testVariableTypeCommentWithSubsequentCommentWithoutSpacesInBetween() {
doTestInjectedText("x, y = undefined() # type: int,<caret> str# comment",
"int, str");
}
// PY-22620
public void testVariableTypeCommentInjectionParenthesisedTuple() {
doTestInjectedText("x, y = undefined() # type: (int,<caret> int)",
"(int, int)");
}
// PY-22620
public void testForTypeCommentInjectionTuple() {
doTestInjectedText("for x, y in undefined(): # type: int,<caret> int\n" +
" pass",
"int, int");
}
// PY-22620
public void testWithTypeCommentInjectionTuple() {
doTestInjectedText("with undefined() as (x, y): # type: int,<caret> int\n" +
" pass",
"int, int");
}
// PY-16125
public void testIterableForLoop() {
doTest("int",
"""
from typing import Iterable
def foo() -> Iterable[int]:
pass
for expr in foo():
pass
""");
}
// PY-16353
public void testAssignedType() {
doTest("Iterable[int]",
"""
from typing import Iterable
IntIterable = Iterable[int]
def foo() -> IntIterable:
pass
expr = foo()
""");
}
// PY-16267
public void testGenericField() {
doTest("str",
"""
from typing import TypeVar, Generic
T = TypeVar('T', covariant=True)
class C(Generic[T]):
def __init__(self, foo: T):
self.foo = foo
def f() -> C[str]:
return C('test')
x = f()
expr = x.foo
""");
}
// PY-18427 PY-76243
public void testConditionalTypeAlias() {
doTest("int",
"""
if something:
Type = int
else:
Type = str
expr: Type
""");
}
public void testConditionalGenericTypeAliasWithoutExplicitParameter() {
doTest("list[str]",
"""
if something:
Type = list
else:
Type = set
expr: Type[str]
""");
}
public void testConditionalGenericTypeAliasWithExplicitParameter() {
doTest("list[str]",
"""
from typing import TypeVar
T = TypeVar("T")
if something:
Type = list[T]
else:
Type = set[T]
expr: Type[str]
""");
}
public void testTypeAliasOfUnionOfGenericTypes() {
doTest("list[str] | set[str]",
"""
from typing import TypeVar
T = TypeVar("T")
Type = list[T] | set[T]
expr: Type[str]
""");
}
public void testTypeAliasOfUnionOfGenericTypesWithDifferentArity() {
doTest("dict[str, int] | set[int]",
"""
from typing import TypeVar
T1 = TypeVar("T1")
T2 = TypeVar("T2")
Type = dict[T1, T2] | set[T2]
expr: Type[str, int]
""");
}
// PY-18254
public void testFunctionTypeComment() {
doTest("(x: int, args: tuple[float, ...], kwargs: dict[str, str]) -> list[bool]",
"""
from typing import List
def f(x, *args, **kwargs):
# type: (int, *float, **str) -> List[bool]
pass
expr = f""");
}
// PY-18595
public void testFunctionTypeCommentForStaticMethod() {
doTest("int",
"""
class C:
@staticmethod
def m(some_int, some_bool, some_str):
# type: (int, bool, str) -> bool
expr = some_int""");
}
// PY-18726
public void testFunctionTypeCommentCallableParameter() {
doTest("(bool, str) -> int",
"""
from typing import Callable
def f(cb):
# type: (Callable[[bool, str], int]) -> None
expr = cb""");
}
// PY-18763
public void testCallableTypeWithEllipsis() {
doTest("(...) -> int",
"""
from typing import Callable
expr = unknown() # type: Callable[..., int]""");
}
// PY-18763
public void testFunctionTypeCommentCallableParameterWithEllipsis() {
doTest("(...) -> int",
"""
from typing import Callable
def f(cb):
# type: (Callable[..., int]) -> None
expr = cb""");
}
// PY-18726
public void testFunctionTypeCommentBadCallableParameter1() {
doTest("Any",
"""
from typing import Callable, Tuple
def f(cb):
# type: (Callable[Tuple[bool, str], int]) -> None
expr = cb""");
}
// PY-18726
public void testFunctionTypeCommentBadCallableParameter2() {
doTest("(bool, int) -> Any",
"""
from typing import Callable, Tuple
def f(cb):
# type: (Callable[[bool, int], [int]]) -> None
expr = cb""");
}
// PY-18598
public void testFunctionTypeCommentEllipsisParameters() {
doTest("(x: Any, y: Any, z: Any) -> int",
"""
def f(x, y=42, z='foo'):
# type: (...) -> int\s
pass
expr = f""");
}
// PY-20421
public void testFunctionTypeCommentSingleElementTuple() {
doTest("tuple[int]",
"""
from typing import Tuple
def f():
# type: () -> Tuple[int]
pass
expr = f()""");
}
// PY-18762
public void testHomogeneousTuple() {
doTest("tuple[int, ...]",
"""
from typing import Tuple
def f(xs: Tuple[int, ...]):
expr = xs""");
}
// PY-18762
public void testHomogeneousTupleIterationType() {
doTest("int",
"""
from typing import Tuple
xs = unknown() # type: Tuple[int, ...]
for x in xs:
expr = x""");
}
// PY-18762
public void testHomogeneousTupleUnpackingTarget() {
doTest("int",
"""
from typing import Tuple
xs = unknown() # type: Tuple[int, ...]
expr, yx = xs""");
}
// PY-18762
public void testHomogeneousTupleMultiplication() {
doTest("tuple[int, ...]",
"""
from typing import Tuple
xs = unknown() # type: Tuple[int, ...]
expr = xs * 42""");
}
// PY-18762
public void testFunctionTypeCommentHomogeneousTuple() {
doTest("tuple[int, ...]",
"""
from typing import Tuple
def f(xs):
# type: (Tuple[int, ...]) -> None
expr = xs
""");
}
// PY-18741
public void testFunctionTypeCommentWithParamTypeComment() {
doTest("(x: int, y: bool, z: Any) -> str",
"""
def f(x, # type: int\s
y # type: bool
,z):
# type: (...) -> str
pass
expr = f""");
}
// PY-18877
public void testFunctionTypeCommentOnTheSameLine() {
doTest("(x: int, y: int) -> None",
"""
def f(x,
y): # type: (int, int) -> None
pass
expr = f""");
}
// PY-18386
public void testRecursiveType() {
doTest("int | Any",
"""
from typing import Union
Type = Union[int, 'Type']
expr = 42 # type: Type""");
}
// PY-18386
public void testRecursiveType2() {
doTest("dict[str, str | int | float | Any]",
"""
from typing import Dict, Union
JsonDict = Dict[str, Union[str, int, float, 'JsonDict']]
def f(x: JsonDict):
expr = x""");
}
// PY-18386
public void testRecursiveType3() {
doTest("str | int | Any",
"""
from typing import Union
Type1 = Union[str, 'Type2']
Type2 = Union[int, Type1]
expr = None # type: Type1""");
}
// PY-19858
public void testGetListItemByIntegral() {
doTest("list",
"""
from typing import List
def foo(x: List[List]):
expr = x[0]
""");
}
// PY-19858
public void testGetListItemByIndirectIntegral() {
doTest("list",
"""
from typing import List
def foo(x: List[List]):
y = 0
expr = x[y]
""");
}
// PY-19858
public void testGetSublistBySlice() {
doTest("list[list]",
"""
from typing import List
def foo(x: List[List]):
expr = x[1:3]
""");
}
// PY-19858
public void testGetSublistByIndirectSlice() {
doTest("list[list]",
"""
from typing import List
def foo(x: List[List]):
y = slice(1, 3)
expr = x[y]
""");
}
// PY-19858
public void testGetListItemByUnknown() {
doTest("list | list[list]",
"""
from typing import List
def foo(x: List[List]):
expr = x[y]
""");
}
public void testGetListOfListsItemByIntegral() {
doTest("Any",
"""
from typing import List
def foo(x: List[List]):
sublist = x[0]
expr = sublist[0]
""");
}
public void testLocalVariableAnnotation() {
doTest("int",
"""
def f():
x: int = undefined()
expr = x""");
}
// PY-21864
public void testLocalVariableAnnotationAheadOfTimeWithTarget() {
doTest("int",
"""
x: int
with foo() as x:
expr = x
""");
}
// PY-21864
public void testTopLevelVariableAnnotationAheadOfTimeInAnotherFileWithTarget() {
doMultiFileStubAwareTest("int",
"""
from other import x
expr = x""");
}
public void testLocalVariableAnnotationAheadOfTimeForTarget() {
doTest("int",
"""
x: int
for x in foo():
expr = x
""");
}
// PY-21864
public void testTopLevelVariableAnnotationAheadOfTimeInAnotherFileForTarget() {
doMultiFileStubAwareTest("int",
"""
from other import x
expr = x""");
}
// PY-21864
public void testLocalVariableAnnotationAheadOfTimeUnpackingTarget() {
doTest("int",
"""
x: int
x, y = foo()
expr = x""");
}
// PY-21864
public void testTopLevelVariableAnnotationAheadOfTimeInAnotherFileUnpackingTarget() {
doMultiFileStubAwareTest("int",
"""
from other import x
expr = x""");
}
// PY-21864
public void testLocalVariableAnnotationAheadOfTimeOnlyFirstHintConsidered() {
doTest("int",
"""
x: int
x = foo()
x: str
x = baz()
expr = x""");
}
// PY-16412
public void testLocalVariableAnnotationAheadOfTimeExplicitAny() {
doTest("Any",
"""
from typing import Any
def func(x):
var: Any
var = x
expr = var
""");
}
// PY-28032
public void testClassAttributeAnnotationExplicitAny() {
doTest("Any",
"""
from typing import Any
class C:
attr: Any = None
\s
def m(self, x):
self.attr = x
expr = self.attr""");
}
// PY-21864
public void testClassAttributeAnnotationAheadOfTimeInAnotherFile() {
doMultiFileStubAwareTest("int",
"""
from other import C
expr = C().attr""");
}
public void testInstanceAttributeAnnotation() {
doTest("int",
"""
class C:
attr: int
\s
expr = C().attr""");
}
public void testIllegalAnnotationTargets() {
doTest("tuple[Any, int, Any, Any]",
"""
(w, _): Tuple[int, Any]
((x)): int
y: bool = z = undefined()
expr = (w, x, y, z)
""");
}
// PY-19723
public void testAnnotatedPositionalArgs() {
doTest("tuple[str, ...]",
"""
def foo(*args: str):
expr = args
""");
}
// PY-19723
public void testAnnotatedKeywordArgs() {
doTest("dict[str, int]",
"""
def foo(**kwargs: int):
expr = kwargs
""");
}
// PY-19723
public void testTypeCommentedPositionalArgs() {
doTest("tuple[str, ...]",
"""
def foo(*args # type: str
):
expr = args
""");
}
// PY-19723
public void testTypeCommentedKeywordArgs() {
doTest("dict[str, int]",
"""
def foo(**kwargs # type: int
):
expr = kwargs
""");
}
public void testGenericInheritedSpecificAndGenericParameters() {
doTest("C[float]",
"""
from typing import TypeVar, Generic, Tuple, Iterator, Iterable
T = TypeVar('T')
class B(Generic[T]):
pass
class C(B[Tuple[int, T]], Generic[T]):
def __init__(self, x: T) -> None:
pass
expr = C(3.14)
""");
}
public void testAsyncGeneratorAnnotation() {
doTest("AsyncGenerator[int, str]",
"""
from typing import AsyncGenerator
async def g() -> AsyncGenerator[int, str]:
s = (yield 42)
\s
expr = g()""");
}
public void testCoroutineReturnsGenerator() {
doTest("Coroutine[Any, Any, Generator[int, Any, Any]]",
"""
from typing import Generator
async def coroutine() -> Generator[int, Any, Any]:
def gen():
yield 42
\s
return gen()
\s
expr = coroutine()""");
}
public void testGenericRenamedParameter() {
doTest("int",
"""
from typing import TypeVar, Generic
T = TypeVar('T')
V = TypeVar('V')
class B(Generic[V]):
def get() -> V:
pass
class C(B[T]):
def __init__(self, x: T) -> None:
pass
expr = C(0).get()
""");
}
// PY-27627
public void testExplicitlyParametrizedGenericClassInstance() {
doTest("Node[int]",
"""
from typing import TypeVar, Generic, List
T = TypeVar('T')
class Node(Generic[T]):
def __init__(self, children : List[T]):
self.children = children
expr = Node[int]()""");
}
// PY-27627
public void testMultiTypeExplicitlyParametrizedGenericClassInstance() {
doTest("float",
"""
from typing import TypeVar, Generic
T = TypeVar('T')
V = TypeVar('V')
Z = TypeVar('Z')
class FirstType(Generic[T]): pass
class SecondType(Generic[V]): pass
class ThirdType(Generic[Z]): pass
class Clazz(FirstType[T], SecondType[V], ThirdType[Z]):
first: T
second: V
third: Z
def __init__(self):
pass
node = Clazz[str, int, float]()
expr = node.third""");
}
// PY-27627
public void testExplicitlyParametrizedGenericClassInstanceTypizationPriority() {
doTest("Node[str]",
"""
from typing import TypeVar, Generic, List
T = TypeVar('T')
class Node(Generic[T]):
def __init__(self, children : List[T]):
self.children = children
expr = Node[str]([1,2,3])""");
}
// PY-27627
public void testItemLookupNotResolvedAsParametrizedClassInstance() {
doTest("tuple",
"""
d = {
int: lambda: ()
}
expr = d[int]()""");
}
// PY-20057
public void testClassObjectType() {
doTest("Type[MyClass]",
"""
from typing import Type
class MyClass:
pass
def f(x: Type[MyClass]):\s
expr = x""");
}
// PY-20057
public void testConstrainedClassObjectTypeOfParam() {
doTest("Type[T]",
"""
from typing import Type, TypeVar
T = TypeVar('T', bound=int)
def f(x: Type[T]):
expr = x""");
}
// PY-20057
public void testFunctionCreatesInstanceFromType() {
doTest("int",
"""
from typing import Type, TypeVar
T = TypeVar('T')
def f(x: Type[T]) -> T:
return x()
expr = f(int)""");
}
// PY-20057
public void testFunctionReturnsTypeOfInstance() {
doTest("Type[int]",
"""
from typing import Type, TypeVar
T = TypeVar('T')
def f(x: T) -> Type[T]:
return type(x)
\s
expr = f(42)""");
}
// PY-20057
public void testNonParametrizedTypingTypeMapsToBuiltinType() {
doTest("type",
"""
from typing import Type
def f(x: Type):
expr = x""");
}
// PY-20057
public void testTypingTypeOfAnyMapsToBuiltinType() {
doTest("type",
"""
from typing import Type, Any
def f(x: Type[Any]):
expr = x""");
}
// PY-20057
public void testIllegalTypingTypeFormat() {
doTest("tuple[Any, Any, Any]",
"""
from typing import Type, Tuple
def f(x: Tuple[Type[42], Type[], Type[unresolved]]):
expr = x""");
}
// PY-20057
public void testUnionOfClassObjectTypes() {
doTest("Type[int | str]",
"""
from typing import Type, Union
def f(x: Type[Union[int, str]]):
expr = x""");
}
// PY-23053
public void testUnboundGenericMatchesClassObjectTypes() {
doTest("Type[str]",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class Holder(Generic[T]):
def __init__(self, value: T):
self._value = value
def get(self) -> T:
return self._value
expr = Holder(str).get()
""");
}
// PY-23053
public void testListContainingClasses() {
doTest("Type[str]",
"xs = [str]\n" +
"expr = xs.pop()");
}
public void testGenericUserFunctionWithManyParamsAndNestedCall() {
doTest("tuple[bool, int, str]",
"""
from typing import TypeVar
T = TypeVar('T')
U = TypeVar('U')
V = TypeVar('V')
def myid(x: T) -> T:
pass
def f(x: T, y: U, z: V):
return myid(x), myid(y), myid(z)
expr = f(True, 1, 'foo')
""");
}
// PY-24260
public void testGenericClassParameterTakenFromGenericClassObject() {
doTest("MyClass[T]",
"""
from typing import TypeVar, Generic, Type
T = TypeVar("T")
class MyClass(Generic[T]):
def __init__(self, type: Type[T]):
pass
def f(x: Type[T]):
expr = MyClass(x)
""");
}
// PY-18816
public void testLocalTypeAlias() {
doTest("int",
"""
def func(g):
Alias = int
expr: Alias = g()""");
}
// TODO same test for variable type comments
// PY-18816
public void testLocalTypeAliasInFunctionTypeComment() {
doTest("int",
"""
def func():
Alias = int
def g(x):
# type: (Alias) -> None
expr = x
""");
}
// PY-24729
public void testAnnotatedInstanceAttributeReferenceOutsideClass() {
doTest("int",
"""
class C:
attr: int
def __init__(self):
self.attr = 'foo'
expr = C().attr
""");
}
// PY-24729
public void testAnnotatedInstanceAttributeReferenceInsideClass() {
doTest("int",
"""
class C:
attr: int
def __init__(self):
self.attr = 'foo'
\s
def m(self):
expr = self.attr
""");
}
// PY-24729
public void testAnnotatedInstanceAttributeInOtherFile() {
doMultiFileStubAwareTest("int",
"""
from other import C
expr = C().attr""");
}
// PY-24990
public void testSelfAnnotationSameClassInstance() {
doTest("C",
"""
from typing import TypeVar
T = TypeVar('T')
class C:
def method(self: T) -> T:
pass
expr = C().method()""");
}
// PY-24990
public void testSelfAnnotationSubclassInstance() {
doTest("D",
"""
from typing import TypeVar
T = TypeVar('T')
class C:
def method(self: T) -> T:
pass
class D(C):
pass
expr = D().method()""");
}
// PY-24990
public void testClsAnnotationSameClassInstance() {
doTest("C",
"""
from typing import TypeVar, Type
T = TypeVar('T')
class C:
@classmethod
def factory(cls: Type[T]) -> T:
pass
expr = C.factory()""");
}
// PY-24990
public void testClsAnnotationSubclassInstance() {
doTest("D",
"""
from typing import TypeVar, Type
T = TypeVar('T')
class C:
@classmethod
def factory(cls: Type[T]) -> T:
pass
class D(C):\s
pass
expr = D.factory()""");
}
// PY-24990
public void testClsAnnotationClassMethodCalledOnInstance() {
doTest("D",
"""
from typing import TypeVar, Type
T = TypeVar('T')
class C:
@classmethod
def factory(cls: Type[T]) -> T:
pass
class D(C):\s
pass
expr = D().factory()""");
}
// PY-24990
public void testSelfAnnotationReceiverUnionType() {
doTest("A | B",
"""
from typing import TypeVar
T = TypeVar('T')
class Base:
def method(self: T) -> T:
pass
class A(Base):
pass
class B(Base):\s
pass
expr = (A() or B()).method()""");
}
// PY-24990
public void _testClsAnnotationReceiverUnionType() {
doTest("Union[A, B]",
"""
from typing import TypeVar, Type
T = TypeVar('T')
class Base:
@classmethod
def factory(cls: Type[T]) -> T:
pass
class A(Base):
pass
class B(Base):
pass
expr = (A or B).factory()""");
}
// PY-24990
public void testClsAnnotationReceiverUnionTypeClassMethodCalledOnMixedInstanceClassObject() {
doTest("A",
"""
from typing import TypeVar, Type
T = TypeVar('T')
class Base:
@classmethod
def factory(cls: Type[T]) -> T:
pass
class A(Base):
pass
expr = (A or A()).factory()""");
}
// PY-24990
public void testSelfAnnotationInstanceMethodCalledOnClassObject() {
doTest("D",
"""
from typing import TypeVar
T = TypeVar('T')
class C:
def method(self: T) -> T:
pass
class D(C):
pass
expr = C.method(D())""");
}
// PY-24990
public void testSelfAnnotationInTypeCommentSameClassInstance() {
doTest("C",
"""
from typing import TypeVar
T = TypeVar('T')
class C:
def method(self):
# type: (T) -> T
pass
expr = C().method()""");
}
// PY-24990
public void testSelfAnnotationInTypeCommentSubclassInstance() {
doTest("D",
"""
from typing import TypeVar
T = TypeVar('T')
class C:
def method(self):
# type: (T) -> T
pass
class D(C):
pass
expr = D().method()""");
}
// PY-24990
public void testClsAnnotationInTypeCommentSameClassInstance() {
doTest("C",
"""
from typing import TypeVar, Type
T = TypeVar('T')
class C:
@classmethod
def factory(cls):
# type: (Type[T]) -> T
pass
expr = C.factory()""");
}
// PY-24990
public void testClsAnnotationInTypeCommentSubclassInstance() {
doTest("D",
"""
from typing import TypeVar, Type
T = TypeVar('T')
class C:
@classmethod
def factory(cls):
# type: (Type[T]) -> T
pass
class D(C):\s
pass
expr = D.factory()""");
}
// PY-31004
public void testRecursiveTypeAliasInAnotherFile() {
doMultiFileStubAwareTest("list | int",
"""
from other import MyType
expr: MyType = ...""");
}
// PY-31146
public void testNoneTypeInAnotherFile() {
doMultiFileStubAwareTest("(int) -> None",
"""
from other import MyType
expr: MyType = ...
""");
}
// PY-34478
public void testTrivialTypeAliasInAnotherFile() {
doMultiFileStubAwareTest("str",
"""
from other import alias
expr: alias""");
}
// PY-34478
public void testTrivialUnresolvedTypeAliasInAnotherFile() {
doMultiFileStubAwareTest("Any",
"""
from other import alias
expr: alias""");
}
// PY-34478
public void testTrivialRecursiveTypeAliasInAnotherFile() {
doMultiFileStubAwareTest("Any",
"""
from other import alias
expr: alias""");
}
public void testGenericSubstitutionInDeepHierarchy() {
doTest("int",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Root(Generic[T1, T2]):
def m(self) -> T2:
pass
class Base3(Root[T1, int]):
pass
class Base2(Base3[T1]):
pass
class Base1(Base2[T1]):
pass
class Sub(Base1[T1]):
pass
expr = Sub().m()
""");
}
// PY-35235
public void testNoStringLiteralInjectionForTypingLiteral() {
doTestNoInjectedText("""
from typing import Literal
a: Literal["f<caret>oo"]
""");
doTestNoInjectedText("""
from typing import Literal
a: Literal[42, "f<caret>oo", True]
""");
doTestNoInjectedText("""
from typing import Literal
MyType = Literal[42, "f<caret>oo", True]
a: MyType
""");
doTestNoInjectedText("""
from typing import Literal, TypeAlias
MyType: TypeAlias = Literal[42, "f<caret>oo", True]
""");
doTestNoInjectedText("""
import typing
a: typing.Literal["f<caret>oo"]
""");
}
// PY-41847
public void testNoStringLiteralInjectionForTypingAnnotated() {
doTestNoInjectedText("""
from typing import Annotated
MyType = Annotated[str, "f<caret>oo", True]
a: MyType
""");
doTestNoInjectedText("""
from typing import Annotated
a: Annotated[int, "f<caret>oo", True]
""");
doTestInjectedText("from typing import Annotated\n" +
"a: Annotated['Forward<caret>Reference', 'foo']",
"ForwardReference");
}
// PY-41847
public void testTypingAnnotated() {
doTest("int",
"""
from typing import Annotated
A = Annotated[int, 'Some constraint']
expr: A""");
doTest("int",
"from typing_extensions import Annotated\n" +
"expr: Annotated[int, 'Some constraint'] = '5'");
doMultiFileStubAwareTest("int",
"from annotated import A\n" +
"expr: A = 'str'");
}
// PY-35370
public void testAnyArgumentsCallableInTypeComment() {
doTestInjectedText("from typing import Callable\n" +
"a = b # type: Call<caret>able[..., int]",
"Callable[..., int]");
}
// PY-42334
public void testExplicitTypeAliasItselfHasAnyType() {
doTest("Any",
"""
from typing import TypeAlias
expr: TypeAlias = int
""");
}
// PY-29257
public void testParameterizedTypeAliasForPartiallyGenericType() {
doTest("dict[str, int]",
"""
from typing import TypeVar
T = TypeVar('T')
dict_t1 = dict[str, T]
expr: dict_t1[int]""");
doTest("dict[str, int]",
"""
from typing import TypeVar
T = TypeVar('T')
dict_t1 = dict[T, int]
expr: dict_t1[str]""");
}
// PY-49582
public void testParameterizedTypeAliasForGenericUnion() {
doTest("str | Awaitable[str] | None",
"""
from typing import Awaitable, Optional, TypeVar, Union
T = TypeVar('T')
Input = Union[T, Awaitable[T]]
def f(expr: Optional[Input[str]]):
pass
""");
}
// PY-29257
public void testParameterizedTypeAliasPreservesOrderOfTypeParameters() {
doTest("dict[str, Any]",
"""
from typing import TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
Alias = dict[T1, T2]
expr: Alias[str]""");
doTest("dict[str, Any]",
"""
from typing import TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
Alias = dict[T2, T1]
expr: Alias[str]""");
}
// PY-29257
public void testGenericTypeAliasParameterizedWithExplicitAny() {
doTest("dict[Any, str]",
"""
from typing import TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
Alias = dict[T1, T2]
expr: Alias[Any, str]""");
}
// PY-29257
public void testGenericTypeAliasParameterizedInTwoSteps() {
doTest("dict[int, str]",
"""
from typing import TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
Alias1 = dict[T1, T2]
Alias2 = Alias1[int, T2]
expr: Alias2[str]""");
}
// PY-44905
public void testGenericTypeAliasToAnnotated() {
doTest("int",
"""
from typing import Annotated, TypeVar
marker = object()
T = TypeVar("T")
Inject = Annotated[T, marker]
expr: Inject[int]""");
}
// PY-29257
public void testGenericTypeAliasForTuple() {
doTest("tuple[int, int]",
"""
from typing import TypeVar
T = TypeVar('T')
Pair = tuple[T, T]
expr: Pair[int]""");
}
// PY-29257
public void testGenericAliasParametersCannotBeOverridden() {
doTest("list[int]",
"Alias = list[int]\n" +
"expr: Alias[str]");
}
// PY-44974
public void testBitwiseOrUnionIsInstance() {
doTest("str | dict | int",
"""
a = [42]
if isinstance(a, str | dict | int):
expr = a""");
}
// PY-44974
public void testBitwiseOrUnionIsSubclass() {
doTest("Type[str | dict | int]",
"""
a = list
if issubclass(a, str | dict | int):
expr = a""");
}
// PY-44974
public void testBitwiseOrUnionIsInstanceIntNone() {
doTest("int | None",
"""
a = [42]
if isinstance(a, int | None):
expr = a""");
}
// PY-44974
public void testBitwiseOrUnionIsInstanceNoneInt() {
doTest("int | None",
"""
a = [42]
if isinstance(a, None | int):
expr = a""");
}
// PY-44974
public void testBitwiseOrUnionIsInstanceUnionInTuple() {
doTest("str | list | dict | bool | None",
"""
a = 42
if isinstance(a, (str, (list | dict), bool | None)):
expr = a""");
}
// PY-44974
public void testBitwiseOrUnionOfUnionsIsInstance() {
doTest("dict | str | bool | list",
"""
from typing import Union
a = 42
if isinstance(a, Union[dict, Union[str, Union[bool, list]]]):
expr = a""");
}
// PY-44974
public void testBitwiseOrUnionWithFromFutureImport() {
runWithLanguageLevel(LanguageLevel.PYTHON39, () -> {
doTest("int | str",
"""
from __future__ import annotations
if something:
x: int
else:
x: str
expr = x
""");
});
}
// PY-44974
public void testBitwiseOrUnionWithoutFromFutureImport() {
runWithLanguageLevel(LanguageLevel.PYTHON39, () -> {
doTest("Union[int, str]",
"""
if something:
x: int
else:
x: str
expr = x
""");
});
}
// PY-44974
public void testBitwiseOrUnionParenthesizedUnionOfUnions() {
doTest("int | list | dict | float | str",
"""
bar: int | ((list | dict) | (float | str)) = ""
expr = bar
""");
}
// PY-44974
public void testBitwiseOrOperatorOverload() {
doTest("int",
"""
class A:
def __or__(self, other) -> int: return 5
\s
expr = A() | A()""");
}
public void testClassVarTypeResolvedFromAnnotation() {
doTest("int",
"""
from typing import ClassVar
class A:
x: ClassVar[int] = 1
expr = A.x""");
}
public void testClassVarTypeResolvedFromTypeComment() {
doTest("int",
"""
from typing import ClassVar
class A:
x = 1 # type: ClassVar[int]
expr = A.x""");
}
// PY-53104
public void testMethodReturnSelf() {
doTest("B",
"""
from typing import Self
class A:
def foo(self) -> Self:
...
class B(A):
pass
expr = B().foo()""");
}
// PY-53104
public void testMethodReturnListSelf() {
doTest("list[B]",
"""
from typing import Self
class A:
def foo(self) -> list[Self]:
...
class B(A):
pass:
...
expr = B().foo()""");
}
// PY-53104
public void testClassMethodReturnSelf() {
doTest("Circle",
"""
from typing import Self
class Shape:
@classmethod
def from_config(cls, config: dict[str, float]) -> Self:
return cls(config["scale"])
class Circle(Shape):
pass
expr = Circle.from_config({})
""");
}
// PY-53104
public void testClassMethodReturnSelfNestedClass() {
doTest("Circle",
"""
from typing import Self
class OuterClass:
class Shape:
@classmethod
def from_config(cls, config: dict[str, float]) -> Self:
return cls(config["scale"])
class Circle(Shape):
pass
expr = OuterClass.Circle.from_config({})
""");
}
// PY-53104
public void testNoUnstubInCalculateSelfTypeInFunctionDefinedInImportedFile() {
doMultiFileStubAwareTest("Clazz",
"""
from other import Clazz
clz = Clazz()
expr = clz.foo()
""");
}
// PY-53104
public void testMatchSelfUnionType() {
doTest("C",
"""
from typing import Self
class C:
def method(self) -> Self:
return self
if bool():
x = 42
else:
x = C()
expr = x.method()""");
}
// PY-53105
public void testGenericVariadicType() {
doTest("tuple[*Shape]",
"""
from typing import Generic, TypeVarTuple, Tuple
Shape = TypeVarTuple('Shape')
t: Tuple[*Shape]
expr = t""");
}
// PY-53105
public void testGenericVariadicByCallable() {
doTest("tuple[int, str]",
"""
from typing import TypeVar, TypeVarTuple, Callable, Tuple
Ts = TypeVarTuple('Ts')
def foo(f: Callable[[*Ts], Tuple[*Ts]]) -> Tuple[*Ts]: ...
def bar(a: int, b: str) -> Tuple[int, str]: ...
expr = foo(bar)
""");
}
// PY-53105
public void testGenericVariadicByCallablePrefixSuffix() {
doTest("tuple[str, str, float, int, bool]",
"""
from typing import TypeVar, TypeVarTuple, Callable, Tuple
T = TypeVar('T')
Ts = TypeVarTuple('Ts')
def foo(f: Callable[[int, *Ts, T], Tuple[T, *Ts]]) -> Tuple[str, *Ts, int, T]: ...
def bar(a: int, b: str, c: float, d: bool) -> Tuple[bool, str, float]: ...
expr = foo(bar)
""");
}
// PY-53105
public void testGenericVariadicClass() {
doTest("A[float, bool, list[str]]",
"""
from typing import TypeVarTuple, Generic, Tuple
Ts = TypeVarTuple('Ts')
class A(Generic[*Ts]):
def __init__(self, value: Tuple[int, *Ts]) -> None:
self.field: Tuple[int, *Ts] = value
tpl = (42, 1.1, True, ['42'])
expr = A(tpl)
""");
}
// PY-53105
public void testGenericVariadicClassField() {
doTest("tuple[int, float, bool, list[str]]",
"""
from typing import TypeVarTuple, Generic, Tuple
Ts = TypeVarTuple('Ts')
class A(Generic[*Ts]):
def __init__(self, value: Tuple[int, *Ts]) -> None:
self.field: Tuple[int, *Ts] = value
tpl = (42, 1.1, True, ['42'])
a = A(tpl)
expr = a.field
""");
}
// PY-53105
public void testGenericVariadicClassMethod() {
doTest("tuple[int, bool, float, str]",
"""
from typing import TypeVarTuple, Generic, Tuple
Ts = TypeVarTuple('Ts')
class A(Generic[*Ts]):
def __init__(self, value: Tuple[*Ts]) -> None:
...
def foo(self) -> Tuple[int, *Ts, str]:
...
tpl = (True, 1.1)
a = A(tpl)
expr = a.foo()
""");
}
// PY-53105
public void testGenericVariadicClassMethodPlus() {
doTest("A[int, str, bool, int]",
"""
from __future__ import annotations
from typing import TypeVarTuple, Generic, Tuple, TypeVar
T = TypeVar('T')
Ts = TypeVarTuple('Ts')
class A(Generic[T, *Ts]):
def __init__(self, t: T, *args: *Ts) -> None:
...
def __add__(self, other: A[T, *Ts]) -> A[T, *Ts, T]:
...
a = A(1, '', True)
b = A(1, '', True)
expr = a + b
""");
}
// PY-53105
public void testGenericVariadicAndGenericClass() {
doTest("A[int | str, int | str, list[int]]",
"""
from __future__ import annotations
from typing import TypeVarTuple, Generic, Tuple, TypeVar
T = TypeVar('T')
T1 = TypeVar('T1')
Ts = TypeVarTuple('Ts')
class A(Generic[T, *Ts, T1]):
def __init__(self, t: T, tpl: Tuple[*Ts], t1: T1) -> None:
...
x: int | str
expr = A(x, (x,), [1])
""");
}
// PY-53105
public void testGenericVariadicClassMethodAddAxisPrefix() {
doTest("Array[str, int, bool]",
"""
from __future__ import annotations
from typing import Generic, TypeVarTuple, Tuple, NewType, TypeVar
T = TypeVar('T')
Shape = TypeVarTuple('Shape')
class Array(Generic[*Shape]):
def __init__(self, shape: Tuple[*Shape]):
self._shape: Tuple[*Shape] = shape
def add_axis_prefix(self, t: T) -> Array[T, *Shape]: ...
shape = (42, True)
arr: Array[int, bool] = Array(shape)
expr = arr.add_axis_prefix('')
""");
}
// PY-53105
public void testGenericVariadicClassMethodAddAxisSuffix() {
doTest("Array[list[int], bool, str]",
"""
from __future__ import annotations
from typing import Generic, TypeVarTuple, Tuple, NewType, TypeVar
T = TypeVar('T')
Shape = TypeVarTuple('Shape')
class Array(Generic[*Shape]):
def __init__(self, shape: Tuple[*Shape]):
self._shape: Tuple[*Shape] = shape
def add_axis_suffix(self, t: T) -> Array[*Shape, T]: ...
shape = ([42], True)
arr: Array[list[int], bool] = Array(shape)
expr = arr.add_axis_suffix('42')
""");
}
// PY-53105
public void testGenericVariadicClassMethodAddAxisPrefixAndSuffix() {
doTest("Array[str, dict[int, str], int, str, list[int], bool]",
"""
from __future__ import annotations
from typing import Generic, TypeVarTuple, Tuple, NewType, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
T4 = TypeVar('T4')
Shape = TypeVarTuple('Shape')
class Array(Generic[*Shape]):
def __init__(self, shape: Tuple[*Shape]):
self._shape: Tuple[*Shape] = shape
def add_axis_prefix_suffix(self, t1: T1, t2: T2, t3: T3, t4: T4) -> Array[T3, T2, *Shape, T1, T4]: ...
shape = (42, '42')
arr: Array[int, str] = Array(shape)
expr = arr.add_axis_prefix_suffix([42], {42: '42'}, '42', True)
""");
}
// PY-53105
public void testGenericVariadicFunctionAddPrefixAndSuffix() {
doTest("Array[int, list[int], bool, str]",
"""
from typing import Generic, TypeVarTuple, NewType, Tuple
Ts = TypeVarTuple('Ts')
class Array(Generic[*Ts]):
def __init__(self, shape: Tuple[*Ts]):
...
def add_suf_pref(x: Array[*Ts]) -> Array[int, *Ts, str]:
...
ts = ([42], True)
arr = Array(ts)
expr = add_suf_pref(arr)
""");
}
// PY-53105
public void testGenericVariadicFunctionDeletePrefixAndSuffix() {
doTest("Array[list[int], bool]",
"""
from typing import Generic, TypeVarTuple, NewType, Tuple
Ts = TypeVarTuple('Ts')
class Array(Generic[*Ts]):
def __init__(self, shape: Tuple[*Ts]):
...
def del_suf_pref(x: Array[int, *Ts, str]) -> Array[*Ts]:
...
ts = (42, [42], True, '42')
arr = Array(ts)
expr = del_suf_pref(arr)
""");
}
// PY-53105
public void testGenericVariadicStarArgs() {
doTest("tuple[int, str]",
"""
from typing import TypeVarTuple, Tuple
Ts = TypeVarTuple('Ts')
def args_to_tuple(*args: *Ts) -> Tuple[*Ts]: ...
expr = args_to_tuple(1, 'a')
""");
}
// PY-53105
public void testGenericVariadicStarArgsOfGenericVariadics() {
doTest("tuple[int, str]",
"""
from typing import Tuple, TypeVarTuple
Ts = TypeVarTuple('Ts')
def foo(*args: Tuple[*Ts]) -> Tuple[*Ts]: ...
expr = foo((0, '1'), (1, '0'))
""");
}
// PY-53105
public void testGenericVariadicStarArgsPrefixSuffix() {
doTest("tuple[str, list, dict, bool, int]",
"""
from typing import TypeVarTuple, Tuple
Ts = TypeVarTuple('Ts')
def foo(*args: *Tuple[int, *Ts, str]) -> Tuple[*Ts, int]: ...
expr = foo(1, '', [], {}, True, '')
""");
}
// PY-53105
public void testGenericVariadicStarArgsAndTypeVars() {
doTest("tuple[str, list[int], bool, int]",
"""
from typing import TypeVarTuple, Tuple, TypeVar
Ts = TypeVarTuple('Ts')
T1 = TypeVar('T1')
T2 = TypeVar('T2')
def args_to_tuple(t1: T1, t2: T2, *args: *Tuple[T2, *Ts, float]) -> Tuple[T2, *Ts, T1]: ...
expr = args_to_tuple(1, 'a', 'a', [1], True, 3.3)
""");
}
// PY-53105
public void testGenericVariadicTypeAlias() {
doTest("tuple[int, str, bool]",
"""
from typing import Tuple, TypeVarTuple
Ts = TypeVarTuple('Ts')
MyType = Tuple[int, *Ts]
t: MyType[str, bool]
expr = t
""");
}
// PY-53105
public void testGenericVariadicAndGenericTypeAlias() {
doTest("tuple[int, str, bool, float]",
"""
from typing import Tuple, TypeVarTuple, TypeVar
T = TypeVar('T')
Ts = TypeVarTuple('Ts')
MyType = Tuple[int, *Ts, T]
t: MyType[str, bool, float]
expr = t
""");
}
// PY-53105
public void testGenericVariadicAndGenericConsecutiveTypeAlias() {
doTest("tuple[int, str, list[str], dict[str, int]]",
"""
from typing import Tuple, TypeVarTuple, TypeVar
T = TypeVar('T')
Ts = TypeVarTuple('Ts')
MyType = Tuple[int, T, *Ts]
MyType1 = MyType[str, *Ts]
t: MyType1[list[str], dict[str, int]]
expr = t
""");
}
// PY-53105
public void testChainOfGenericAliasesWithTypeVarTupleReplacedByGenericUnpackedTuple() {
doTest("tuple[int, str, bool, list[str], dict[str, int]]",
"""
from typing import Tuple, TypeVarTuple, TypeVar
T = TypeVar('T')
Ts = TypeVarTuple('Ts')
Ts1 = TypeVarTuple('Ts1')
MyType = Tuple[int, T, *Ts]
MyType1 = MyType[str, bool, *Ts1]
t: MyType1[list[str], dict[str, int]]
expr = t
""");
}
public void testChainOfGenericAliasesWithTypeVarReplacedByGenericType() {
doTest("tuple[int, list[str]]",
"""
from typing import Tuple, TypeVarTuple, TypeVar
T = TypeVar('T')
T2 = TypeVar('T2')
MyType = Tuple[int, T]
MyType1 = MyType[list[T2]]
t: MyType1[str]
expr = t
""");
}
// PY-53105
public void testGenericVariadicsIntersectsSameName() {
doTest("tuple[int, str, bool, Any]",
"""
from typing import Tuple, TypeVarTuple, TypeVar
T = TypeVar('T')
Ts = TypeVarTuple('Ts')
MyType = Tuple[int, T, *Ts]
MyType1 = MyType[str, bool, *Ts]
t: MyType1[list[str], dict[str, int]] # first place \s
expr = t
""");
}
// PY-53105
public void testGenericVariadicsTupleUnpacking() {
doTest("tuple[int, str, bool, float]",
"""
from typing import Tuple, TypeVarTuple, TypeVar
Ts = TypeVarTuple('Ts')
MyType = Tuple[int, *Ts]
t: MyType[*tuple[str, bool, float]]
expr = t
""");
}
// PY-53105
public void testVariadicGenericMatchWithHomogeneousGenericVariadicAndOtherTypes() {
doTest("Array[*tuple[Any, ...], int, str]","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
class Array(Generic[*Shape]):
...
y: Array[int, *tuple[Any, ...], int, str] = Array()
def expect_variadic_array(x: Array[int, *Shape]) -> Array[*Shape]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testVariadicGenericMatchWithHomogeneousGenericVariadicAndOtherTypesPrefixSuffix() {
doTest("Array[*tuple[Any, ...], int, float, str]","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[int, float, *tuple[Any, ...], int, str] = Array()
def expect_variadic_array(x: Array[int, T, *Shape, T1]) -> Array[*Shape, T, T1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testVariadicGenericMatchWithHomogeneousGenericVariadicAmbiguousMatchActualGenericFirst() {
doTest("Array[*tuple[float, ...], int, float, str]", """
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[int, *tuple[float, ...], int, str] = Array()
def expect_variadic_array(x: Array[int, T, *Shape, T1]) -> Array[*Shape, T, T1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothAmbiguousMatch() {
doTest("Array[*tuple[int, ...], int, int, str]", """
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[*tuple[int, ...], int, str] = Array()
def expect_variadic_array(x: Array[int, T, *Shape, T1]) -> Array[*Shape, T, T1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothActualHomogeneousGenericFirst() {
doTest("Array[float, *tuple[float, ...]]","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
T = TypeVar("T")
class Array(Generic[*Shape]):
...
y: Array[*tuple[float, ...]] = Array()
def expect_variadic_array(x: Array[T, *Shape]) -> Array[T, *Shape]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothActualHomogeneousGenericLast() {
doTest("Array[*tuple[float, ...], float]","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
T = TypeVar("T")
class Array(Generic[*Shape]):
...
y: Array[*tuple[float, ...]] = Array()
def expect_variadic_array(x: Array[*Shape, T]) -> Array[*Shape, T]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothActualHomogeneousGenericsBothSides() {
doTest("Array[float, *tuple[float, ...], float, float]","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
T = TypeVar("T")
T1 = TypeVar("T1")
T2 = TypeVar("T2")
T3 = TypeVar("T3")
class Array(Generic[*Shape]):
...
y: Array[*tuple[float, ...]] = Array()
def expect_variadic_array(x: Array[T1, *Shape, T2, T3]) -> Array[T1, *Shape, T2, T3]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothSameExpectedAndActual() {
doTest("Array[*Shape]","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[int, *Shape, str] = Array()
def expect_variadic_array(x: Array[int, *Shape1, str]) -> Array[*Shape1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothExpectedExpand() {
doTest("Array[float, *Shape, list[str]]","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[int, float, *Shape, list[str], str] = Array()
def expect_variadic_array(x: Array[int, *Shape1, str]) -> Array[*Shape1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothExpectedExpandTwoArguments() {
doTest("Any","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
a: Array[int, float, *Shape, list[str], str] = Array()
def expect_variadic_arrays(x: Array[int, *Shape1, str], y: Array[int, float, bool, list[str], str]) -> Array[*Shape1]:
print(x, y)
expr = expect_variadic_arrays(a, a)
""");
}
public void testGenericVariadicsNotUnifiedBothExpectedExpandTwoArgumentsGenericVariadic() {
doTest("Any","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
a: Array[int, float, *Shape, list[str], str] = Array()
def expect_variadic_arrays(x: Array[int, *Shape1, str], y: Array[int, float, *Shape1, list[str], str]) -> Array[*Shape1]:
print(x, y)
expr = expect_variadic_arrays(a, a)
""");
}
public void testGenericVariadicsNotUnifiedBothExpectedExpandTwoDifferentArgumentsGenericVariadic() {
doTest("Any","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
a: Array[int, float, *Shape, list[str], str] = Array()
def expect_variadic_arrays(x: Array[int, *Shape1, str], y: Array[int, float, *Shape, bool, list[str], str]) -> Array[*Shape1] | Array[*Shape]:
print(x, y)
expr = expect_variadic_arrays(a, a)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothExpectedExpandNotExactLeft() {
doTest("Any","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[int, *Shape, list[str], str] = Array()
def expect_variadic_array(x: Array[int, float, *Shape1, str]) -> Array[*Shape1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothExpectedExpandNotExactRight() {
doTest("Any","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[int, float, *Shape, str] = Array()
def expect_variadic_array(x: Array[int, *Shape1, int, str]) -> Array[*Shape1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testGenericVariadicsNotUnifiedBothActualSwallowAllExpected() {
doTest("Any","""
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import Any
Shape = TypeVarTuple("Shape")
Shape1 = TypeVarTuple("Shape1")
T = TypeVar("T")
T1 = TypeVar("T1")
class Array(Generic[*Shape]):
...
y: Array[*Shape] = Array()
def expect_variadic_array(x: Array[int, *Shape1, str]) -> Array[*Shape1]:
print(x)
expr = expect_variadic_array(y)
""");
}
// PY-53105
public void testVariadicGenericClassOverloadedMethods() {
doTest("Array[str, int]", """
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import overload
Shape = TypeVarTuple("Shape")
Axis1 = TypeVar("Axis1")
Axis2 = TypeVar("Axis2")
Axis3 = TypeVar("Axis3")
class Array(Generic[*Shape]):
@overload
def transpose(self: Array[Axis1, Axis2]) -> Array[Axis2, Axis1]: ...
@overload
def transpose(self: Array[Axis1, Axis2, Axis3]) -> Array[Axis3, Axis2, Axis1]: ...
def transpose(self): ...
a: Array[int, str] = Array()
expr = a.transpose()
""");
}
// PY-53105
public void testVariadicGenericClassOverloadedMethodsSecondMethod() {
doTest("Array[list[int], str, int]", """
from __future__ import annotations
from typing import TypeVarTuple
from typing import TypeVar
from typing import Generic
from typing import overload
Shape = TypeVarTuple("Shape")
Axis1 = TypeVar("Axis1")
Axis2 = TypeVar("Axis2")
Axis3 = TypeVar("Axis3")
class Array(Generic[*Shape]):
@overload
def transpose(self: Array[Axis1, Axis2]) -> Array[Axis2, Axis1]: ...
@overload
def transpose(self: Array[Axis1, Axis2, Axis3]) -> Array[Axis3, Axis2, Axis1]: ...
def transpose(self): ...
a: Array[int, str, list[int]] = Array()
expr = a.transpose()
""");
}
public void testUnresolvedReturnTypeNotOverridenByAncestorAnnotation() {
doTest("Any",
"""
class Super:
def m(self) -> int:
...
class Sub(Super):
def m(self) -> Unresolved:
...
expr = Sub().m()
""");
}
public void testGenericProtocolUnificationSameTypeVar() {
doTest("list[int]",
"""
from typing import Protocol
from typing import TypeVar
T = TypeVar('T', covariant=True)
class SupportsIter(Protocol[T]):
def __iter__(self) -> T:
pass
def my_iter(x: SupportsIter[T]) -> T:
pass
class MyList:
def __iter__(self) -> list[int]:
pass
expr = my_iter(MyList())""");
}
public void testGenericProtocolUnificationSeparateTypeVar() {
doTest("list[int]",
"""
from typing import Protocol
from typing import TypeVar
T = TypeVar('T', covariant=True)
T2 = TypeVar('T2')
class SupportsIter(Protocol[T]):
def __iter__(self) -> T:
pass
def my_iter(x: SupportsIter[T2]) -> T2:
pass
class MyList:
def __iter__(self) -> list[int]:
pass
expr = my_iter(MyList())""");
}
public void testGenericProtocolUnificationGenericImplementation() {
doTest("int",
"""
from typing import Generic, Protocol, TypeVar\s
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Fooable(Protocol[T1]):
def foo(self) -> T1:
...
class MyClass(Generic[T2]):
def foo(self) -> T2:
...
def f(x: Fooable[T1]) -> T1:
...
obj: MyClass[int]
expr = f(obj)""");
}
public void testGenericProtocolUnificationNonGenericImplementationWithGenericSuperclass() {
doTest("int",
"""
from typing import Generic, Protocol, TypeVar\s
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Fooable(Protocol[T1]):
def foo(self) -> T1:
...
class Super(Generic[T2]):
def foo(self) -> T2:
...
class MyClass(Super[int]):
pass
def f(x: Fooable[T1]) -> T1:
...
obj: MyClass
expr = f(obj)""");
}
public void testGenericProtocolUnificationGenericImplementationWithGenericSuperclass() {
doTest("int",
"""
from typing import Generic, Protocol, TypeVar\s
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Fooable(Protocol[T1]):
def foo(self) -> T1:
...
class Super(Generic[T2]):
def foo(self) -> T2:
...
class MyClass(Super[T2]):
pass
def f(x: Fooable[T1]) -> T1:
...
obj: MyClass[int]
expr = f(obj)""");
}
public void testGenericProtocolUnificationGenericImplementationWithGenericSuperclassAndExtraParameter() {
doTest("int",
"""
from typing import Generic, Protocol, TypeVar\s
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Fooable(Protocol[T1]):
def foo(self) -> T1:
...
class Super(Generic[T2]):
def foo(self) -> T2:
...
class MyClass(Super[int], Generic[T1]):
pass
def f(x: Fooable[T1]) -> T1:
...
obj: MyClass[str]
expr = f(obj)""");
}
public void testGenericMethodCallUnification() {
doTest("int", """
from typing import Generic, TypeVar
T = TypeVar("T")
class Box(Generic[T]):
def __init__(self, value: T) -> None:
self.value = value
def get(self) -> T:
return self.value
box = Box(42)
expr = box.get()
""");
}
// PY-53105
public void testGenericVariadicMethodCallUnification() {
doTest("tuple[int, str, float]", """
from typing import Generic, TypeVarTuple, Tuple
Ts = TypeVarTuple("Ts")
class Box(Generic[*Ts]):
def __init__(self, value: Tuple[*Ts]) -> None:
self.value = value
def get(self):
return self.value
box = Box((42, 'a', 3.3))
expr = box.get()""");
}
public void testSingleTypeVarSpecifiedOnInheritance() {
doTest("str", """
from typing import Generic, TypeVar
T = TypeVar("T")
class Box(Generic[T]):
pass
class StrBox(Box[str]):
pass
def extract(b: Box[T]) -> T:
pass
box = StrBox()
expr = extract(box)""");
}
// PY-53105
public void testSingleTypeVarTupleSpecifiedOnInheritance() {
doTest("tuple[str, int]", """
from typing import Generic, TypeVarTuple, Tuple
Ts = TypeVarTuple("Ts")
class Box(Generic[*Ts]):
pass
class StrBox(Box[str, int]):
pass
def extract(b: Box[*Ts]) -> Tuple[*Ts]:
pass
box = StrBox()
expr = extract(box)
""");
}
public void testPartialTypeVarSpecializationOnInheritanceInherited() {
doTest("str",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Pair(Generic[T1, T2]):
pass
class StrFirstPair(Pair[str, T2]):
def __init__(self, second: T2):
pass
def first(pair: Pair[T1, T2]) -> T1:
pass
expr = first(StrFirstPair(42))""");
}
public void testPartialTypeVarSpecializationOnInheritanceInstantiated() {
doTest("int",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Pair(Generic[T1, T2]):
pass
class StrFirstPair(Pair[str, T2]):
def __init__(self, second: T2):
pass
def second(pair: Pair[T1, T2]) -> T2:
pass
expr = second(StrFirstPair(42))""");
}
public void testTypeVarsNotSpecializedOnInheritanceDistinctTypeVars() {
doTest("tuple[int, str]",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
T4 = TypeVar('T4')
T5 = TypeVar('T5')
T6 = TypeVar('T6')
class Pair(Generic[T1, T2]):
pass
class PairExt(Pair[T3, T4]):
def __init__(self, first: T3, second: T4):
pass
def to_tuple(pair: Pair[T5, T6]) -> tuple[T5, T6]:
pass
expr = to_tuple(PairExt(42, 'foo'))""");
}
public void testTypeVarsNotSpecializedOnInheritanceReusedTypeVars() {
doTest("tuple[int, str]",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Pair(Generic[T1, T2]):
pass
class PairExt(Pair[T1, T2]):
def __init__(self, first: T1, second: T2):
pass
def to_tuple(pair: Pair[T1, T2]) -> tuple[T1, T2]:
pass
expr = to_tuple(PairExt(42, 'foo'))""");
}
public void testTypeVarSpecializedOnInheritanceExtraTypeVarAdded() {
doTest("str",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
class Box(Generic[T1]):
pass
class StrBoxWithExtra(Box[str], Generic[T2]):
def __init__(self, extra: T2):
self.extra = extra
def func(b: Box[T3]) -> T3:
pass
box = StrBoxWithExtra(42)
expr = func(box)""");
}
// PY-53105
public void testTypeVarTupleSpecializedOnInheritanceExtraTypeVarAdded() {
doTest("tuple[str, int]",
"""
from typing import Generic, TypeVarTuple, Tuple
Ts1 = TypeVarTuple('Ts1')
Ts2 = TypeVarTuple('Ts2')
Ts3 = TypeVarTuple('Ts3')
class Box(Generic[*Ts1]):
pass
class StrBoxWithExtra(Box[str, int], Generic[*Ts2]):
def __init__(self, extra: Tuple[*Ts2]):
self.extra = extra
def func(b: Box[*Ts3]) -> Tuple[*Ts3]:
pass
box = StrBoxWithExtra((42, 'a', 3.3))
expr = func(box)""");
}
public void testGenericClassSpecializesInheritedParameterAndAddsNewOne() {
doTest("StrBoxWithExtra[int]",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Box(Generic[T1]):
pass
class StrBoxWithExtra(Box[str], Generic[T2]):
def __init__(self, extra: T2):
self.extra = extra
expr = StrBoxWithExtra(42)""");
}
// PY-53105
public void testGenericVariadicClassSpecializesInheritedParameterAndAddsNewOne() {
doTest("StrBoxWithExtra[int, str, float]",
"""
from typing import Generic, TypeVarTuple, Tuple
Ts1 = TypeVarTuple('Ts1')
Ts2 = TypeVarTuple('Ts2')
class Box(Generic[*Ts1]):
pass
class StrBoxWithExtra(Box[str], Generic[*Ts2]):
def __init__(self, extra: Tuple[*Ts2]):
self.extra = extra
expr = StrBoxWithExtra((42, 'a', 3.3))""");
}
// PY-70528
public void testTypeVarTupleAndUnpackFromTypingExtensions() {
doTest("tuple[int, str]",
"""
from typing_extensions import TypeVarTuple, Unpack
Ts = TypeVarTuple("Ts")
def f(*args: Unpack[Ts]) -> tuple[Unpack[Ts]]:
...
expr = f(42, "foo")
""");
}
public void testGenericSelfSpecializationInOverloadedConstructor() {
doTest("Pair[int, int]",
"""
from typing import Generic, TypeVar, overload
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Pair(Generic[T1, T2]):
@overload
def __init__(self: 'Pair[str, str]', value: str):
pass
@overload
def __init__(self: 'Pair[int, int]', value: int):
pass
expr = Pair(42)""");
}
public void testIterResultOnIterable() {
doTest("Iterator[int]",
"""
from typing import Iterable, TypeVar
T = TypeVar('T')
xs: Iterable[int]
expr = iter(xs)
""");
}
public void testNextResultOnIterator() {
doTest("int",
"""
from typing import Iterable, TypeVar
T = TypeVar('T')
xs: Iterable[int]
expr = iter(xs).__next__()
""");
}
public void testWeakUnionTypeOfOfGenericMethodCallReceiver() {
doTest("str",
"""
from typing import Any, Generic, TypeVar
T = TypeVar("T")
class Box(Generic[T]):
def get(self) -> T:
pass
class StrBox(Box[str]):
pass
receiver: Any | int | StrBox = ...
expr = receiver.get()""");
}
// PY-53105
public void testWeakUnionTypeOfOfGenericVariadicMethodCallReceiver() {
doTest("tuple[str, int, float]",
"""
from typing import Any, Generic, TypeVarTuple, Tuple
Ts = TypeVarTuple("Ts")
class Box(Generic[*Ts]):
def get(self) -> Tuple[*Ts]:
pass
class StrBox(Box[str, int, float]):
pass
receiver: Any | int | StrBox = ...
expr = receiver.get()""");
}
public void testGenericClassTypeHintedInDocstrings() {
doTest("int",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class User1(Generic[T]):
def __init__(self, x: T):
self.x = x
def get(self) -> T:
return self.x
c = User1(10)
expr = c.get()""");
}
// PY-53105
public void testGenericVariadicClassTypeHintedInDocstrings() {
doTest("tuple[int, str, float]",
"""
from typing import Generic, TypeVar, TypeVarTuple, Tuple
Ts = TypeVarTuple('Ts')
class User1(Generic[*Ts]):
def __init__(self, x: Tuple[*Ts]):
self.x = x
def get(self) -> Tuple[*Ts]:
return self.x
c = User1((1, '2', 3.3))
expr = c.get()""");
}
public void testIterOnListOfListsResult() {
doTest("Iterator[list[int]]",
"expr = iter([[1, 2, 3]])");
}
public void testSwappingTypeParametersInConstructor() {
doTest("Pair[str, int]",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Pair(Generic[T1, T2]):
def __init__(self, pair: 'Pair[T2, T1]'):
pass
int_then_str: Pair[int, str] = ...()
expr = Pair(int_then_str)""");
}
public void testDefaultDictFromDict() {
doTest("defaultdict[Any, dict]",
"from collections import defaultdict\n" +
"expr = defaultdict(dict)");
}
public void testDecoratorWithArgumentCalledAsFunction() {
doTest("(str) -> int",
"""
from typing import Callable, TypeVar
S = TypeVar('S')
T = TypeVar('T')
def dec(t: T):
def g(fun: Callable[[], S]) -> Callable[[T], S]:
...
return g
def func() -> int:
...
expr = dec('foo')(func)""");
}
// PY-53105
public void testGenericVariadicDecoratorWithArgumentCalledAsFunction() {
doTest("(str, int) -> tuple[int, str, float]",
"""
from typing import Callable, TypeVar, TypeVarTuple, Tuple
Ss = TypeVarTuple('Ss')
Ts = TypeVarTuple('Ts')
def dec(ts: Tuple[*Ts]):
def g(fun: Callable[[], Tuple[*Ss]]) -> Callable[[*Ts], Tuple[*Ss]]:
...
return g
def func() -> Tuple[int, str, float]:
...
expr = dec(('foo', 42))(func)""");
}
public void testGenericParameterOfExpectedCallable() {
doTest("int",
"""
from typing import Callable, Generic, TypeVar
T = TypeVar('T')
class Super(Generic[T]):
pass
class Sub(Super[T]):
pass
def f(x: Callable[[Sub[T]], None]) -> T:
pass
def g(x: Super[int]):
pass
expr = f(g)""");
}
// PY-53105
public void testGenericVariadicParameterOfExpectedCallable() {
doTest("tuple[int, str, float]",
"""
from typing import Callable, Generic, TypeVar, TypeVarTuple, Tuple
Ts = TypeVarTuple('Ts')
class Super(Generic[*Ts]):
pass
class Sub(Super[*Ts]):
pass
def f(x: Callable[[Sub[*Ts]], None]) -> Tuple[*Ts]:
pass
def g(x: Super[int, str, float]):
pass
expr = f(g)""");
}
// PY-53522
public void testGenericIteratorParameterizedWithAnotherGeneric() {
doTest("Entry[str]",
"""
from typing import Iterator, Generic, TypeVar
T = TypeVar("T")
class Entry(Generic[T]):
pass
class MyIterator(Iterator[Entry[T]]):
def __next__(self) -> Entry[T]: ...
def iter_entries(path: T) -> MyIterator[T]: ...
def main() -> None:
for x in iter_entries("some path"):
expr = x
""");
}
// PY-53105
public void testGenericVariadicIteratorParameterizedWithAnotherGenericVariadic() {
doTest("Entry[str, int, float]",
"""
from typing import Iterator, Generic, Tuple, TypeVarTuple
Ts = TypeVarTuple("Ts")
class Entry(Generic[*Ts]):
pass
class MyIterator(Iterator[Entry[*Ts]]):
def __next__(self) -> Entry[*Ts]: ...
def iter_entries(path: Tuple[*Ts]) -> MyIterator[*Ts]: ...
def main() -> None:
for x in iter_entries(("some path", 1, 1.1)):
expr = x
""");
}
// PY-53522
public void testGenericParameterizedWithGeneric() {
doTest("list[int]",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class Box(Generic[T]):
def get(self) -> T:
pass
class ListBox(Box[list[T]]):
pass
xs: ListBox[int] = ...
expr = xs.get()
""");
}
// PY-53105
public void testGenericVariadicParameterizedWithGenericVariadic() {
doTest("tuple[tuple[int, str]]",
"""
from typing import Generic, TypeVar, TypeVarTuple, Tuple
Ts = TypeVarTuple('Ts')
class Box(Generic[*Ts]):
def get(self) -> Tuple[*Ts]:
pass
class ListBox(Box[Tuple[*Ts]]):
pass
xs: ListBox[int, str] = ...
expr = xs.get()
""");
}
// PY-52656
public void testClassInheritsGenericToOrderTypeParameters() {
doTest("str",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Box(Generic[T1]):
def get(self) -> T1:
pass
class Pair(Box[T2], Generic[T1, T2]):
pass
xs: Pair[int, str] = ...
expr = xs.get()
""");
}
// PY-54336
public void testReusedTypeVarsAndInheritanceDoNotCauseRecursiveSubstitution() {
doTest("Sub[T1]",
"""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class Super(Generic[T1]):
pass
class Sub(Super[T2]):
def __init__(self, xs: list[T2]):
pass
def func(xs: list[T1]):
expr = Sub(xs)
""");
}
// PY-50542
public void testReusedTypeVarsInOppositeOrderDoNotCauseRecursiveSubstitution() {
doTest("str",
"""
from typing import TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
def f(x: T1, y: T2) -> T2:
pass
def g(x: T2, y: T1):
return f(x, y)
expr = g(42, 'foo')
""");
}
// PY-56541
public void testRecursiveTypedDictDeclarations() {
//RecursionManager.assertOnRecursionPrevention(getTestRootDisposable());
StringBuilder text = new StringBuilder("""
from __future__ import annotations
from typing import TypedDict, Union
""");
int typedDictCount = 30;
for (int i = 1; i <= typedDictCount; i++) {
text.append(String.format("""
class D%d(TypedDict):
key%d: Alias
""", i, i));
}
text.append("Alias = Union[");
for (int i = 1; i <= typedDictCount; i++) {
text.append("D").append(i).append(", ");
}
text.append("]\n");
text.append("expr: D1\n");
myFixture.configureByText(PythonFileType.INSTANCE, text.toString());
PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getProject(), expr.getContainingFile());
PyType type = codeAnalysis.getType(expr);
assertInstanceOf(type, PyTypedDictType.class);
assertTrue(countTypes(type) < 100);
}
public static int countTypes(@Nullable PyType type) {
int result = 1;
if (type instanceof PyUnionType pyUnionType) {
for (PyType member : pyUnionType.getMembers()) {
result += countTypes(member);
}
}
else if (type instanceof PyCollectionType pyCollectionType) {
for (PyType member : pyCollectionType.getElementTypes()) {
result += countTypes(member);
}
}
return result;
}
// PY-59548
public void testGenericBaseClassSpecifiedThroughAlias() {
doTest("int",
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class Super(Generic[T]):
pass
Alias = Super
class Sub(Alias[T]):
pass
def f(x: Super[T]) -> T:
pass
arg: Sub[int]
expr = f(arg)
""");
}
// PY-59548
public void testGenericBaseClassSpecifiedThroughAliasInImportedFile() {
doMultiFileStubAwareTest("int",
"""
from typing import TypeVar
from mod import Sub, Super
T = TypeVar('T')
def f(x: Super[T]) -> T:
pass
arg: Sub[int]
expr = f(arg)
""");
}
public void testTypeOfArgsParameterAnnotatedWithTypeVarTuple() {
doTest("tuple[*Ts]",
"""
from typing import TypeVarTuple
Ts = TypeVarTuple("Ts")
def f(*args: *Ts):
expr = args
""");
}
public void testTypeOfArgsParameterAnnotatedWithBoundUnpackedTuple() {
doTest("tuple[int, str]",
"""
def f(*args: *tuple[int, str]):
expr = args
""");
}
public void testTypeOfArgsParameterAnnotatedWithUnboundUnpackedTuple() {
doTest("tuple[int, ...]",
"""
def f(*args: *tuple[int, ...]):
expr = args
""");
}
// PY-61883
public void testSimpleGenericClassWithPEP695TypeParameterSyntax() {
doTest("str", """
class MyStack[T]:
def pop(self) -> T:
pass
stack = MyStack[str]()
expr = stack.pop()
""");
}
// PY-61883
public void testSimpleGenericFunWithPEP695Syntax() {
doTest("int", """
def foo[T](x: T) -> T:
return x
expr = foo(1)
""");
}
// PY-61883
public void testGenericClassParameterizedWithTypeOfConstructorArgumentWithPEP695Syntax() {
doTest("C[int]", """
class C[T]:
def __init__(self, x: T):
pass
expr = C(10)
""");
}
// PY-61883
public void testGenericBaseWithPEP695SyntaxClassSpecifiedThroughAlias() {
doTest("int",
"""
class Super[T]:
pass
Alias = Super
class Sub[T](Alias[T]):
pass
def f[T](x: Super[T]) -> T:
pass
arg: Sub[int]
expr = f(arg)
""");
}
// PY-61883
public void testExplicitlyParametrizedGenericClassInstanceWithPEP695Syntax() {
doTest("Node[int]",
"""
from typing import List
class Node[T]:
def __init__(self, children: List[T]):
self.children = children
expr = Node[int]()""");
}
// PY-61883
public void testParameterizedWithPEP695SyntaxClassInheritance() {
doTest("int",
"""
class B[T]:
def foo(self) -> T:
pass
class C[T](B[T]):
def __init__(self, x: T):
pass
expr = C(10).foo()
""");
}
// PY-61883
public void testGenericFieldOfClassParameterizedWithNewPEP695Syntax() {
doTest("str",
"""
class C[T]:
def __init__(self, foo: T):
self.foo = foo
def f() -> C[str]:
return C('test')
x = f()
expr = x.foo
""");
}
// PY-61883
public void testMultiTypeExplicitlyParametrizedGenericClassInstanceWithPEP695Syntax() {
doTest("float",
"""
class FirstType[T]: pass
class SecondType[V]: pass
class ThirdType[Z]: pass
class Clazz[T, V, Z](FirstType[T], SecondType[V], ThirdType[Z]):
first: T
second: V
third: Z
def __init__(self):
pass
node = Clazz[str, int, float]()
expr = node.third""");
}
// PY-61883
public void testGenericUserFunctionWithManyParamsAndNestedCallWithPEP695Syntax() {
doTest("tuple[bool, int, str]",
"""
def myid[T](x: T) -> T:
pass
def f[T, U, V](x: T, y: U, z: V):
return myid(x), myid(y), myid(z)
expr = f(True, 1, 'foo')
""");
}
// PY-61883
public void testGenericSubstitutionInDeepHierarchyWithPEP695Syntax() {
doTest("int",
"""
class Root[T1, T2]:
def m(self) -> T2:
pass
class Base3[T1](Root[T1, int]):
pass
class Base2[T1](Base3[T1]):
pass
class Base1[T1](Base2[T1]):
pass
class Sub[T1](Base1[T1]):
pass
expr = Sub().m()
""");
}
// PY-61883
public void testGenericClassSpecializesInheritedParameterAndAddsNewOneWithPEP695Syntax() {
doTest("StrBoxWithExtra[int]",
"""
class Box[T]:
pass
class StrBoxWithExtra[T2](Box[str]):
def __init__(self, extra: T2):
self.extra = extra
expr = StrBoxWithExtra(42)""");
}
// PY-61883
public void testSimpleTypeAliasWithPEP695Syntax() {
doTest("str",
"""
type myType = str
def foo() -> myType:
pass
expr = foo()
""");
}
// PY-61883
public void testGenericTypeAliasForTupleWithPEP695Syntax() {
doTest("tuple[int, int]",
"""
type Pair[T] = tuple[T, T]
expr: Pair[int]""");
}
// PY-61883
public void testGenericTypeAliasParameterizedInTwoStepsWithPEP695Syntax() {
doTest("dict[int, str]",
"""
type Alias1[T1, T2] = dict[T1, T2]
type Alias2[T2] = Alias1[int, T2]
expr: Alias2[str]""");
}
// PY-61883
public void testGenericClassDefinedInAnotherFileWithPEP695Syntax() {
doMultiFileStubAwareTest("int",
"""
from a import Stack
expr = Stack[int]().pop()""");
}
// PY-61883
public void testRecursiveTypeAliasInAnotherFilePEP695Syntax() {
doMultiFileStubAwareTest("list | int",
"""
from a import MyType
expr: MyType = ...""");
}
// PY-61883
public void testTrivialRecursiveTypeAliasInAnotherFileWithPEP695Syntax() {
doMultiFileStubAwareTest("Any",
"""
from a import alias
expr: alias""");
}
// PY-61883
public void testGenericTypeAliasInAnotherFileWithPEP695Syntax() {
doMultiFileStubAwareTest("dict[str, int]",
"""
from a import alias
expr: alias[str, int]""");
}
// PY-61883
public void testGenericFunctionInAnotherFileWithPEP695Syntax() {
doMultiFileStubAwareTest("int",
"""
from a import foo
expr = foo(42)""");
}
// PY-61883
public void testGenericProtocolUnificationSameTypeVarWithPEP695Syntax() {
doTest("list[int]",
"""
from typing import Protocol
class SupportsIter[T](Protocol):
def __iter__(self) -> T:
pass
def my_iter[T](x: SupportsIter[T]) -> T:
pass
class MyList:
def __iter__(self) -> list[int]:
pass
expr = my_iter(MyList())""");
}
// PY-61883
public void testGenericProtocolUnificationSeparateTypeVarWithPEP695Syntax() {
doTest("list[int]",
"""
from typing import Protocol
class SupportsIter[T](Protocol):
def __iter__(self) -> T:
pass
def my_iter[T2](x: SupportsIter[T2]) -> T2:
pass
class MyList:
def __iter__(self) -> list[int]:
pass
expr = my_iter(MyList())""");
}
// PY-61883
public void testGenericProtocolUnificationGenericImplementationWithGenericSuperclassWithPEP695Syntax() {
doTest("int",
"""
from typing import Protocol
class Fooable[T1](Protocol):
def foo(self) -> T1:
...
class Super[T2]:
def foo(self) -> T2:
...
class MyClass[T2](Super[T2]):
pass
def f[T1](x: Fooable[T1]) -> T1:
...
obj: MyClass[int]
expr = f(obj)""");
}
// PY-61883
public void testGenericVariadicByCallableWithPEP695Syntax() {
doTest("tuple[int, str]",
"""
from typing import Callable, Tuple
def foo[*Ts](f: Callable[[*Ts], Tuple[*Ts]]) -> Tuple[*Ts]: ...
def bar(a: int, b: str) -> Tuple[int, str]: ...
expr = foo(bar)
""");
}
// PY-61883
public void testGenericVariadicByCallablePrefixSuffixWithPEP695Syntax() {
doTest("tuple[str, str, float, int, bool]",
"""
from typing import Callable, Tuple
def foo[T, *Ts](f: Callable[[int, *Ts, T], Tuple[T, *Ts]]) -> Tuple[str, *Ts, int, T]: ...
def bar(a: int, b: str, c: float, d: bool) -> Tuple[bool, str, float]: ...
expr = foo(bar)
""");
}
// PY-61883
public void testGenericVariadicClassWithPEP695Syntax() {
doTest("A[float, bool, list[str]]",
"""
from typing import Generic, Tuple
class A[*Ts]:
def __init__(self, value: Tuple[int, *Ts]) -> None:
self.field: Tuple[int, *Ts] = value
tpl = (42, 1.1, True, ['42'])
expr = A(tpl)
""");
}
// PY-61883
public void testGenericVariadicClassFieldWithPEP695Syntax() {
doTest("tuple[int, float, bool, list[str]]",
"""
from typing import Tuple
class A[*Ts]:
def __init__(self, value: Tuple[int, *Ts]) -> None:
self.field: Tuple[int, *Ts] = value
tpl = (42, 1.1, True, ['42'])
a = A(tpl)
expr = a.field
""");
}
// PY-61883
public void testGenericVariadicAndGenericClassWithPEP695Syntax() {
doTest("A[int | str, int | str, list[int]]",
"""
from __future__ import annotations
from typing import Tuple
class A[T, *Ts, T1]:
def __init__(self, t: T, tpl: Tuple[*Ts], t1: T1) -> None:
...
x: int | str
expr = A(x, (x,), [1])
""");
}
// PY-61883
public void testGenericVariadicClassMethodAddAxisPrefixWithPEP695Syntax() {
doTest("Array[str, int, bool]",
"""
from __future__ import annotations
from typing import Tuple, NewType
class Array[*Shape]:
def __init__(self, shape: Tuple[*Shape]):
self._shape: Tuple[*Shape] = shape
def add_axis_prefix[T](self, t: T) -> Array[T, *Shape]: ...
shape = (42, True)
arr: Array[int, bool] = Array(shape)
expr = arr.add_axis_prefix('')
""");
}
// PY-61883
public void testGenericVariadicStarArgsAndTypeVarsWithPEP695Syntax() {
doTest("tuple[str, list[int], bool, int]",
"""
from typing import TypeVarTuple, Tuple, TypeVar
def args_to_tuple[T1, T2, *Ts](t1: T1, t2: T2, *args: *Tuple[T2, *Ts, float]) -> Tuple[T2, *Ts, T1]: ...
expr = args_to_tuple(1, 'a', 'a', [1], True, 3.3)
""");
}
// PY-61883
public void testTypeAliasStatementTypeNotInterpretedAsAssignedTypeOutsideOfTypeHint() {
doTest("TypeAliasType",
"""
type myType = str
expr = myType
""");
}
// PY-61883
public void testTypeParameterTypeIsTypingTypeVar() {
doTest("TypeVar",
"""
def foo[T]():
expr = T
""");
}
// PY-61883
public void testTypeParameterTypeIsTypingParamSpec() {
doTest("ParamSpec",
"""
def foo[**P]():
expr = P
""");
}
// PY-61883
public void testTypeParameterTypeIsTypingTypeVarTuple() {
doTest("TypeVarTuple",
"""
def foo[*Ts]():
expr = Ts
""");
}
// PY-64481
public void testIterationOverRegularStrEmitsStrNotLiteralString() {
doTest("str",
"""
s = "foo"
for expr in s:
pass
""");
}
// PY-64481
public void testForLoopTargetTypeComesFromCorrectDunderIterOverload() {
doTest("Super",
"""
from typing import overload
class Super:
@overload
def __iter__(self: 'Sub') -> list['Sub']: ...
@overload
def __iter__(self) -> list['Super']: ...
class Sub(Super): ...
for expr in Super():
pass
""");
}
// PY-36444
public void testContextManagerDecorator() {
doTest("str",
"""
from contextlib import contextmanager
@contextmanager
def generator_function():
yield "some value"
with generator_function() as value:
expr = value
""");
}
// PY-36444
public void testTextIOInferredWithContextManagerDecorator() {
doTest("TextIO",
"""
from contextlib import contextmanager
@contextmanager
def open_file(name: str):
f = open(name)
yield f
f.close()
cm = open_file(__file__)
with cm as file:
expr = file
""");
}
// PY-70484
public void testUnboundParamSpecFromUnresolvedArgumentReplacedWithArgsKwargs() {
doTest("(args: Any, kwargs: Any) -> str",
"""
from typing import Callable, Any, ParamSpec
P = ParamSpec("P")
def deco(fn: Callable[P, Any]) -> Callable[P, str]:
return ...
expr = deco(unresolved)
""");
}
// PY-70484
public void testUnboundParamSpecThatCannotBeBoundThroughParametersLeftIntact() {
doTest("((ParamSpec(\"P\")) -> Any) -> (ParamSpec(\"P\")) -> int",
"""
from typing import Callable, Any, ParamSpec
P = ParamSpec("P")
def deco() -> Callable[[Callable[P, Any]], Callable[P, int]]
return ...
expr = deco()
""");
}
public void testMixingUpConcatenateAndTypeVarTuple() {
doTest("(int, int, x: int, y: str) -> int",
"""
from typing import TypeVarTuple, ParamSpec, Callable, Any, Concatenate, reveal_type
Ts = TypeVarTuple('Ts')
P = ParamSpec('P')
def f(prefix: tuple[*Ts], fn: Callable[P, Any]) -> Callable[Concatenate[*Ts, P], int]:
...
def g(x: int, y: str) -> bool:
...
expr = f((1, 2), g)
""");
}
public void testParamSpecInConcatenateMappedToAnotherParamSpec() {
doTest("(int, ParamSpec(\"P1\")) -> Any",
"""
from typing import Callable, Any, ParamSpec, Concatenate
P1 = ParamSpec('P1')
P2 = ParamSpec('P2')
def f(fn: Callable[P1, Any]):
expr = g(fn)
def g(fn: Callable[P2, Any]) -> Callable[Concatenate[int, P2], Any]:
...
""");
}
// PY-71002
public void testTypeVarDefaultsClassReference() {
doTest("Type[slice[int, int, int | None]]", """
from typing import TypeVar, Generic
StartT = TypeVar("StartT", default=int)
StopT = TypeVar("StopT", default=StartT)
StepT = TypeVar("StepT", default=int | None)
class slice(Generic[StartT, StopT, StepT]): ...
expr = slice
""");
}
// PY-71002
public void testTypeVarDefaultsClassReferenceNewSyntax() {
doTest("Type[slice[int, int, int | None]]", """
class slice[StartT = int, StopT = StartT, StepT = int | None]: ...
expr = slice
""");
}
// PY-71002
public void testTypeVarDefaultsClassCall() {
doTest("slice[int, int, int | None]", """
from typing import TypeVar, Generic
StartT = TypeVar("StartT", default=int)
StopT = TypeVar("StopT", default=StartT)
StepT = TypeVar("StepT", default=int | None)
class slice(Generic[StartT, StopT, StepT]): ...
expr = slice()
""");
}
// PY-71002
public void testTypeVarDefaultsClassCallNewSyntax() {
doTest("slice[int, int, int | None]", """
class slice[StartT = int, StopT = StartT, StepT = int | None]: ...
expr = slice()
""");
}
// PY-71002
public void testTypeVarDefaultsClassCallParameterizedWithOneType() {
doTest("slice[str, str, int | None]", """
from typing import TypeVar, Generic
StartT = TypeVar("StartT", default=int)
StopT = TypeVar("StopT", default=StartT)
StepT = TypeVar("StepT", default=int | None)
class slice(Generic[StartT, StopT, StepT]): ...
expr = slice[str]()
""");
}
// PY-71002
public void testTypeVarDefaultsClassCallParameterizedWithOneTypeNewSyntax() {
doTest("slice[str, str, int | None]", """
class slice[StartT = int, StopT = StartT, StepT = int | None]: ...
expr = slice[str]()
""");
}
// PY-71002
public void testTypeVarDefaultsClassCallFullyParameterized() {
doTest("slice[str, bool, complex]", """
from typing import TypeVar, Generic
StartT = TypeVar("StartT", default=int)
StopT = TypeVar("StopT", default=StartT)
StepT = TypeVar("StepT", default=int | None)
class slice(Generic[StartT, StopT, StepT]): ...
expr = slice[str, bool, complex]()
""");
}
// PY-71002
public void testTypeVarDefaultsClassCallFullyParameterizedNewSyntax() {
doTest("slice[str, bool, complex]", """
class slice[StartT = int, StopT = StartT, StepT = int | None]: ...
expr = slice[str, bool, complex]()
""");
}
// PY-71002
public void testTypeVarDefaultsListDefault() {
doTest("Type[Bar[int, list[int]]]", """
from typing import TypeVar, Generic
T = TypeVar("T")
ListDefaultT = TypeVar("ListDefaultT", default=list[T])
class Bar(Generic[T, ListDefaultT]):
def __init__(self, x: T, y: ListDefaultT): ...
expr = Bar[int]
""");
}
// PY-71002
public void testTypeVarDefaultsClassWithInitMethodReference() {
doTest("Type[Bar[Any, list]]", """
from typing import TypeVar, Generic
Z1 = TypeVar("Z1")
ListDefaultT = TypeVar("ListDefaultT", default=list[Z1])
class Bar(Generic[Z1, ListDefaultT]):
def __init__(self, x: Z1, y: ListDefaultT): ...
expr = Bar
""");
}
// PY-71002
public void testTypeVarDefaultsClassWithInitMethodReferenceNewSyntax() {
doTest("Type[Bar[Any, list]]", """
from typing import TypeVar, Generic
class Bar[Z1, ListDefaultT = list[Z1]]:
def __init__(self, x: Z1, y: ListDefaultT): ...
expr = Bar
""");
}
// PY-71002
public void testTypeVarDefaultsClassWithInitMethodReferenceParameterizedWithOneType() {
doTest("Type[Bar[int, list[int]]]", """
from typing import TypeVar, Generic
Z1 = TypeVar("Z1")
ListDefaultT = TypeVar("ListDefaultT", default=list[Z1])
class Bar(Generic[Z1, ListDefaultT]):
def __init__(self, x: Z1, y: ListDefaultT): ...
expr = Bar[int]
""");
}
// PY-71002
public void testTypeVarDefaultsClassWithInitMethodCallParameterizedWithOneTypeAndConstructorArguments() {
doTest("Bar[int, list[int]]", """
from typing import TypeVar, Generic
Z1 = TypeVar("Z1")
ListDefaultT = TypeVar("ListDefaultT", default=list[Z1])
class Bar(Generic[Z1, ListDefaultT]):
def __init__(self, x: Z1, y: ListDefaultT): ...
expr = Bar[int](0, [])
""");
}
// PY-71002
public void testTypeVarDefaultsClassWithInitMethodCallParameterizedWithTwoTypesAndConstructorArguments() {
doTest("Bar[int, list[str]]", """
from typing import TypeVar, Generic
Z1 = TypeVar("Z1")
ListDefaultT = TypeVar("ListDefaultT", default=list[Z1])
class Bar(Generic[Z1, ListDefaultT]):
def __init__(self, x: Z1, y: ListDefaultT): ...
expr = Bar[int, list[str]](0, [])
""");
}
// PY-71002
public void testTypeVarDefaultsClassWithInitMethodCallParameterizedWithTwoTypesAndConstructorArgumentsChangingDefaultType() {
doTest("Bar[int, str]", """
from typing import TypeVar, Generic
Z1 = TypeVar("Z1")
ListDefaultT = TypeVar("ListDefaultT", default=list[Z1])
class Bar(Generic[Z1, ListDefaultT]):
def __init__(self, x: Z1, y: ListDefaultT): ...
expr = Bar[int, str](0, "")
""");
}
// PY-71002
public void testTypeVarDefaultsSubclassedClassReference() {
doTest("Type[Bar[str]]", """
from typing import TypeVar, Generic, TypeAlias
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
class SubclassMe(Generic[T1, DefaultStrT]):
x: DefaultStrT
class Bar(SubclassMe[int, DefaultStrT]): ...
expr = Bar
""");
}
// PY-71002
public void testTypeVarDefaultsSubclassedClassInstance() {
doTest("Bar[str]", """
from typing import TypeVar, Generic, TypeAlias
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
class SubclassMe(Generic[T1, DefaultStrT]):
x: DefaultStrT
class Bar(SubclassMe[int, DefaultStrT]): ...
expr = Bar()
""");
}
// PY-71002
public void testTypeVarDefaultsSubclassedParameterizedClassInstance() {
doTest("Bar[bool]", """
from typing import TypeVar, Generic, TypeAlias
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
class SubclassMe(Generic[T1, DefaultStrT]):
x: DefaultStrT
class Bar(SubclassMe[int, DefaultStrT]): ...
expr = Bar[bool]()
""");
}
// PY-71002
public void testTypeVarDefaultsSubclassedWithClassAttribute() {
doTest("str", """
from typing import TypeVar, Generic, TypeAlias
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
class SubclassMe(Generic[T1, DefaultStrT]):
x: DefaultStrT
class Foo(SubclassMe[float]): ...
expr = Foo().x
""");
}
// PY-71002
public void testReferenceToTypeVarTupleWithDefaultIsParameterizedType() {
doTest("Type[Foo[str, int]]", """
from typing import Generic, TypeVarTuple, Unpack
DefaultTs = TypeVarTuple("DefaultTs", default=Unpack[tuple[str, int]])
class Foo(Generic[*DefaultTs]): ...
expr = Foo
""");
}
// PY-71002
public void testTypeVarTupleWithDefault() {
doTest("Foo[str, int]", """
from typing import Generic, TypeVarTuple, Unpack
DefaultTs = TypeVarTuple("DefaultTs", default=Unpack[tuple[str, int]])
class Foo(Generic[*DefaultTs]): ...
expr = Foo()
""");
}
// PY-71002
public void testTypeVarTupleWithDefaultsClassInstanceNewSyntax() {
doTest("Foo[str, int]", """
from typing import Unpack
class Foo[*DefaultTs = Unpack[tuple[str, int]]]: ...
expr = Foo()
""");
}
// PY-71002
public void testTypeVarTupleWithDefaultOverridenByExplicit() {
doTest("Foo[bool, float]", """
from typing import Generic, TypeVarTuple, Unpack
DefaultTs = TypeVarTuple("DefaultTs", default=Unpack[tuple[str, int]])
class Foo(Generic[*DefaultTs]): ...
expr = Foo[bool, float]()
""");
}
// PY-71002
public void testTypeVarTupleWithDefaultParameterizedWithAnotherGeneric() {
doTest("Foo[list, list, int]", """
from typing import Generic, TypeVarTuple, Unpack, TypeVar
T = TypeVar("T", default=list)
DefaultTs = TypeVarTuple("DefaultTs", default=Unpack[tuple[T, int]])
class Foo(Generic[T, *DefaultTs]): ...
expr = Foo()
""");
}
// PY-71002
public void testParamSpecWithDefaultsClassReference() {
doTest("Type[Foo[[str, int]]]", """
from typing import ParamSpec, Generic
DefaultP = ParamSpec("DefaultP", default=[str, int])
class Foo(Generic[DefaultP]): ...
expr = Foo
""");
}
// PY-71002
public void testParamSpecWithDefaultsClassReferencesNewSyntax() {
doTest("Type[Foo[[str, int]]]", """
class Foo[**P = [str, int]]: ...
expr = Foo
""");
}
// PY-71002
public void testParamSpecWithDefaultsClassInstance() {
doTest("Foo[[str, int]]", """
from typing import ParamSpec, Generic
DefaultP = ParamSpec("DefaultP", default=[str, int])
class Foo(Generic[DefaultP]): ...
expr = Foo()
""");
}
// PY-71002
public void testParamSpecWithEmptyDefaultsClassInstance() {
doTest("Foo[[]]", """
from typing import ParamSpec, Generic
DefaultP = ParamSpec("DefaultP", default=[])
class Foo(Generic[DefaultP]): ...
expr = Foo()
""");
}
// PY-71002
public void testParamSpecWithDefaultsClassInstanceNewSyntax() {
doTest("Foo[[str, int]]", """
class Foo[**P = [str, int]]: ...
expr = Foo()
""");
}
// PY-71002
public void testParamSpecWithEmptyDefaultsClassInstanceNewSyntax() {
doTest("Foo[[]]", """
class Foo[**P = []]: ...
expr = Foo()
""");
}
// PY-71002
public void testParamSpecWithDefaultsParameterizedClassInstance() {
doTest("Foo[[int, bool]]", """
from typing import ParamSpec, Generic
DefaultP = ParamSpec("DefaultP", default=[str, int])
class Foo(Generic[DefaultP]): ...
expr = Foo[[int, bool]]()
""");
}
// PY-71002
public void testNewStyleGenericFunctionWithDefault() {
doTest("int", """
def foo[T = int](x: T = None) -> T: ...
expr = foo()
""");
}
// PY-71002
public void testTypeVarDefaultsEmptyConstructorCall() {
doTest("Box[int, str, bool]", """
from typing import TypeVar, Generic
T = TypeVar("T", default=int)
T1 = TypeVar("T1", default=str)
T2 = TypeVar("T2", default=bool)
class Box(Generic[T, T1, T2]):
def __init__(self, a: T = None, b: T1 = None, c: T2 = None):
self.value = a
self.value1 = b
self.value2 = c
expr = Box()
""");
}
// PY-71002
public void testTypeVarDefaultsDefaultOverridenByExplicitConstructorArgument() {
doTest("Box[str, str, bool]", """
from typing import TypeVar, Generic
T = TypeVar("T", default=int)
T1 = TypeVar("T1", default=str)
T2 = TypeVar("T2", default=bool)
class Box(Generic[T, T1, T2]):
def __init__(self, a: T = None, b: T1 = None, c: T2 = None):
self.value = a
self.value1 = b
self.value2 = c
expr = Box("str")
""");
}
// PY-71002
public void testTypeVarWithDefaultsMethodReturnType() {
doTest("int", """
from typing import TypeVar, Generic
DefaultIntT = TypeVar('DefaultIntT', default=int)
class Test(Generic[DefaultIntT]):
def foo(self) -> DefaultIntT: ...
expr = Test().foo()
""");
}
// PY-71002
public void testParamSpecWithDefaultsExtendedCase() {
doTest("(float, bool) -> int | None", """
from typing import Callable, TypeVar, Optional, ParamSpec
T = TypeVar('T', default=int)
P = ParamSpec('P', default=[float, bool])
def catch_exception(function: Callable[P, T]) -> Callable[P, Optional[T]]:
def decorator(*args: P.args, **kwargs: P.kwargs) -> Optional[T]:...
return decorator
expr = catch_exception()
""");
}
// PY-71002
public void testParamSpecWithEmptyDefaultsExtendedCase() {
doTest("() -> int | None", """
from typing import Callable, TypeVar, Optional, ParamSpec
T = TypeVar('T', default=int)
P = ParamSpec('P', default=[])
def catch_exception(function: Callable[P, T]) -> Callable[P, Optional[T]]:
def decorator(*args: P.args, **kwargs: P.kwargs) -> Optional[T]:...
return decorator
expr = catch_exception()
""");
}
// PY-71002
public void testParamSpecWithDefaultsExtendedCaseDefaultsOverridden() {
doTest("(a: str, b: int, c: list[float]) -> float | None", """
from typing import Callable, TypeVar, Optional
from typing_extensions import ParamSpec # or `typing` for `python>=3.10`
T = TypeVar('T', default=int)
P = ParamSpec('P', default=[float, bool])
def catch_exception(function: Callable[P, T]) -> Callable[P, Optional[T]]:
def decorator(*args: P.args, **kwargs: P.kwargs) -> Optional[T]:...
return decorator
def some_func(a: str, b: int, c: list[float]) -> float: ...
expr = catch_exception(some_func)
""");
}
// PY-71002
public void testTypeVarWithDefaultsClassVariable() {
doTest("int", """
from typing import TypeVar, Generic
DefaultIntT = TypeVar('DefaultIntT', default=int)
class Test(Generic[DefaultIntT]):
x: DefaultIntT
expr = Test().x
""");
}
// PY-71002
public void testTypeVarWithDefaultsClassVariableOverriden() {
doTest("str", """
from typing import TypeVar, Generic
DefaultIntT = TypeVar('DefaultIntT', default=int)
class Test(Generic[DefaultIntT]):
x: DefaultIntT
expr = Test[str]().x
""");
}
// PY-71002
public void testTypeVarWithDefaultsClassVariableNewSyntax() {
doTest("int", """
class Test[DefaultIntT = int]:
x: DefaultIntT
expr = Test().x
""");
}
// PY-71002
public void testTypeVarWithDefaultClassVariableTypeDefinedViaAnotherTypeVarWithNewSyntax() {
doTest("int", """
class Test[T = int, U = T]:
x: U
expr = Test().x
""");
}
// PY-71002
public void testTypeVarWithDefaultsClassVariableOverridenNewSyntax() {
doTest("str", """
class Test[DefaultIntT = int]:
x: DefaultIntT
expr = Test[str]().x
""");
}
// PY-71002
public void testTypeVarWithDefaultsClassVariableAccessViaReference() {
doTest("int", """
from typing import TypeVar, Generic
DefaultIntT = TypeVar('DefaultIntT', default=int)
class Test(Generic[DefaultIntT]):
x: DefaultIntT
expr = Test.x
""");
}
// PY-71002
public void testMixedTypeVarsWithDefaultsAndNonDefaults() {
doTest("AllTheDefaults[int, complex, str, int, bool]", """
from typing import TypeVar, Generic
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
DefaultIntT = TypeVar("DefaultIntT", default=int)
DefaultBoolT = TypeVar("DefaultBoolT", default=bool)
class AllTheDefaults(Generic[T1, T2, DefaultStrT, DefaultIntT, DefaultBoolT]): ...
expr = AllTheDefaults[int, complex]()
""");
}
// PY-71002
public void testMixedTypeVarsWithDefaultsAndNonDefaultsReferenceType() {
doTest("Type[AllTheDefaults[int, complex, str, int, bool]]", """
from typing import TypeVar, Generic
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
DefaultIntT = TypeVar("DefaultIntT", default=int)
DefaultBoolT = TypeVar("DefaultBoolT", default=bool)
class AllTheDefaults(Generic[T1, T2, DefaultStrT, DefaultIntT, DefaultBoolT]): ...
expr = AllTheDefaults[int, complex]
""");
}
// PY-71002
public void testMixedTypeVarsWithDefaultsAndNonDefaultsOneTypeParamMissing() {
doTest("AllTheDefaults[int, Any, str, int, bool]", """
from typing import TypeVar, Generic
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
DefaultIntT = TypeVar("DefaultIntT", default=int)
DefaultBoolT = TypeVar("DefaultBoolT", default=bool)
class AllTheDefaults(Generic[T1, T2, DefaultStrT, DefaultIntT, DefaultBoolT]): ...
expr = AllTheDefaults[int]()
""");
}
// PY-71002
public void testMixedTypeVarsWithDefaultsAndNonDefaultsTwoTypeParamsMissing() {
doTest("AllTheDefaults[Any, Any, str, int, bool]", """
from typing import TypeVar, Generic
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
DefaultIntT = TypeVar("DefaultIntT", default=int)
DefaultBoolT = TypeVar("DefaultBoolT", default=bool)
class AllTheDefaults(Generic[T1, T2, DefaultStrT, DefaultIntT, DefaultBoolT]): ...
expr = AllTheDefaults()
""");
}
// PY-71002
public void testTypeVarDefaultsLongTypeVarToTypeVarChain() {
doTest("str", """
from typing import TypeVar, Generic
T = TypeVar("T", default=str)
T1 = TypeVar("T1", default=T)
T2 = TypeVar("T2", default=T1)
T3 = TypeVar("T3", default=T2)
T4 = TypeVar("T4", default=T3)
T5 = TypeVar("T5", default=T4)
T6 = TypeVar("T6", default=T5)
T7 = TypeVar("T7", default=T6)
T8 = TypeVar("T8", default=T7)
class Box(Generic[T, T1, T2, T3, T4, T5, T6, T7, T8]):
value: T8
expr = Box().value
""");
}
// PY-71002
public void testTypeVarDefaultsLongTypeVarToTypeVarChainWithFirstOverriden() {
doTest("list", """
from typing import TypeVar, Generic
T = TypeVar("T", default=str)
T1 = TypeVar("T1", default=T)
T2 = TypeVar("T2", default=T1)
T3 = TypeVar("T3", default=T2)
T4 = TypeVar("T4", default=T3)
T5 = TypeVar("T5", default=T4)
T6 = TypeVar("T6", default=T5)
T7 = TypeVar("T7", default=T6)
T8 = TypeVar("T8", default=T7)
class Box(Generic[T, T1, T2, T3, T4, T5, T6, T7, T8]):
value: T8
expr = Box[list]().value
""");
}
// PY-71002
public void testTypeVarDefaultsLongTypeVarToTypeVarChainWithFirstAndSecondOverriden() {
doTest("int", """
from typing import TypeVar, Generic
T = TypeVar("T", default=str)
T1 = TypeVar("T1", default=T)
T2 = TypeVar("T2", default=T1)
T3 = TypeVar("T3", default=T2)
T4 = TypeVar("T4", default=T3)
T5 = TypeVar("T5", default=T4)
T6 = TypeVar("T6", default=T5)
T7 = TypeVar("T7", default=T6)
T8 = TypeVar("T8", default=T7)
class Box(Generic[T, T1, T2, T3, T4, T5, T6, T7, T8]):
value: T8
expr = Box[list, int]().value
""");
}
// PY-71002
public void testTypeVarDefaultsLongTypeVarToTypeVarChainWithMultipleDefaults() {
doTest("str | bool | float", """
from typing import TypeVar, Generic
T = TypeVar("T", default=str)
T1 = TypeVar("T1", default=T)
T2 = TypeVar("T2", default=float)
T3 = TypeVar("T3", default=T2)
T4 = TypeVar("T4", default=bool)
T5 = TypeVar("T5", default=T4)
T6 = TypeVar("T6", default=T5)
T7 = TypeVar("T7", default=T6)
T8 = TypeVar("T8", default=T7)
class Box(Generic[T, T1, T2, T3, T4, T5, T6, T7, T8]):
value: T | T8 | T3 = None
expr = Box().value
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaults() {
doTest("dict[int, str]", """
type Alias[T = int, U = str] = dict[T, U]
expr: Alias
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsOneOverriden() {
doTest("dict[bool, str]", """
type Alias[T = int, U = str] = dict[T, U]
expr: Alias[bool]
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsTwoOverriden() {
doTest("dict[bool, list[int]]", """
type Alias[T = int, U = str] = dict[T, list[U]]
x: Alias[bool, int]
expr = x
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsNested() {
doTest("dict[int, list[str]]", """
type Alias[T = int, U = str] = dict[T, list[U]]
expr: Alias
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsNestedOneOverriden() {
doTest("dict[bool, list[str]]", """
type Alias[T = int, U = str] = dict[T, list[U]]
expr: Alias[bool]
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsNestedTwoOverriden() {
doTest("dict[bool, list[bool]]", """
type Alias[T = int, U = str] = dict[T, list[U]]
expr: Alias[bool, bool]
""");
}
// PY-71002
public void testNewStyleTypeAliasWithTypeVarOnly() {
doTest("int", """
type Alias[T = int] = T
expr: Alias
""");
}
// PY-71002
public void testNewStyleTypeAliasWithTypeVarOnlyOverriden() {
doTest("bool", """
type Alias[T = int] = T
expr: Alias[bool]
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsUnion() {
doTest("int | str", """
type Alias[T = int, U = str] = T | U
expr: Alias
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsOneTypeOfUnionOverriden() {
doTest("bool | str", """
type Alias[T = int, U = str] = T | U
expr: Alias[bool]
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsUnionOverriden() {
doTest("bool | float", """
type Alias[T = int, U = str] = T | U
expr: Alias[bool, float]
""");
}
// PY-71002
public void testNewStyleTypeAliasUnionChangedOrder() {
doTest("str | list[int]", """
type Alias[T = int, U = str] = U | list[T]
expr: Alias
""");
}
// PY-71002
public void testNewStyleTypeAliasUnionChangedOrderDefaultsOverriden() {
doTest("bool | list[float]", """
type Alias[T = int, U = str] = U | list[T]
expr: Alias[float, bool]
""");
}
// PY-71002
public void testTypeAliasOneWithoutDefault() {
doTest("dict[Any, str] | list[float]", """
from typing import TypeVar, TypeAlias
T = TypeVar("T")
U = TypeVar("U", default=str)
B = TypeVar("B", default=float)
Alias : TypeAlias = dict[T, U] | list[B]
expr: Alias
""");
}
// PY-71002
public void testNewStyleTypeAliasOneWithoutDefault() {
doTest("dict[Any, str] | list[float]", """
type Alias[T, U = str, B = float] = dict[T, U] | list[B]
expr: Alias
""");
}
// PY-71002
public void testNewStyleTypeAliasOneWithoutDefaultParameterized() {
doTest("dict[int, str] | list[float] | int", """
type Alias[T, U = str, B = float] = dict[T, U] | list[B] | T
expr: Alias[int]
""");
}
// PY-71002
public void testNewStyleTypeAliasOneWithoutDefaultAllOverriden() {
doTest("dict[int, int] | list[int] | int", """
type Alias[T, U = str, B = float] = dict[T, U] | list[B] | T
expr: Alias[int, int, int]
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsPrevTypeVarAsDefault() {
doTest("str | list[str]", """
type Alias[T, U = T] = T | list[U]
expr: Alias[str]
""");
}
// PY-71002
public void testNewStyleTypeAliasWithDefaultsTypeVarChain() {
doTest("str", """
type Alias[T = str, T1 = T, T2 = T1, T3 = T2, T4 = T3] = T4
expr: Alias
""");
}
// PY-71002
public void testParamSpecWithDefaultsDefinedInTypeAlias() {
doTest("(func: (str, int) -> str) -> None", """
from typing import ParamSpec, Generic, Callable
type PAlias[T = str, **P = [str, int]] = Callable[P, T]
def wrapper(func: PAlias) -> None:
pass
expr = wrapper
""");
}
// PY-71002
public void testParamSpecWithDefaultsDefinedInTypeAliasOverriden() {
doTest("(func: (str, str) -> bool) -> None", """
from typing import ParamSpec, Generic, Callable
type PAlias[T = str, **P = [str, int]] = Callable[P, T]
def wrapper(func: PAlias[bool, [str, str]]) -> None:
pass
expr = wrapper
""");
}
// PY-71002
public void testNewStyleTypeAliasWithAllDefaultTypes() {
doTest("(str, int, str, str) -> float", """
from typing import Generic, TypeVarTuple, Unpack, ParamSpec, Callable, Any, Concatenate
type ReturnTupleAlias[T = float, **P = [str, str], *Ts = Unpack[tuple[str, int]]] = Callable[Concatenate[*Ts, P], T]
def f() -> ReturnTupleAlias: ...
expr = f()
""");
}
// PY-71002
public void testNewStyleTypeAliasWithAllDefaultTypesReturnTypeOverriden() {
doTest("(str, int, str, str) -> list[str]", """
from typing import Generic, TypeVarTuple, Unpack, ParamSpec, Callable, Any, Concatenate
type ReturnTupleAlias[T = float, **P = [str, str], *Ts = Unpack[tuple[str, int]]] = Callable[Concatenate[*Ts, P], T]
def f() -> ReturnTupleAlias[list[str]]: ...
expr = f()
""");
}
// PY-71002
public void testNewStyleTypeAliasWithAllDefaultTypesReturnAndParamSpecTypeOverriden() {
doTest("(str, int, float, float) -> list[str]", """
from typing import Generic, TypeVarTuple, Unpack, ParamSpec, Callable, Any, Concatenate
type ReturnTupleAlias[T = float, **P = [str, str], *Ts = Unpack[tuple[str, int]]] = Callable[Concatenate[*Ts, P], T]
def f() -> ReturnTupleAlias[list[str], [float, float]]: ...
expr = f()
""");
}
// PY-71002
public void testNewStyleTypeAliasWithAllDefaultTypesAllOverridden() {
doTest("(str, float, bool, list[bool], float, float) -> list[str]", """
from typing import Generic, TypeVarTuple, Unpack, ParamSpec, Callable, Any, Concatenate
type ReturnTupleAlias[T = float, **P = [str, str], *Ts = Unpack[tuple[str, int]]] = Callable[Concatenate[*Ts, P], T]
def f() -> ReturnTupleAlias[list[str], [float, float], str, float, bool, list[bool]]: ...
expr = f()
""");
}
// PY-71002
public void testTypeVarWithDefaultClassMethodTypeDefinedViaAnotherTypeVarWithNewSyntax() {
doTest("int", """
class Test[T = int, U = T]:
def foo(self) -> U: ...
expr = Test().foo()
""");
}
// PY-71002
public void testTypeAliasWithDefaults() {
doTest("SomethingWithNoDefaults[int, str]", """
from typing import Generic, TypeAlias, TypeVar
T = TypeVar('T')
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
class SomethingWithNoDefaults(Generic[T, T2]): ...
MyAlias: TypeAlias = SomethingWithNoDefaults[int, DefaultStrT]
expr: MyAlias
""");
}
// PY-71002
public void testTypeAliasWithParameterizedInstance() {
doTest("SomethingWithNoDefaults[int, bool]", """
from typing import Generic, TypeAlias, TypeVar
T = TypeVar('T')
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
class SomethingWithNoDefaults(Generic[T, T2]): ...
MyAlias: TypeAlias = SomethingWithNoDefaults[int, DefaultStrT]
expr: MyAlias[bool]
""");
}
// PY-71002
public void testTypeAliasWithDefaultsTuple() {
doTest("int | str", """
from typing import Generic, TypeAlias, TypeVar
T = TypeVar('T', default=int)
U = TypeVar('U', default=str)
MyAlias: TypeAlias = T | U
expr: MyAlias
""");
}
// PY-71002
public void testTypeAliasWithDefaultsDict() {
doTest("dict[int, str]", """
from typing import Generic, TypeAlias, TypeVar
T = TypeVar('T', default=int)
U = TypeVar('U', default=str)
MyAlias: TypeAlias = dict[T, U]
expr: MyAlias
""");
}
// PY-71002
public void testTypeAliasWithDefaultsDictOneDefaultOverriden() {
doTest("dict[str, str]", """
from typing import Generic, TypeAlias, TypeVar
T = TypeVar('T', default=int)
U = TypeVar('U', default=str)
MyAlias: TypeAlias = dict[T, U]
expr: MyAlias[str]
""");
}
// PY-71002
public void testTypeAliasWithDefaultsDictTwoDefaultsOverriden() {
doTest("dict[str, float]", """
from typing import Generic, TypeAlias, TypeVar
T = TypeVar('T', default=int)
U = TypeVar('U', default=str)
MyAlias: TypeAlias = dict[T, U]
expr: MyAlias[str, float]
""");
}
// PY-71002
public void testTypeAliasWithAllDefaultTypes() {
doTest("(str, int, str, str) -> float", """
from typing import Generic, TypeVarTuple, Unpack, ParamSpec, Callable, Any, Concatenate, TypeAlias, TypeVar
T = TypeVar('T', default = float)
P = ParamSpec('P', default=[str ,str])
Ts = TypeVarTuple('Ts', default=Unpack[tuple[str, int]])
ReturnTupleAlias: TypeAlias = Callable[Concatenate[*Ts, P], T]
def g() -> ReturnTupleAlias: ...
expr = g()
""");
}
// PY-71002
public void testTypeAliasWithParameterizedNonDefaultInDeclaration() {
doTest("dict[str, int] | str", """
from typing import TypeVar, Generic, TypeAlias
T = TypeVar('T')
T1 = TypeVar("T1")
T2 = TypeVar("T2")
DefaultStrT = TypeVar("DefaultStrT", default=str)
DefaultIntT = TypeVar("DefaultIntT", default=int)
DefaultBoolT = TypeVar("DefaultBoolT", default=bool)
class Triple(Generic[T1, T2, DefaultStrT, DefaultIntT, DefaultBoolT]):
val: dict[T1, T2] | DefaultStrT
Alias: TypeAlias = Triple[str, int]
e: Alias = None
expr = e.val
""");
}
// PY-71002
public void testClassWithDefaultGenericsDefinedInAnotherFile() {
doMultiFileStubAwareTest("int", """
from mod import StackOfIntsByDefault
stack = StackOfIntsByDefault()
expr = stack.pop()
""");
}
// PY-71002
public void testClassWithDefaultGenericsDefinedInAnotherFileDefaultOverriden() {
doMultiFileStubAwareTest("str", """
from mod import StackOfIntsByDefault
stack = StackOfIntsByDefault[str]()
expr = stack.pop()
""");
}
// PY-71002
public void testClassWithDefaultGenericsDefinedInAnotherFileAttributeAccess() {
doMultiFileStubAwareTest("int | str", """
from mod import Box
expr = Box.val
""");
}
// PY-71002
public void testClassWithNewStyleDefaultGenericsDefinedInAnotherFile() {
doMultiFileStubAwareTest("int", """
from mod import StackOfIntsByDefault
stack = StackOfIntsByDefault()
expr = stack.pop()
""");
}
// PY-71002
public void testTypeAliasWithDefaultsDefinedInAnotherFile() {
doMultiFileStubAwareTest("dict[int, str]", """
from mod import StrIntDict
expr: StrIntDict
""");
}
// PY-71002
public void testTypeAliasWithDefaultsDefinedInAnotherFileAliasingGenericClass() {
doMultiFileStubAwareTest("SomethingWithNoDefaults[int, bool]", """
from mod import MyAlias
expr = MyAlias[bool]()
""");
}
// PY-71002
public void testExplicitAnyNotSubstitutedByDefaults() {
doTest("Test[Any, Any, bool]", """
class Test[T = str, T1 = int, T2 = bool]: ...
expr = Test[Any, Any]()
""");
}
// PY-71002
public void testNewStyleTypeAliasParameterizedInMultipleSteps() {
doTest("float | int | str", """
from typing import Union
type A[T1, T2, T3 = str] = Union[T1, T2, T3]
type B[T1, T2 = int] = A[T1, T2]
type C[T1] = B[T1]
type D = C[float]
expr: D
""");
}
// PY-71002
public void testMixedOldAndNewStyleTypeAliasesParameterizedInMultipleSteps() {
doTest("float | int | str", """
from typing import Union, TypeVar, TypeAlias
T = TypeVar("T")
T1 = TypeVar("T1", default=int)
type A[T1, T2, T3 = str] = Union[T1, T2, T3]
B: TypeAlias = A[T, T1]
C: TypeAlias = B[T]
type D = C[float]
expr: D
""");
}
// PY-71002
public void testNewStyleTypeAliasWithAssignedSubscriptionExpression() {
doTest("dict[int, str]", """
type my_dict[K = float, V = bool] = dict[K, V]
type myIntStrDict = my_dict[int, str]
expr: myIntStrDict
""");
}
// PY-71002
public void testNewStyleTypeAliasWithAssignedSubscriptionExpressionAliasingUnion() {
doTest("bool | list[float]", """
type Alias[T = int, U = str] = U | list[T]
type Alias2 = Alias[float, bool]
expr: Alias2
""");
}
// PY-71002
public void testOldStyleTypeAliasWithAssignedSubscriptionExpressionAliasingUnion() {
doTest("float | list[bool]", """
from typing import TypeVar, Generic, TypeAlias
T = TypeVar("T", default=int)
U = TypeVar("U", default=str)
Alias: TypeAlias = U | list[T]
Alias2: TypeAlias = Alias[float, bool]
expr: Alias2
""");
}
// PY-71002
public void testParamSpecDefaultTypeRefersToAnotherParamSpecNewStyle() {
doTest("Clazz[[str], [str], [str]]", """
class Clazz[**P1, **P2 = P1, **P3 = P2]: ...
expr = Clazz[[str]]()
""");
}
// PY-71002
public void testParamSpecDefaultTypeRefersToAnotherParamSpecOldStyle() {
doTest("Clazz[[str], [str], [str]]", """
from typing import Generic, ParamSpec
P1 = ParamSpec("P1")
P2 = ParamSpec("P2", default=P1)
P3 = ParamSpec("P3", default=P2)
class Clazz(Generic[P1, P2, P3]): ...
expr = Clazz[[str]]()
""");
}
// PY-71002
public void testParamSpecDefaultTypeRefersToAnotherParamSpecOldStyleNoExplicit() {
doTest("Clazz[[str], [str], [bool, bool], [bool, bool]]", """
from typing import Generic, ParamSpec
P1 = ParamSpec("P1", default=[str])
P2 = ParamSpec("P2", default=P1)
P3 = ParamSpec("P3", default=[bool, bool])
P4 = ParamSpec("P4", default=P3)
class Clazz(Generic[P1, P2, P3, P4]): ...
expr = Clazz()
""");
}
// PY-71002
public void testParamSpecWithDefaultInConstructor() {
doTest("(int, str, str) -> None | None", """
from typing import Generic, ParamSpec, Callable
P = ParamSpec("P", default=[int, str, str])
class ClassA(Generic[P]):
def __init__(self, x: Callable[P, None] = None) -> None:
self.x = x
...
expr = ClassA().x
""");
}
// PY-71002
public void testParamSpecDefaultTypeRefersToAnotherParamSpecWithEllipsis() {
doTest("Clazz[Any, [float], [float]]", """
class Clazz[**P1, **P2 = P1, **P3 = P2]: ...
expr = Clazz[..., [float]]()
""");
}
public void testDataclassTransformConstructorSignature() {
doTestExpressionUnderCaret("(id: int, name: str) -> MyClass", """
from typing import dataclass_transform
@dataclass_transform()
def deco(cls):
...
@deco
class MyClass:
id: int
name: str
MyCl<caret>ass()
""");
}
public void testDataclassTransformConstructorSignatureDecoratedBaseClassAttributeExcluded() {
doTestExpressionUnderCaret("(id: int, name: str) -> SubSub", """
from typing import dataclass_transform
@dataclass_transform()
class Base:
excluded: int
class Sub(Base):
id: int
class SubSub(Sub):
name: str
Sub<caret>Sub()
""");
}
public void testDataclassTransformConstructorSignatureMetaClassBaseClassAttributeNotExcluded() {
doTestExpressionUnderCaret("(included: int, id: int, name: str) -> SubSub", """
from typing import dataclass_transform
@dataclass_transform()
class Meta(type):
pass
class Base(metaclass=Meta):
included: int
class Sub(Base):
id: int
class SubSub(Sub):
name: str
Sub<caret>Sub()
""");
}
public void testDataclassTransformOverloads() {
doTestExpressionUnderCaret("(id: int, name: str) -> MyClass", """
from typing import dataclass_transform, overload
@overload
def deco(name: str):
...
@dataclass_transform()
@overload
def deco(cls: type):
...
@overload
def deco():
...
def deco(*args, **kwargs):
...
@deco
class MyClass:
id: int
name: str
MyCl<caret>ass()
""");
}
public void testDataclassTransformOwnKwOnlyOmittedAndTakenFromKwOnlyDefault() {
doTestExpressionUnderCaret("(Any, id: int, name: str) -> MyClass", """
from typing import dataclass_transform, Callable
@dataclass_transform(kw_only_default=True)
def deco(**kwargs) -> Callable[[type], type]:
...
@deco(frozen=True)
class MyClass:
id: int
name: str
My<caret>Class()
""");
}
public void testDataclassTransformFieldSpecifierKwOnlyDefaultOverridesDecoratorsKwOnly() {
doTestExpressionUnderCaret("(id: str, Any, addr: list[str]) -> Order", """
from typing import Callable, dataclass_transform
def my_field(kw_only=False):
...
@dataclass_transform(field_specifiers=(my_field,))
def my_dataclass(**kwargs) -> Callable[[type], type]:
...
@my_dataclass(kw_only=True)
class Order:
id: str = my_field()
addr: list[str]
Ord<caret>er()
""");
}
public void testDataclassTransformFieldSpecifierKwOnlyDefaultOverridesDecoratorsKwOnlyDefault() {
doTestExpressionUnderCaret("(id: str, Any, addr: list[str]) -> Order", """
from typing import Callable, dataclass_transform
def my_field(kw_only=False):
...
@dataclass_transform(kw_only_default=True, field_specifiers=(my_field,))
def my_dataclass(**kwargs) -> Callable[[type], type]:
...
@my_dataclass()
class Order:
id: str = my_field()
addr: list[str]
Ord<caret>er()
""");
}
public void testDataclassTransformFieldSpecifierKwOnlyOverridesDecoratorsKwOnly() {
doTestExpressionUnderCaret("(id: str, Any, addr: list[str]) -> Order", """
from typing import Callable, dataclass_transform
def my_field(kw_only=False):
...
@dataclass_transform(field_specifiers=(my_field,))
def my_dataclass(**kwargs) -> Callable[[type], type]:
...
@my_dataclass(kw_only=True)
class Order:
id: str = my_field(kw_only=False)
addr: list[str]
Ord<caret>er()
""");
}
public void testDataclassTransformFieldSpecifierKwOnlyOverridesDecoratorsKwOnlyDefault() {
doTestExpressionUnderCaret("(id: str, Any, addr: list[str]) -> Order", """
from typing import Callable, dataclass_transform
def my_field(kw_only=False):
...
@dataclass_transform(kw_only_default=True, field_specifiers=(my_field,))
def my_dataclass(**kwargs) -> Callable[[type], type]:
...
@my_dataclass()
class Order:
id: str = my_field(kw_only=False)
addr: list[str]
Ord<caret>er()
""");
}
// PY-76076
public void testGenericAliasUnderVersionGuard() {
doMultiFileStubAwareTest("list[str]", """
from mod import f
expr = f("foo")
""");
}
// PY-76076
public void testGenericMethodReturnTypeImportedUnderVersionGuard() {
doMultiFileStubAwareTest("list[str]", """
from mod import C
expr = C().m()
""");
}
// PY-60968
public void testGenericMethodReturnTypeImportedUnderVersionGuardInStub() {
doMultiFileStubAwareTest("list[str]", """
from mod import C
expr = C().m()
""");
}
// PY-76076
public void testFunctionDefinitionUnderVersionGuard() {
doTest("list[str]", """
import sys
from typing import TypeVar
T = TypeVar("T")
if sys.version_info >= (3,):
def f(x: T) -> list[T]: ...
else:
def f(x: T) -> set[T]: ...
expr = f("foo")
""");
}
// PY-76076
public void testClassDefinitionUnderVersionGuard() {
doTest("list[str]", """
import sys
from typing import TypeVar
T = TypeVar("T")
if sys.version_info >= (3,):
class C:
def m(self, x: T) -> list[T]: ...
else:
class C:
def m(self, x: T) -> set[T]: ...
expr = C().m("foo")
""");
}
// PY-76076
public void testVariableDefinitionUnderVersionGuard() {
doTest("int", """
import sys
if sys.version_info < (3, 0):
x: str = "foo"
else:
x: int = 42
expr = x
""");
}
// PY-76243
public void testGenericClassDeclaredInStubPackage() {
runWithAdditionalClassEntryInSdkRoots("types/" + getTestName(false) + "/site-packages", () -> {
doTest("MyClass[int]",
"""
from pkg.mod import MyClass
expr: MyClass[int]
""");
});
}
private void doTestNoInjectedText(@NotNull String text) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject());
final PsiLanguageInjectionHost host = languageManager.getInjectionHost(getElementAtCaret());
assertNull(host);
}
private void doTestInjectedText(@NotNull String text, @NotNull String expected) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject());
final PsiLanguageInjectionHost host = languageManager.getInjectionHost(getElementAtCaret());
assertNotNull(host);
final List<Pair<PsiElement, TextRange>> files = languageManager.getInjectedPsiFiles(host);
assertNotNull(files);
assertFalse(files.isEmpty());
final PsiElement injected = files.get(0).getFirst();
assertEquals(expected, injected.getText());
assertFalse(PsiTreeUtil.hasErrorElements(injected));
}
private void doTest(@NotNull String expectedType, @NotNull String text) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
final TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getProject(), expr.getContainingFile());
final TypeEvalContext userInitiated = TypeEvalContext.userInitiated(expr.getProject(), expr.getContainingFile()).withTracing();
assertType("Failed in code analysis context", expectedType, expr, codeAnalysis);
assertType("Failed in user initiated context", expectedType, expr, userInitiated);
}
private void doTestExpressionUnderCaret(@NotNull String expectedType, @NotNull String text) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
PyExpression expr = PsiTreeUtil.getParentOfType(myFixture.getFile().findElementAt(myFixture.getCaretOffset()), PyExpression.class);
TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getProject(), expr.getContainingFile());
TypeEvalContext userInitiated = TypeEvalContext.userInitiated(expr.getProject(), expr.getContainingFile()).withTracing();
assertType("Failed in code analysis context", expectedType, expr, codeAnalysis);
assertType("Failed in user initiated context", expectedType, expr, userInitiated);
}
private void doMultiFileStubAwareTest(@NotNull final String expectedType, @NotNull final String text) {
myFixture.copyDirectoryToProject("types/" + getTestName(false), "");
myFixture.configureByText(PythonFileType.INSTANCE, text);
final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
final TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getProject(), expr.getContainingFile());
assertType("Failed in code analysis context", expectedType, expr, codeAnalysis);
assertProjectFilesNotParsed(expr.getContainingFile());
final TypeEvalContext userInitiated = TypeEvalContext.userInitiated(expr.getProject(), expr.getContainingFile()).withTracing();
assertType("Failed in user initiated context", expectedType, expr, userInitiated);
}
}