Started to untangle the hairball related to the "genericTypesX.py" test cases.

This commit is contained in:
Eric Traut 2023-06-19 11:49:56 -07:00
parent 67394ad67c
commit 1111f1b9bb
61 changed files with 398 additions and 512 deletions

View File

@ -1,5 +1,4 @@
# This sample tests the type checker's ability to do
# TypeVar matching for both constrained TypeVars and unconstrained.
# This sample tests constraint solving constrained TypeVars.
from typing import Generic, TypeVar
@ -14,18 +13,6 @@ def constrained(first: S, second: S) -> S:
# cannot satisfy the 'str' or 'bytes' constraint.
result = constrained("a", b"abc")
T = TypeVar("T")
def unconstrained(first: T, second: T) -> T:
return first
# This shouldn't generate an error because the TypeVar matching
# logic is free to expand the type to a union of 'str' and 'bytes'.
result = unconstrained("a", b"abc")
U = TypeVar("U", int, str)

View File

@ -1,11 +1,11 @@
# This sample tests the handling of constrained type variables
# that include unions.
from typing import List, TypeVar, Union
from typing import TypeVar
T1 = TypeVar("T1", int, str)
T2 = TypeVar("T2", int, str, Union[int, str])
T3 = TypeVar("T3", int, str, Union[int, str, List[int]])
T2 = TypeVar("T2", int, str, int | str)
T3 = TypeVar("T3", int, str, int | str | list[int])
def func1(x: T1) -> T1:
@ -20,7 +20,7 @@ def func3(x: T3) -> T3:
return x
def func4(y: Union[int, str]):
def func4(y: int | str):
# This should generate an error because T1 doesn't
# include a union constraint.
func1(y)

View File

@ -1,6 +1,6 @@
# This sample tests for proper handling of constrained or bound TypeVars.
from typing import Dict, Generic, Literal, Optional, TypeVar, Union
from typing import Generic, TypeVar
class IntSubclass1(int):
@ -28,30 +28,3 @@ _T2 = TypeVar("_T2", int, IntSubclass2)
def add2(value: _T2) -> _T2:
reveal_type(value + 1, expected_text="int* | IntSubclass2*")
return value + 5
class A:
...
class B:
...
_T3 = TypeVar("_T3", bound=Union[A, B])
class Registry(Generic[_T3]):
def __init__(self) -> None:
self.registry = {}
@property
def registry(self) -> Dict[str, _T3]:
...
@registry.setter
def registry(self, registry: Dict[str, _T3]) -> None:
...
def get(self, _id: str) -> Optional[_T3]:
return self.registry.get(_id)

View File

@ -6,9 +6,9 @@ from os import PathLike
from typing import AnyStr
def func(path: AnyStr | PathLike[AnyStr]) -> AnyStr:
def func1(path: AnyStr | PathLike[AnyStr]) -> AnyStr:
...
def thing(value: AnyStr) -> AnyStr:
return func(value)
def func2(value: AnyStr) -> AnyStr:
return func1(value)

View File

@ -4,7 +4,7 @@
# that is typed as that TypeVar, we know that the code path is taken only
# in the case where constraint is satisfied.
from typing import AnyStr, Generic, List, Optional, ParamSpec, TypeVar, Union
from typing import AnyStr, Generic, ParamSpec, TypeVar
from typing_extensions import TypeVarTuple, Unpack
_T1 = TypeVar("_T1", str, int)
@ -44,7 +44,7 @@ def func2(val1: _T1) -> list[_T1]:
class Class1(Generic[_T1, _T2, _T3, _P, Unpack[_Ts]]):
def meth1(
self, val1: _T1, val2: _T2, val3: _T3, cond: bool
) -> Union[List[_T1], List[_T2], List[_T3]]:
) -> list[_T1] | list[_T2] | list[_T3]:
if cond:
# This should generate an error.
return [0]
@ -98,7 +98,7 @@ class Class1(Generic[_T1, _T2, _T3, _P, Unpack[_Ts]]):
raise BaseException()
def func3(s: AnyStr, y: Optional[AnyStr] = None) -> AnyStr:
def func3(s: AnyStr, y: AnyStr | None = None) -> AnyStr:
if isinstance(s, str):
if y is None:
pass

View File

@ -1,15 +1,15 @@
# This sample tests the case where a constrained TypeVar is used
# as an argument for a constructor or function call.
from typing import TypeVar, Generic, Union
from typing import TypeVar, Generic
from dataclasses import dataclass
class NDArray:
class ClassA:
...
_T = TypeVar("_T", Union[int, float], NDArray)
_T = TypeVar("_T", int | float, ClassA)
@dataclass
@ -23,6 +23,6 @@ def func1(a: Data[_T]) -> _T:
reveal_type(value, expected_text="int*")
else:
value = a.data
reveal_type(value, expected_text="NDArray*")
reveal_type(value, expected_text="ClassA*")
return value

View File

@ -1,4 +1,4 @@
# This sample tests type var matching for constrained type vars.
# This sample tests constraint solving for constrained type vars.
import pathlib
import shutil

View File

@ -1,18 +1,18 @@
# This sample tests type narrowing of generic constrained types.
from typing import AnyStr, Generic, List, Optional, Sequence, TypeVar, Union
from typing import AnyStr, Generic, Sequence, TypeVar
Command = Union[AnyStr, Sequence[AnyStr]]
Command = AnyStr | Sequence[AnyStr]
def version1(cmd: Command) -> List[str]:
def func1(cmd: Command) -> list[str]:
if isinstance(cmd, bytes):
return [str(cmd, "utf-8")]
if isinstance(cmd, str):
return [cmd]
ret: List[str] = []
ret: list[str] = []
for itm in cmd:
if isinstance(itm, str):
ret.append(itm)
@ -25,12 +25,12 @@ T = TypeVar("T", str, int, float, bool)
class Item(Generic[T]):
value: Optional[T]
value: T | None
def __init__(self, source: Optional[T]) -> None:
def __init__(self, source: T | None) -> None:
self.value = source
def read(self) -> Optional[T]:
def read(self) -> T | None:
if self.value is None:
raise RuntimeError(f"Item is required!")

View File

@ -1,7 +1,7 @@
# This sample tests the handling of generic type aliases
# with constrained types.
from typing import Callable, Generic, Type, TypeVar, Union
from typing import Callable, Generic, TypeVar
T = TypeVar("T", str, bool, None)
@ -34,7 +34,7 @@ def f_generic3(val: T) -> T:
return val
def f_union(val: Union[bool, str]) -> None:
def f_union(val: bool | str) -> None:
# This should generate an error because a
# union cannot be assigned to a constrained
# type variable.
@ -46,9 +46,9 @@ def f_union(val: Union[bool, str]) -> None:
f_generic3(val)
def func1(v: T, t: Type[T]):
def func1(v: T, t: type[T]):
print(t)
def func2(v: T, t: Type[T]):
def func2(v: T, t: type[T]):
func1(v, t)

View File

@ -4,7 +4,7 @@
from typing import Iterator, Optional, Sequence, TypeVar, Union
def func(a: Union[int, float]):
def func0(a: Union[int, float]):
...
@ -12,7 +12,7 @@ _T1 = TypeVar("_T1", int, float)
def func1(a: _T1, b: _T1):
return func(a)
return func0(a)
_T2 = TypeVar("_T2", int, float, complex)
@ -20,7 +20,7 @@ _T2 = TypeVar("_T2", int, float, complex)
def func2(a: _T2, b: _T2):
# This should generate an error.
return func(a)
return func0(a)
_T3 = TypeVar("_T3", int, float)

View File

@ -1,7 +1,7 @@
# This sample tests the handling of a constrained TypeVar used with
# a Type[T] annotation.
from typing import Type, TypeVar, Any
from typing import TypeVar, Any
class A:
@ -15,7 +15,7 @@ class A:
T = TypeVar("T", str, int, A)
def factory(desired_type: Type[T]) -> T:
def factory(desired_type: type[T]) -> T:
return desired_type(1)

View File

@ -0,0 +1,15 @@
# This sample tests the case where a constrained type variable
# includes a Literal[False] and Literal[True].
from typing import TypeVar, Generic, Literal
XOrY = TypeVar("XOrY", Literal[True], Literal[False])
class A(Generic[XOrY]):
pass
class B(Generic[XOrY]):
def __init__(self, a: A[XOrY]):
self.a = a

View File

@ -7,7 +7,7 @@ from typing import Generic, TypeVar
_T1 = TypeVar("_T1")
class Foo(Generic[_T1]):
class ClassA(Generic[_T1]):
pass
@ -21,12 +21,13 @@ def func2(p1: Generic[_T1]) -> _T1:
...
AAA = Generic
TA1 = Generic
# This should generate an error.
def func3(a: _T1) -> AAA[_T1]:
def func3(a: _T1) -> TA1[_T1]:
...
class Foo2(AAA[_T1]):
class ClassB(TA1[_T1]):
...

View File

@ -1,16 +1,16 @@
# This sample tests the assignment of unions that contain TypeVars.
from typing import TypeVar
T = TypeVar("T")
def func1(x: T | None) -> T | str:
# This should generate an error.
return x
def func2(x: T | int) -> T | str:
# This should generate an error.
return x

View File

@ -1,4 +1,4 @@
# This sample validates generic type matching for protocol
# This sample validates constraint solving for protocol
# classes where the protocol is partially specialized with a
# type variable.
@ -9,18 +9,18 @@ from typing import Callable, Iterator, Protocol, TypeVar
_T = TypeVar("_T", covariant=True)
class Foo(Iterator[_T], Protocol):
class ProtoA(Iterator[_T], Protocol):
pass
def foo(func: Callable[..., Iterator[_T]]) -> Callable[..., Foo[_T]]:
def decorator1(func: Callable[..., Iterator[_T]]) -> Callable[..., ProtoA[_T]]:
...
@foo
def f() -> Iterator[str]:
@decorator1
def func1() -> Iterator[str]:
yield ""
a = f()
b: Foo[str] = a
a = func1()
b: ProtoA[str] = a

View File

@ -1,14 +0,0 @@
# This sample tests the checker's ability to enforce
# type invariance for type arguments.
# pyright: strict
from typing import Dict, Union
foo: Dict[Union[int, str], str] = {}
bar: Dict[str, str] = {}
# This should generate an error because
# both type parameters for Dict are invariant,
# and str isn't assignable to Union[int, str].
foo = bar

View File

@ -1,7 +1,7 @@
# This sample tests the type checker's ability to do bidirectional
# type inference when the expected type is defined by a bound TypeVar.
from typing import Dict, TypeVar
from typing import TypeVar
class A:
@ -19,7 +19,7 @@ class C(A):
_T_A = TypeVar("_T_A", bound=A)
def testFunc(value: Dict[str, _T_A]) -> _T_A:
def testFunc(value: dict[str, _T_A]) -> _T_A:
return value["a"]

View File

@ -1,22 +1,22 @@
# This sample tests TypeVar matching in a situation
# where the matched type has a type argument that is
# This sample tests constraint solving in a situation
# where the type has a type argument that is
# a union of types that are subclasses of each other.
from typing import Iterable, Iterator, List, Literal, Optional, TypeVar, Union
from typing import Iterable, Iterator, Literal, TypeVar
_T = TypeVar("_T")
def filter(__function: None, __iterable: Iterable[Optional[_T]]) -> Iterator[_T]:
def filter(__function: None, __iterable: Iterable[_T | None]) -> Iterator[_T]:
...
# In this case, bool is a subclass of int, so the TypeVar
# matching for _T should evaluate to Iterator[int].
list_of_bools_and_ints: List[Union[Literal[False], int]] = []
list_of_bools_and_ints: list[Literal[False] | int] = []
generator_of_ints = filter(None, list_of_bools_and_ints)
a: int = next(generator_of_ints)
# This should generate an error
# This should generate an error.
b: bool = next(generator_of_ints)

View File

@ -3,11 +3,9 @@
# the "keys" method on "dict") based on the provided "self"
# argument.
from typing import Dict
foo: Dict[str, str] = {}
v1: dict[str, str] = {}
# This should not result in an "Unknown", so no
# error should be generated.
result = dict.keys(foo)
result = dict.keys(v1)
reveal_type(result, expected_text="dict_keys[Unknown, Unknown]")

View File

@ -1,15 +1,14 @@
# This sample tests the type checker's ability to
# perform TypeVar matching in the case where the first
# This sample tests constraint solving where the first
# encounter with the TypeVar is contravariant but later
# encounters are covariant or invariant.
def foo(value: object) -> bool:
def func1(value: object) -> bool:
...
# This should evaluate to a type of "Iterable[str]",
# not "Iterable[object]".
filtered_list = filter(foo, ["b", "a", "r"])
should_be_str = next(filtered_list)
a = len(should_be_str)
v1 = filter(func1, ["b", "a", "r"])
reveal_type(v1, expected_text="filter[str]")
v2 = next(v1)
reveal_type(v2, expected_text="str")

View File

@ -5,20 +5,20 @@
from typing import Any, Callable, Iterable, Iterator, TypeVar
_T = TypeVar("_T")
def is_one(x: int) -> bool:
return x == 1
nums = ["a", "b", "c"]
_T = TypeVar("_T")
v1 = ["a", "b", "c"]
def filterX(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> Iterator[_T]:
def func1(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> Iterator[_T]:
...
# This should be flagged as an error because nums is
# not an int array.
ones = filterX(is_one, nums)
ones = func1(is_one, v1)

View File

@ -1,9 +1,10 @@
# This sample tests the matching of type variables in methods
# This sample tests constraint solving in methods
# where the type is provided by a default initialization value
# rather than an argument provided directly by the caller.
# We use "strict" here because we want to ensure that there are
# no "unknown" types remaining in this file.
# pyright: strict
from typing import Generic, TypeVar
@ -12,7 +13,7 @@ _A = TypeVar("_A")
_B = TypeVar("_B")
class Foo(Generic[_A, _B]):
class ClassA(Generic[_A, _B]):
def __init__(self, a: _A, b: _B = "hello"):
self._foo_a = a
self._foo_b = b
@ -26,7 +27,7 @@ class Foo(Generic[_A, _B]):
return self._foo_b
foo = Foo(27)
a1 = ClassA(27)
reveal_type(foo.value_a, expected_text="int")
reveal_type(foo.value_b, expected_text="str")
reveal_type(a1.value_a, expected_text="int")
reveal_type(a1.value_b, expected_text="str")

View File

@ -1,40 +0,0 @@
# This sample checks for handling of generic functions.
from typing import TypeVar, Any, Callable, List
T = TypeVar("T")
def for_each(xs: List[T], f: Callable[[T], Any]) -> None:
for x in xs:
f(x)
class Foo:
...
def call_len(x: Foo) -> None:
pass
# This should generate an error because call_len takes a str,
# which isn't compatible with a List[int].
for_each([1, 2, 3], call_len)
def validate_param_types(i: int, s: str):
pass
async def test():
import asyncio
async def get_int() -> int:
return 42
async def get_str() -> str:
return "Hi!"
i, s = await asyncio.gather(get_int(), get_str())
validate_param_types(i, s)

View File

@ -6,13 +6,13 @@ from typing import Optional, TypeVar
_T = TypeVar("_T")
def foo1(v: Optional[_T]) -> _T:
def func1(v: Optional[_T]) -> _T:
if v is None:
raise ValueError
return v
def foo2(v: _T) -> _T:
def func2(v: _T) -> _T:
if v is None:
raise ValueError
return v
@ -20,10 +20,8 @@ def foo2(v: _T) -> _T:
f: Optional[int] = None
# This should not generate an error because type var _T
# should be matched to "int" rather than "Optional[int]".
a: int = foo1(f)
a: int = func1(f)
# This should generate an error because type var _T
# should be matched to "Optional[int]".
b: int = foo2(f)
b: int = func2(f)

View File

@ -8,25 +8,25 @@ _T2 = TypeVar("_T2", bound=None)
_T3 = TypeVar("_T3")
def foo1(a: Type[_T1]) -> _T1:
def func1(a: Type[_T1]) -> _T1:
return a()
a = foo1(Optional[int])
a = func1(Optional[int])
def foo2(a: Type[_T2]) -> Type[_T2]:
def func2(a: Type[_T2]) -> Type[_T2]:
return a
b = foo2(type(None))
b = func2(type(None))
# This should generate an error because None is
# not a type; it's an instance of the NoneType class.
c = foo2(None)
c = func2(None)
class Foo(Generic[_T1]):
class ClassA(Generic[_T1]):
def __init__(self, value: _T1) -> None:
...
@ -35,21 +35,21 @@ class Foo(Generic[_T1]):
return cls
class Bar(Foo):
class ClassB(ClassA):
pass
def bar(value: _T1) -> Type[Foo[_T1]]:
baz = Foo(value)
qux = type(baz)
reveal_type(qux, expected_text="type[Foo[_T1@bar]]")
return qux
def func3(value: _T1) -> Type[ClassA[_T1]]:
v1 = ClassA(value)
v2 = type(v1)
reveal_type(v2, expected_text="type[ClassA[_T1@func3]]")
return v2
d = Bar.get()
reveal_type(d, expected_text="type[Bar]")
reveal_type(Bar.get(), expected_text="type[Bar]")
d = ClassB.get()
reveal_type(d, expected_text="type[ClassB]")
reveal_type(ClassB.get(), expected_text="type[ClassB]")
def class_constructor(cls: type[_T1]) -> Callable[..., _T1]:
def func4(cls: type[_T1]) -> Callable[..., _T1]:
return cls

View File

@ -1,17 +1,17 @@
# This sample tests bidirectional inference when the type derives from the
# expected type and both are generic.
from typing import Generic, Iterable, Mapping, Optional, TypeVar, Union
from typing import Generic, Iterable, Mapping, TypeVar
v0: Optional[Mapping[str, Union[int, str]]] = dict([("test1", 1), ("test2", 2)])
v0: Mapping[str, int | str] | None = dict([("test1", 1), ("test2", 2)])
v1: Optional[Mapping[str, float]] = dict([("test1", 1), ("test2", 2)])
v1: Mapping[str, float] | None = dict([("test1", 1), ("test2", 2)])
# This should generate an error because of a type mismatch.
v2: Mapping[str, str] = dict([("test1", 1), ("test2", 2)])
options: dict[Union[int, str], int] = {}
options: dict[int | str, int] = {}
channel_types: dict[str, int] = {}
keys = channel_types.keys()

View File

@ -1,4 +1,4 @@
# This sample checks the handling of TypeVar matching
# This sample checks the handling of constraint solving
# in the case where list and tuple expressions are being
# matched, and those expressions contain literal values.
# We need to validate that the type inference for lists

View File

@ -6,7 +6,7 @@
# NOTE: This test is no longer working. It previously worked
# because of the looser handling of TypeVars.
from typing import TypeVar, Callable, Optional
from typing import TypeVar, Callable
T1 = TypeVar("T1")
U1 = TypeVar("U1")
@ -16,11 +16,11 @@ def identity1(x: T1) -> T1:
return x
def fmap(f: Callable[[T1], U1], maybe: Optional[T1]) -> Optional[U1]:
def fmap(f: Callable[[T1], U1], maybe: T1 | None) -> U1 | None:
return None
x1: Optional[int] = 0
x1: int | None = 0
y1 = fmap(identity1, x1)
if y1 is not None:
@ -37,7 +37,7 @@ def identity2(x: T2) -> T2:
return x
x2: Optional[int] = 0
x2: int | None = 0
# This should generate an error because identity2's TypeVar
# T2 is bound to str, so there is no solution that satisfies

View File

@ -4,14 +4,14 @@
from typing import Any, Generic, TypeVar
class Bar:
class ClassA:
...
_T = TypeVar("_T", bound=Bar)
_T = TypeVar("_T", bound=ClassA)
class Foo(Generic[_T]):
class ClassB(Generic[_T]):
def func1(self, a: _T):
pass

View File

@ -1,15 +0,0 @@
# This sample tests the handling of type variables
# used within a generic class.
from queue import Queue
from typing import Generic, Optional, TypeVar
_T = TypeVar("_T")
class Foo(Generic[_T]):
def __init__(self):
self._queue: "Queue[Optional[_T]]" = Queue()
def publish(self, message: _T):
self._queue.put_nowait(message)

View File

@ -1,63 +1,50 @@
# This sample tests the handling of TypeVars defined by
# a generic function.
from typing import Callable, Dict, Generic, Iterable, List, Tuple, TypeVar
T = TypeVar("T")
R = TypeVar("R")
from typing import Generic, TypeVar
def do_something(
collection: Iterable[T], zero: R, f: Callable[[R, T], R]
) -> Iterable[R]:
s = zero
yield s
for x in collection:
s = f(s, x)
yield s
class Foo:
class ClassA:
pass
_T1 = TypeVar("_T1")
_T2 = TypeVar("_T2", bound=Foo)
_T2A = TypeVar("_T2A", bound=Foo)
_T3 = TypeVar("_T3", Foo, int, str)
_T2 = TypeVar("_T2", bound=ClassA)
_T2A = TypeVar("_T2A", bound=ClassA)
_T3 = TypeVar("_T3", ClassA, int, str)
class MyClass1(Generic[_T1]):
class Class1(Generic[_T1]):
def __init__(self, a: _T1):
self._a: Dict[str, _T1] = {}
self._b: Tuple[_T1, ...] = (a, a, a)
self._c: Tuple[_T1, _T1] = (a, a)
self._d: List[_T1] = [a]
self._a: dict[str, _T1] = {}
self._b: tuple[_T1, ...] = (a, a, a)
self._c: tuple[_T1, _T1] = (a, a)
self._d: list[_T1] = [a]
class MyClass2(Generic[_T2]):
class Class2(Generic[_T2]):
def __init__(self, a: _T2):
self._a: Dict[str, _T2] = {}
self._b: Tuple[_T2, ...] = (a, a, a)
self._c: Tuple[_T2, _T2] = (a, a)
self._d: List[_T2] = [a]
self._a: dict[str, _T2] = {}
self._b: tuple[_T2, ...] = (a, a, a)
self._c: tuple[_T2, _T2] = (a, a)
self._d: list[_T2] = [a]
class MyClass2A(Generic[_T2, _T2A]):
class Class2A(Generic[_T2, _T2A]):
def __init__(self, a: _T2, b: _T2A):
self._a1: Dict[str, _T2A] = {"a": b}
self._a2: Dict[str, _T2] = {"a": a}
self._b: Tuple[_T2, ...] = (a, a, a)
self._c: Tuple[_T2, _T2] = (a, a)
self._d: List[_T2] = [a]
self._a1: dict[str, _T2A] = {"a": b}
self._a2: dict[str, _T2] = {"a": a}
self._b: tuple[_T2, ...] = (a, a, a)
self._c: tuple[_T2, _T2] = (a, a)
self._d: list[_T2] = [a]
class MyClass3(Generic[_T3]):
class Class3(Generic[_T3]):
def __init__(self, a: _T3):
self._a: Dict[str, _T3] = {}
self._b: Tuple[_T3, ...] = (a, a, a)
self._c: Tuple[_T3, _T3] = (a, a)
self._d: List[_T3] = [a]
self._a: dict[str, _T3] = {}
self._b: tuple[_T3, ...] = (a, a, a)
self._c: tuple[_T3, _T3] = (a, a)
self._d: list[_T3] = [a]
class Animal:

View File

@ -1,6 +1,4 @@
# This sample tests type inference and TypeVar matching.
from typing import Union
# This sample tests bidirectional type inference and constraint solving.
m = int(1)
n = float(1.1)
@ -34,4 +32,4 @@ e1: str = e["x"]
# This should generate an error because d should be
# typed as dict[Any, str].
e2: float = e["x"]
e3: Union[float, str] = e["x"]
e3: float | str = e["x"]

View File

@ -3,7 +3,7 @@
# pyright: strict
from typing import Callable, Dict, Literal, TypeVar
from typing import Callable, Literal, TypeVar
def filter_fn(value: object):
@ -28,7 +28,7 @@ def func(v: Callable[[], _T]) -> _T:
...
x1: Dict[Animal, int] = func(lambda: {"cat": 0})
x1: dict[Animal, int] = func(lambda: {"cat": 0})
def func1(factory: Callable[[], _T]) -> _T:

View File

@ -3,14 +3,14 @@
from typing import TypeVar
_T1 = TypeVar("_T1", bound="P")
_T2 = TypeVar("_T2", bound="P")
_T1 = TypeVar("_T1", bound="ClassA")
_T2 = TypeVar("_T2", bound="ClassA")
class P:
class ClassA:
def chain(self: _T1) -> _T1:
...
def func(p1: _T2) -> _T2:
def func1(p1: _T2) -> _T2:
return p1.chain()

View File

@ -1,30 +1,30 @@
# This sample tests the instantiation of classes via a constructor
# when the type of the class is a TypeVar.
from typing import Type, TypeVar
from typing import TypeVar
class Foo:
class ClassA:
def __init__(self, a: int, b: str):
pass
_TFoo = TypeVar("_TFoo", bound=Foo)
T_A = TypeVar("T_A", bound=ClassA)
def func1(cls: Type[_TFoo]) -> _TFoo:
def func1(cls: type[T_A]) -> T_A:
# This should generate an error
y = cls()
x = cls(1, "")
reveal_type(x, expected_text="_TFoo@func1")
reveal_type(x, expected_text="T_A@func1")
return x
_T = TypeVar("_T")
def func2(cls: Type[_T]) -> _T:
def func2(cls: type[_T]) -> _T:
y = cls(1, "")
x = cls()

View File

@ -4,21 +4,21 @@
from typing import Generic, List, Type, TypeVar
class Foo:
class ClassA:
pass
_TFoo = TypeVar("_TFoo", bound=Foo)
_TAnything = TypeVar("_TAnything")
T_A = TypeVar("T_A", bound=ClassA)
T = TypeVar("T")
class Bar(Generic[_TFoo, _TAnything]):
class ClassB(Generic[T_A, T]):
def __init__(
self,
p1: Type[_TFoo] = Foo,
p2: List[_TAnything] = [],
p1: Type[T_A] = ClassA,
p2: List[T] = [],
# This should generate an error.
p3: List[_TFoo] = [2],
p4: List[_TAnything] = [2],
p3: List[T_A] = [2],
p4: List[T] = [2],
):
pass

View File

@ -17,12 +17,12 @@ class ClassA(Iterator[T]):
...
def bar(it: Iterable[T]) -> Iterator[T]:
return ClassA(it)
def func1(val: Iterable[T]) -> Iterator[T]:
return ClassA(val)
def baz(it_of_its: Iterable[Iterable[T]]) -> Iterator[T]:
return chain(*it_of_its)
def func2(val: Iterable[Iterable[T]]) -> Iterator[T]:
return chain(*val)
class ClassB(Generic[T]):

View File

@ -9,35 +9,35 @@ _T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")
class Foo(Generic[_T1]):
class ClassA(Generic[_T1]):
@staticmethod
def func1(value: _T1) -> "Foo[_T1]":
return Foo[_T1]()
def func1(value: _T1) -> "ClassA[_T1]":
return ClassA[_T1]()
@classmethod
def func2(cls, value: _T1) -> "Foo[_T1]":
def func2(cls, value: _T1) -> "ClassA[_T1]":
return cls()
class FooSub1(Foo[_T2]):
class ClassASub1(ClassA[_T2]):
pass
class FooSub2(Foo[int]):
class ClassASub2(ClassA[int]):
pass
def test1(val_str: str, val_int: int):
reveal_type(Foo.func1(val_str), expected_text="Foo[str]")
reveal_type(FooSub1.func1(val_str), expected_text="Foo[str]")
reveal_type(FooSub2.func1(val_int), expected_text="Foo[int]")
reveal_type(ClassA.func1(val_str), expected_text="ClassA[str]")
reveal_type(ClassASub1.func1(val_str), expected_text="ClassA[str]")
reveal_type(ClassASub2.func1(val_int), expected_text="ClassA[int]")
# This should generate an error because the argument type doesn't match.
FooSub2.func1(val_str)
ClassASub2.func1(val_str)
reveal_type(Foo.func2(val_str), expected_text="Foo[str]")
reveal_type(FooSub1.func2(val_str), expected_text="Foo[str]")
reveal_type(FooSub2.func2(val_int), expected_text="Foo[int]")
reveal_type(ClassA.func2(val_str), expected_text="ClassA[str]")
reveal_type(ClassASub1.func2(val_str), expected_text="ClassA[str]")
reveal_type(ClassASub2.func2(val_int), expected_text="ClassA[int]")
# This should generate an error because the argument type doesn't match.
FooSub2.func2(val_str)
ClassASub2.func2(val_str)

View File

@ -1,5 +1,4 @@
# This sample tests that various types can be assigned
# to Type[Any].
# This sample tests that various types can be assigned to Type[Any].
from typing import Any, Type, TypeVar

View File

@ -1,15 +1,30 @@
# This sample tests the case where a constrained type variable
# includes a Literal[False] and Literal[True].
# This sample tests for proper handling of bound TypeVars.
from typing import TypeVar, Generic, Literal
XOrY = TypeVar("XOrY", Literal[True], Literal[False])
from typing import Generic, TypeVar
class A(Generic[XOrY]):
pass
class A:
...
class B(Generic[XOrY]):
def __init__(self, a: A[XOrY]):
self.a = a
class B:
...
_T3 = TypeVar("_T3", bound=A | B)
class Registry(Generic[_T3]):
def __init__(self) -> None:
self.registry = {}
@property
def registry(self) -> dict[str, _T3]:
...
@registry.setter
def registry(self, registry: dict[str, _T3]) -> None:
...
def get(self, _id: str) -> _T3 | None:
return self.registry.get(_id)

View File

@ -1,5 +1,5 @@
# This sample tests the case that exercises some of the heuristics that
# determine whether TypeVar matching should retain a literal type.
# determine whether a solved TypeVar should retain a literal type.
from typing import Callable, Dict, Generic, Literal, Tuple, TypeVar

View File

@ -1,5 +1,5 @@
# This sample tests the type checker's ability to do type var
# matching for callables, whose input parameters are contravariant.
# This sample tests the constraint solver's handling of callables
# whose input parameters are contravariant.
from typing import TypeVar, Callable

View File

@ -1,17 +1,15 @@
# This sample tests that a generic callable passed to a function cannot
# be called with parameters that don't match the generic.
from typing import TypeVar, Callable, Any, Union
from typing import TypeVar, Callable, Any
T = TypeVar("T")
def foo(
mkfoo: Callable[[T], list[T]], param1: T, param2: Any, param3: Union[Any, T]
) -> None:
mkfoo(param1)
mkfoo(param2)
mkfoo(param3)
def func1(cb: Callable[[T], list[T]], param1: T, param2: Any, param3: Any | T) -> None:
cb(param1)
cb(param2)
cb(param3)
# This should generate an error.
mkfoo(0)
cb(0)

View File

@ -2,11 +2,12 @@
# evaluates correctly.
# pyright: strict
from typing import TypeVar
_T = TypeVar("_T")
def func(x: list[_T]) -> list[_T]:
result = func(x)
def func1(x: list[_T]) -> list[_T]:
result = func1(x)
return result

View File

@ -5,20 +5,20 @@ from typing import TypeVar, Generic
T = TypeVar("T")
class Foo(Generic[T]):
class ClassA(Generic[T]):
def __init__(self, bar: T):
self._bar = bar
@property
def bar(self) -> T:
def prop1(self) -> T:
return self._bar
def bar_method(self) -> T:
reveal_type(self._bar, expected_text="T@Foo")
def method1(self) -> T:
reveal_type(self._bar, expected_text="T@ClassA")
return self._bar
foo = Foo[int](3)
a = ClassA[int](3)
# This should work fine because foo.bar should be an int
foo.bar.bit_length()
# This should work fine because a.bar should be an int
a.prop1.bit_length()

View File

@ -1,8 +1,6 @@
# This sample tests type checking scenarios related to "pseudo generic"
# classes - those whose constructors are unannotated.
from typing import List
_DEFAULT_VALUE = object()
@ -15,9 +13,9 @@ class ClassA:
...
a1: List[ClassA] = [ClassA("a", description="b")]
a2: List[ClassA] = [ClassA("c")]
a3: List[ClassA] = a1 + a2
a1: list[ClassA] = [ClassA("a", description="b")]
a2: list[ClassA] = [ClassA("c")]
a3: list[ClassA] = a1 + a2
class ClassB:

View File

@ -9,7 +9,7 @@
from logging import Handler, NOTSET
class Foo(Handler):
class ClassA(Handler):
def __init__(self, a, b="hello", level=NOTSET):
super().__init__(level)
self._foo_a = a
@ -24,15 +24,15 @@ class Foo(Handler):
return self._foo_b
foo1 = Foo(27)
reveal_type(foo1.value_a, expected_text="int")
reveal_type(foo1.value_b, expected_text="str")
a1 = ClassA(27)
reveal_type(a1.value_a, expected_text="int")
reveal_type(a1.value_b, expected_text="str")
foo2 = Foo("hello", "27")
reveal_type(foo2.value_a, expected_text="str")
reveal_type(foo2.value_b, expected_text="str")
a2 = ClassA("hello", "27")
reveal_type(a2.value_a, expected_text="str")
reveal_type(a2.value_b, expected_text="str")
# This should generate an error because a pseudo-generic
# class is not actually generic.
foo3: Foo[int, str, int]
a3: ClassA[int, str, int]

View File

@ -1,11 +1,11 @@
# This sample is similar to genericTypes20.py in that it tests
# This sample is similar to pseudoGeneric2.py in that it tests
# the case where the class's constructor is unannotated. This
# particular case was causing an internal crash.
import abc
class MyClass(metaclass=abc.ABCMeta):
class ClassB(metaclass=abc.ABCMeta):
def __init__(self, value=None):
self._cache = {"value": value}
@ -25,7 +25,6 @@ class MyClass(metaclass=abc.ABCMeta):
return self.__getattribute__(attr)
my_class = MyClass("test")
print(my_class.value)
del my_class.cache
print(my_class.value)
b1 = ClassB("test")
reveal_type(b1.value, expected_text="Unknown | Any | None")
del b1.cache

View File

@ -1074,6 +1074,12 @@ test('Properties14', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('Properties15', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['properties15.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('Operators1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['operators1.py']);
@ -1496,6 +1502,18 @@ test('PseudoGeneric1', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('PseudoGeneric2', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['pseudoGeneric2.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('PseudoGeneric3', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['pseudoGeneric3.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('LiteralString1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['literalString1.py']);

View File

@ -415,72 +415,133 @@ test('NameBindings5', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes1.py']);
test('ConstrainedTypeVar1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar1.py']);
TestUtils.validateResults(analysisResults, 3);
});
test('ConstrainedTypeVar2', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar2.py']);
TestUtils.validateResults(analysisResults, 5);
});
test('ConstrainedTypeVar3', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar3.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ConstrainedTypeVar4', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar4.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ConstrainedTypeVar5', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar5.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('ConstrainedTypeVar6', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar6.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ConstrainedTypeVar7', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar7.py']);
TestUtils.validateResults(analysisResults, 2);
});
test('GenericTypes2', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes2.py']);
test('ConstrainedTypeVar8', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar8.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('ConstrainedTypeVar9', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar9.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ConstrainedTypeVar10', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar10.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('ConstrainedTypeVar11', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar11.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('ConstrainedTypeVar12', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar12.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ConstrainedTypeVar13', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar13.py']);
TestUtils.validateResults(analysisResults, 5);
});
test('ConstrainedTypeVar14', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar14.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ConstrainedTypeVar15', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar15.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ConstrainedTypeVar16', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constrainedTypeVar16.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('MissingTypeArg1', () => {
const configOptions = new ConfigOptions('.');
// By default, reportMissingTypeArgument is disabled.
let analysisResults = TestUtils.typeAnalyzeSampleFiles(['missingTypeArg1.py']);
TestUtils.validateResults(analysisResults, 1);
// Turn on errors.
configOptions.diagnosticRuleSet.reportMissingTypeArgument = 'error';
analysisResults = TestUtils.typeAnalyzeSampleFiles(['missingTypeArg1.py'], configOptions);
TestUtils.validateResults(analysisResults, 6);
});
test('GenericTypes4', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes4.py']);
TestUtils.validateResults(analysisResults, 5);
});
test('GenericTypes5', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes5.py']);
TestUtils.validateResults(analysisResults, 2);
});
test('GenericTypes6', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes6.py']);
TestUtils.validateResults(analysisResults, 3);
});
test('GenericTypes7', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes7.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes8', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes8.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes9', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes9.py']);
TestUtils.validateResults(analysisResults, 5);
});
test('GenericTypes10', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes10.py']);
TestUtils.validateResults(analysisResults, 3);
});
test('GenericTypes11', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes11.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes12', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes12.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes13', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes13.py']);
@ -523,24 +584,12 @@ test('GenericTypes19', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes20', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes20.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes21', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes21.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes22', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes22.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes23', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes23.py']);
@ -553,24 +602,6 @@ test('GenericTypes24', () => {
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes25', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes25.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes26', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes26.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes27', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes27.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes28', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes28.py']);
@ -583,12 +614,6 @@ test('GenericTypes29', () => {
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes30', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes30.py']);
TestUtils.validateResults(analysisResults, 3);
});
test('GenericTypes31', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes31.py']);
@ -601,49 +626,18 @@ test('GenericTypes32', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes33', () => {
const configOptions = new ConfigOptions('.');
// By default, reportMissingTypeArgument is disabled.
let analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes33.py']);
TestUtils.validateResults(analysisResults, 1);
// Turn on errors.
configOptions.diagnosticRuleSet.reportMissingTypeArgument = 'error';
analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes33.py'], configOptions);
TestUtils.validateResults(analysisResults, 6);
});
test('GenericTypes34', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes34.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes35', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes35.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes36', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes36.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes37', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes37.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes38', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes38.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes39', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes39.py']);
@ -686,12 +680,6 @@ test('GenericTypes45', () => {
TestUtils.validateResults(analysisResults, 2);
});
test('GenericTypes46', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes46.py']);
TestUtils.validateResults(analysisResults, 2);
});
test('GenericTypes47', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes47.py']);
@ -734,12 +722,6 @@ test('GenericTypes53', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes54', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes54.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes55', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes55.py']);
@ -788,12 +770,6 @@ test('GenericTypes62', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes63', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes63.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes64', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes64.py']);
@ -806,24 +782,6 @@ test('GenericTypes65', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes66', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes66.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes67', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes67.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes68', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes68.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes69', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes69.py']);
@ -872,12 +830,6 @@ test('GenericTypes75', () => {
TestUtils.validateResults(analysisResults, 1);
});
test('GenericTypes76', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes76.py']);
TestUtils.validateResults(analysisResults, 5);
});
test('GenericTypes77', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes77.py']);
@ -902,24 +854,12 @@ test('GenericTypes80', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes81', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes81.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes82', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes82.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes83', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes83.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('GenericTypes84', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes84.py']);

View File

@ -633,6 +633,12 @@ test('TypeAlias20', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('TypeAlias21', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeAlias21.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('RecursiveTypeAlias1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['recursiveTypeAlias1.py']);
@ -1439,6 +1445,12 @@ test('Constructor19', () => {
TestUtils.validateResults(analysisResults, 1);
});
test('Constructor20', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['constructor20.py']);
TestUtils.validateResults(analysisResults, 2);
});
test('InconsistentConstructor1', () => {
const configOptions = new ConfigOptions('.');

View File

@ -739,6 +739,18 @@ test('Generic1', () => {
TestUtils.validateResults(analysisResults, 9);
});
test('Generic2', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['generic2.py']);
TestUtils.validateResults(analysisResults, 3);
});
test('Generic3', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['generic3.py']);
TestUtils.validateResults(analysisResults, 3);
});
test('Unions1', () => {
const configOptions = new ConfigOptions('.');
@ -1206,3 +1218,9 @@ test('Del1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['del1.py']);
TestUtils.validateResults(analysisResults, 6);
});
test('Del2', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['del2.py']);
TestUtils.validateResults(analysisResults, 2);
});