From 0c5c7b65eff2cbcda2d3fa8761a1b485b67ee619 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 19 Jun 2023 14:23:50 -0700 Subject: [PATCH] Next batch of text case cleanup. --- ...istComprehension1.py => comprehension1.py} | 8 +- ...istComprehension2.py => comprehension2.py} | 0 ...istComprehension3.py => comprehension3.py} | 0 ...istComprehension4.py => comprehension4.py} | 0 ...istComprehension5.py => comprehension5.py} | 0 ...istComprehension6.py => comprehension6.py} | 0 ...istComprehension7.py => comprehension7.py} | 0 ...istComprehension8.py => comprehension8.py} | 4 +- ...istComprehension9.py => comprehension9.py} | 0 .../src/tests/samples/hashability1.py | 4 + .../src/tests/samples/import16.py | 1 - .../src/tests/samples/inferredTypes2.py | 2 +- .../src/tests/samples/isinstance1.py | 61 +-- .../src/tests/samples/isinstance5.py | 8 - .../src/tests/samples/lambda1.py | 4 +- .../src/tests/samples/lambda4.py | 6 +- .../src/tests/samples/lambda7.py | 1 + .../src/tests/samples/list1.py | 29 +- .../src/tests/samples/list2.py | 1 + .../src/tests/samples/list3.py | 1 + .../src/tests/samples/literalString1.py | 1 + .../src/tests/samples/{loops1.py => loop1.py} | 26 +- .../tests/samples/{loops10.py => loop10.py} | 0 .../tests/samples/{loops11.py => loop11.py} | 0 .../tests/samples/{loops12.py => loop12.py} | 2 +- .../tests/samples/{loops13.py => loop13.py} | 0 .../tests/samples/{loops14.py => loop14.py} | 4 +- .../tests/samples/{loops15.py => loop15.py} | 0 .../tests/samples/{loops16.py => loop16.py} | 0 .../tests/samples/{loops17.py => loop17.py} | 0 .../tests/samples/{loops18.py => loop18.py} | 0 .../tests/samples/{loops19.py => loop19.py} | 0 .../src/tests/samples/{loops2.py => loop2.py} | 4 +- .../tests/samples/{loops20.py => loop20.py} | 0 .../tests/samples/{loops21.py => loop21.py} | 0 .../tests/samples/{loops22.py => loop22.py} | 0 .../tests/samples/{loops23.py => loop23.py} | 0 .../tests/samples/{loops24.py => loop24.py} | 0 .../tests/samples/{loops25.py => loop25.py} | 0 .../tests/samples/{loops26.py => loop26.py} | 0 .../tests/samples/{loops27.py => loop27.py} | 0 .../tests/samples/{loops28.py => loop28.py} | 0 .../tests/samples/{loops29.py => loop29.py} | 0 .../src/tests/samples/{loops3.py => loop3.py} | 3 +- .../tests/samples/{loops30.py => loop30.py} | 0 .../tests/samples/{loops31.py => loop31.py} | 0 .../tests/samples/{loops32.py => loop32.py} | 0 .../tests/samples/{loops33.py => loop33.py} | 0 .../tests/samples/{loops34.py => loop34.py} | 0 .../tests/samples/{loops35.py => loop35.py} | 0 .../tests/samples/{loops36.py => loop36.py} | 0 .../tests/samples/{loops37.py => loop37.py} | 0 .../tests/samples/{loops38.py => loop38.py} | 0 .../src/tests/samples/{loops4.py => loop4.py} | 1 - .../src/tests/samples/{loops5.py => loop5.py} | 0 .../src/tests/samples/{loops6.py => loop6.py} | 16 +- .../src/tests/samples/{loops7.py => loop7.py} | 4 +- .../src/tests/samples/{loops8.py => loop8.py} | 2 +- .../src/tests/samples/{loops9.py => loop9.py} | 2 +- .../src/tests/samples/match12.py | 64 --- .../src/tests/samples/match2.py | 401 ++--------------- .../src/tests/samples/match3.py | 418 ++---------------- .../src/tests/samples/match7.py | 65 --- .../src/tests/samples/matchClass1.py | 392 ++++++++++++++++ .../samples/{match8.py => matchClass2.py} | 0 .../samples/{match9.py => matchClass3.py} | 0 .../{match10.py => matchExhaustion1.py} | 0 .../samples/{match6.py => matchLiteral1.py} | 0 .../samples/{match5.py => matchMapping1.py} | 14 +- .../src/tests/samples/matchSequence1.py | 378 ++++++++++++++++ .../{match11.py => matchUnnecessary1.py} | 0 .../samples/{match4.py => matchValue1.py} | 8 +- .../src/tests/samples/memberAccess1.py | 6 +- .../src/tests/samples/memberAccess11.py | 10 +- .../src/tests/samples/memberAccess12.py | 10 +- .../src/tests/samples/memberAccess13.py | 3 +- .../src/tests/samples/memberAccess14.py | 6 +- .../src/tests/samples/memberAccess19.py | 2 +- .../src/tests/samples/memberAccess2.py | 1 + .../src/tests/samples/memberAccess4.py | 4 +- .../src/tests/samples/memberAccess5.py | 4 +- .../src/tests/samples/memberAccess6.py | 32 +- .../src/tests/samples/memberAccess8.py | 8 +- .../src/tests/samples/metaclass1.py | 2 +- .../src/tests/samples/metaclass5.py | 22 +- .../src/tests/samples/metaclass9.py | 14 +- .../src/tests/samples/methodOverride1.py | 54 ++- .../src/tests/samples/methodOverride5.py | 4 +- .../src/tests/samples/methods1.py | 10 +- .../src/tests/samples/missingTypeArg1.py | 8 +- .../{nameBindings1.py => nameBinding1.py} | 0 .../{nameBindings2.py => nameBinding2.py} | 0 .../{nameBindings3.py => nameBinding3.py} | 0 .../{nameBindings4.py => nameBinding4.py} | 0 .../{nameBindings5.py => nameBinding5.py} | 0 ...ance10.py => typeNarrowingIsinstance13.py} | 0 ...tance9.py => typeNarrowingIsinstance14.py} | 4 +- ...tance7.py => typeNarrowingIsinstance15.py} | 0 ...tance6.py => typeNarrowingIsinstance16.py} | 10 +- .../samples/typeNarrowingIsinstance17.py | 57 +++ .../src/tests/typeEvaluator1.test.ts | 33 ++ .../src/tests/typeEvaluator2.test.ts | 55 +-- .../src/tests/typeEvaluator3.test.ts | 248 +++++------ 103 files changed, 1256 insertions(+), 1286 deletions(-) rename packages/pyright-internal/src/tests/samples/{listComprehension1.py => comprehension1.py} (80%) rename packages/pyright-internal/src/tests/samples/{listComprehension2.py => comprehension2.py} (100%) rename packages/pyright-internal/src/tests/samples/{listComprehension3.py => comprehension3.py} (100%) rename packages/pyright-internal/src/tests/samples/{listComprehension4.py => comprehension4.py} (100%) rename packages/pyright-internal/src/tests/samples/{listComprehension5.py => comprehension5.py} (100%) rename packages/pyright-internal/src/tests/samples/{listComprehension6.py => comprehension6.py} (100%) rename packages/pyright-internal/src/tests/samples/{listComprehension7.py => comprehension7.py} (100%) rename packages/pyright-internal/src/tests/samples/{listComprehension8.py => comprehension8.py} (88%) rename packages/pyright-internal/src/tests/samples/{listComprehension9.py => comprehension9.py} (100%) delete mode 100644 packages/pyright-internal/src/tests/samples/isinstance5.py rename packages/pyright-internal/src/tests/samples/{loops1.py => loop1.py} (58%) rename packages/pyright-internal/src/tests/samples/{loops10.py => loop10.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops11.py => loop11.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops12.py => loop12.py} (97%) rename packages/pyright-internal/src/tests/samples/{loops13.py => loop13.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops14.py => loop14.py} (86%) rename packages/pyright-internal/src/tests/samples/{loops15.py => loop15.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops16.py => loop16.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops17.py => loop17.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops18.py => loop18.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops19.py => loop19.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops2.py => loop2.py} (82%) rename packages/pyright-internal/src/tests/samples/{loops20.py => loop20.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops21.py => loop21.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops22.py => loop22.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops23.py => loop23.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops24.py => loop24.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops25.py => loop25.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops26.py => loop26.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops27.py => loop27.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops28.py => loop28.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops29.py => loop29.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops3.py => loop3.py} (77%) rename packages/pyright-internal/src/tests/samples/{loops30.py => loop30.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops31.py => loop31.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops32.py => loop32.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops33.py => loop33.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops34.py => loop34.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops35.py => loop35.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops36.py => loop36.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops37.py => loop37.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops38.py => loop38.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops4.py => loop4.py} (99%) rename packages/pyright-internal/src/tests/samples/{loops5.py => loop5.py} (100%) rename packages/pyright-internal/src/tests/samples/{loops6.py => loop6.py} (54%) rename packages/pyright-internal/src/tests/samples/{loops7.py => loop7.py} (87%) rename packages/pyright-internal/src/tests/samples/{loops8.py => loop8.py} (89%) rename packages/pyright-internal/src/tests/samples/{loops9.py => loop9.py} (89%) delete mode 100644 packages/pyright-internal/src/tests/samples/match12.py delete mode 100644 packages/pyright-internal/src/tests/samples/match7.py create mode 100644 packages/pyright-internal/src/tests/samples/matchClass1.py rename packages/pyright-internal/src/tests/samples/{match8.py => matchClass2.py} (100%) rename packages/pyright-internal/src/tests/samples/{match9.py => matchClass3.py} (100%) rename packages/pyright-internal/src/tests/samples/{match10.py => matchExhaustion1.py} (100%) rename packages/pyright-internal/src/tests/samples/{match6.py => matchLiteral1.py} (100%) rename packages/pyright-internal/src/tests/samples/{match5.py => matchMapping1.py} (89%) create mode 100644 packages/pyright-internal/src/tests/samples/matchSequence1.py rename packages/pyright-internal/src/tests/samples/{match11.py => matchUnnecessary1.py} (100%) rename packages/pyright-internal/src/tests/samples/{match4.py => matchValue1.py} (93%) rename packages/pyright-internal/src/tests/samples/{nameBindings1.py => nameBinding1.py} (100%) rename packages/pyright-internal/src/tests/samples/{nameBindings2.py => nameBinding2.py} (100%) rename packages/pyright-internal/src/tests/samples/{nameBindings3.py => nameBinding3.py} (100%) rename packages/pyright-internal/src/tests/samples/{nameBindings4.py => nameBinding4.py} (100%) rename packages/pyright-internal/src/tests/samples/{nameBindings5.py => nameBinding5.py} (100%) rename packages/pyright-internal/src/tests/samples/{isinstance10.py => typeNarrowingIsinstance13.py} (100%) rename packages/pyright-internal/src/tests/samples/{isinstance9.py => typeNarrowingIsinstance14.py} (83%) rename packages/pyright-internal/src/tests/samples/{isinstance7.py => typeNarrowingIsinstance15.py} (100%) rename packages/pyright-internal/src/tests/samples/{isinstance6.py => typeNarrowingIsinstance16.py} (55%) create mode 100644 packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance17.py diff --git a/packages/pyright-internal/src/tests/samples/listComprehension1.py b/packages/pyright-internal/src/tests/samples/comprehension1.py similarity index 80% rename from packages/pyright-internal/src/tests/samples/listComprehension1.py rename to packages/pyright-internal/src/tests/samples/comprehension1.py index 47dc49c0a3a1..7d34de998961 100644 --- a/packages/pyright-internal/src/tests/samples/listComprehension1.py +++ b/packages/pyright-internal/src/tests/samples/comprehension1.py @@ -1,6 +1,6 @@ # This sample tests type checking for list comprehensions. -from typing import Any, Generator, Iterable, List, Literal +from typing import Generator, Iterable, Literal a = [1, 2, 3, 4] @@ -10,12 +10,12 @@ def func1() -> Generator[int, None, None]: return b -def func2() -> List[int]: +def func2() -> list[int]: c = [elem for elem in a] return c -def func3() -> List[str]: +def func3() -> list[str]: c = [elem for elem in a] # This should generate an error because @@ -37,7 +37,7 @@ def generate(): FooOrBar = Literal["foo", "bar"] -def to_list(values: Iterable[FooOrBar]) -> List[FooOrBar]: +def to_list(values: Iterable[FooOrBar]) -> list[FooOrBar]: return [value for value in values] x = 3 diff --git a/packages/pyright-internal/src/tests/samples/listComprehension2.py b/packages/pyright-internal/src/tests/samples/comprehension2.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/listComprehension2.py rename to packages/pyright-internal/src/tests/samples/comprehension2.py diff --git a/packages/pyright-internal/src/tests/samples/listComprehension3.py b/packages/pyright-internal/src/tests/samples/comprehension3.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/listComprehension3.py rename to packages/pyright-internal/src/tests/samples/comprehension3.py diff --git a/packages/pyright-internal/src/tests/samples/listComprehension4.py b/packages/pyright-internal/src/tests/samples/comprehension4.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/listComprehension4.py rename to packages/pyright-internal/src/tests/samples/comprehension4.py diff --git a/packages/pyright-internal/src/tests/samples/listComprehension5.py b/packages/pyright-internal/src/tests/samples/comprehension5.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/listComprehension5.py rename to packages/pyright-internal/src/tests/samples/comprehension5.py diff --git a/packages/pyright-internal/src/tests/samples/listComprehension6.py b/packages/pyright-internal/src/tests/samples/comprehension6.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/listComprehension6.py rename to packages/pyright-internal/src/tests/samples/comprehension6.py diff --git a/packages/pyright-internal/src/tests/samples/listComprehension7.py b/packages/pyright-internal/src/tests/samples/comprehension7.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/listComprehension7.py rename to packages/pyright-internal/src/tests/samples/comprehension7.py diff --git a/packages/pyright-internal/src/tests/samples/listComprehension8.py b/packages/pyright-internal/src/tests/samples/comprehension8.py similarity index 88% rename from packages/pyright-internal/src/tests/samples/listComprehension8.py rename to packages/pyright-internal/src/tests/samples/comprehension8.py index 2bf4d8b6c197..5196e9697b22 100644 --- a/packages/pyright-internal/src/tests/samples/listComprehension8.py +++ b/packages/pyright-internal/src/tests/samples/comprehension8.py @@ -4,12 +4,12 @@ # pyright: strict -class Foo: +class ClassA: input: str output: str -def minify1(foo: Foo): +def func1(foo: ClassA): foo.output = "".join( stripped for line in foo.input.splitlines() if (stripped := line.strip()) ) diff --git a/packages/pyright-internal/src/tests/samples/listComprehension9.py b/packages/pyright-internal/src/tests/samples/comprehension9.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/listComprehension9.py rename to packages/pyright-internal/src/tests/samples/comprehension9.py diff --git a/packages/pyright-internal/src/tests/samples/hashability1.py b/packages/pyright-internal/src/tests/samples/hashability1.py index 935b21f78ae7..4429b30cc62a 100644 --- a/packages/pyright-internal/src/tests/samples/hashability1.py +++ b/packages/pyright-internal/src/tests/samples/hashability1.py @@ -11,10 +11,12 @@ # This should generate two errors because {} and [] are not hashable. s2: set[Any] = {{}, 2, dict, frozenset(), []} + class StrList(list[str]): def __hash__(self) -> int: ... + s3 = {StrList()} @@ -31,10 +33,12 @@ def func1(x: str | dict[Any, Any], y: Any, z: None): d4 = {y: "hi", z: "hi"} + @dataclass class DC1: a: int + @dataclass(frozen=True) class DC2: a: int diff --git a/packages/pyright-internal/src/tests/samples/import16.py b/packages/pyright-internal/src/tests/samples/import16.py index b506a57957a4..228354d3de74 100644 --- a/packages/pyright-internal/src/tests/samples/import16.py +++ b/packages/pyright-internal/src/tests/samples/import16.py @@ -4,4 +4,3 @@ import html.entities x = html.escape - diff --git a/packages/pyright-internal/src/tests/samples/inferredTypes2.py b/packages/pyright-internal/src/tests/samples/inferredTypes2.py index adbd547e9e73..e988cc928d73 100644 --- a/packages/pyright-internal/src/tests/samples/inferredTypes2.py +++ b/packages/pyright-internal/src/tests/samples/inferredTypes2.py @@ -1,6 +1,7 @@ # This sample tests the ability of the type checker to infer # the types of instance variables based on their assigned values. + class ClassA: def __init__(self): self.value = None @@ -13,4 +14,3 @@ def func(self, param: int): self.value.bit_length() self.value = param - diff --git a/packages/pyright-internal/src/tests/samples/isinstance1.py b/packages/pyright-internal/src/tests/samples/isinstance1.py index 5a8d6292986a..cf1d7beb18be 100644 --- a/packages/pyright-internal/src/tests/samples/isinstance1.py +++ b/packages/pyright-internal/src/tests/samples/isinstance1.py @@ -1,57 +1,8 @@ -# This sample tests basic type narrowing behavior for -# the isinstance call. +# This sample tests the use of "self.__class__" and "__class__" +# in an isinstance call. -from typing import Any, List, Optional, Type, TypedDict, Union - -def func1(x: Union[List[str], int]): - if isinstance(x, list): - reveal_type(x, expected_text="List[str]") - else: - reveal_type(x, expected_text="int") - - -def func2(x: Any): - if isinstance(x, list): - reveal_type(x, expected_text="list[Unknown]") - else: - reveal_type(x, expected_text="Any") - - -def func3(x): - if isinstance(x, list): - reveal_type(x, expected_text="list[Unknown]") - else: - reveal_type(x, expected_text="Unknown") - - -class SomeTypedDict(TypedDict): - name: str - - -def func4(x: Union[int, SomeTypedDict]): - if isinstance(x, dict): - reveal_type(x, expected_text="SomeTypedDict") - else: - reveal_type(x, expected_text="int") - - -def func5(x: int | str | complex): - if isinstance(x, (int, str)): - reveal_type(x, expected_text="int | str") - else: - reveal_type(x, expected_text="complex") - - -def func6(x: Type[int] | Type[str] | Type[complex]): - if issubclass(x, (int, str)): - reveal_type(x, expected_text="type[int] | type[str]") - else: - reveal_type(x, expected_text="type[complex]") - - -def func7(x: Optional[Union[int, SomeTypedDict]]): - if isinstance(x, (dict, type(None))): - reveal_type(x, expected_text="SomeTypedDict | None") - else: - reveal_type(x, expected_text="int") +class Foo: + def bar(self): + a = isinstance(object(), self.__class__) + b = isinstance(object(), __class__) diff --git a/packages/pyright-internal/src/tests/samples/isinstance5.py b/packages/pyright-internal/src/tests/samples/isinstance5.py deleted file mode 100644 index cf1d7beb18be..000000000000 --- a/packages/pyright-internal/src/tests/samples/isinstance5.py +++ /dev/null @@ -1,8 +0,0 @@ -# This sample tests the use of "self.__class__" and "__class__" -# in an isinstance call. - - -class Foo: - def bar(self): - a = isinstance(object(), self.__class__) - b = isinstance(object(), __class__) diff --git a/packages/pyright-internal/src/tests/samples/lambda1.py b/packages/pyright-internal/src/tests/samples/lambda1.py index 96aee866b536..668ab08859f7 100644 --- a/packages/pyright-internal/src/tests/samples/lambda1.py +++ b/packages/pyright-internal/src/tests/samples/lambda1.py @@ -1,5 +1,5 @@ # This sample tests type checking for lambdas and their parameters. -from typing import Any, Callable, Iterable, Optional, TypeVar +from typing import Callable, Iterable, TypeVar #------------------------------------------------------ # Test basic lambda matching @@ -64,7 +64,7 @@ def needs_function2(callback: Callable[[str, int], str]): _T1 = TypeVar('_T1') -def may_need_function_generic(callback: Optional[Callable[[_T1], _T1]]): +def may_need_function_generic(callback: Callable[[_T1], _T1] | None): pass may_need_function_generic(lambda x: x) diff --git a/packages/pyright-internal/src/tests/samples/lambda4.py b/packages/pyright-internal/src/tests/samples/lambda4.py index 590182b7eaa2..8644fe2405c9 100644 --- a/packages/pyright-internal/src/tests/samples/lambda4.py +++ b/packages/pyright-internal/src/tests/samples/lambda4.py @@ -1,10 +1,10 @@ # This sample tests the case where a lambda is assigned to # a union type that contains multiple callables. -from typing import Callable, Protocol, Union +from typing import Callable, Protocol -U1 = Union[Callable[[int, str], bool], Callable[[str], bool]] +U1 = Callable[[int, str], bool] | Callable[[str], bool] def accepts_u1(cb: U1) -> U1: @@ -54,7 +54,7 @@ def __call__(self, p0: int, p1: str, *p2: str) -> bool: ... -U2 = Union[Callable1, Callable2, Callable3, Callable4] +U2 = Callable1 | Callable2 | Callable3 | Callable4 def accepts_u2(cb: U2) -> U2: diff --git a/packages/pyright-internal/src/tests/samples/lambda7.py b/packages/pyright-internal/src/tests/samples/lambda7.py index 66ffd847536d..4428736b2be9 100644 --- a/packages/pyright-internal/src/tests/samples/lambda7.py +++ b/packages/pyright-internal/src/tests/samples/lambda7.py @@ -4,5 +4,6 @@ # pyright: strict + def func1(keys: list[str]): filter(lambda s: s.startswith(""), keys) diff --git a/packages/pyright-internal/src/tests/samples/list1.py b/packages/pyright-internal/src/tests/samples/list1.py index 2f7ff84a0d5b..83faf0e3a725 100644 --- a/packages/pyright-internal/src/tests/samples/list1.py +++ b/packages/pyright-internal/src/tests/samples/list1.py @@ -2,18 +2,7 @@ # pyright: strict, reportUnknownVariableType=false -from typing import ( - Any, - Collection, - Dict, - Generic, - List, - Literal, - Optional, - Sequence, - TypeVar, - Union, -) +from typing import Any, Collection, Generic, Literal, Sequence, TypeVar v1 = [1, 2, 3] @@ -25,7 +14,7 @@ v3 = [] reveal_type(v3, expected_text="list[Unknown]") -v4: List[object] = [] +v4: list[object] = [] v5: object = [] @@ -58,22 +47,22 @@ class Bar: v10.baz = [Foo()] reveal_type(v10.baz, expected_text="list[Foo]") -v11: List[Any] = [["hi", ["hi"], [[{}]]]] +v11: list[Any] = [["hi", ["hi"], [[{}]]]] reveal_type(v11, expected_text="list[Any]") -v12: List[Optional[int]] = [None] * 3 +v12: list[int | None] = [None] * 3 reveal_type(v12, expected_text="list[int | None]") -v13: List[Optional[str]] = ["3", None] * 2 +v13: list[str | None] = ["3", None] * 2 reveal_type(v13, expected_text="list[str | None]") x1 = 3 -v14: List[Optional[str]] = [None] * x1 +v14: list[str | None] = [None] * x1 x2 = [1, 2, 3] -v15: List[Optional[str]] = [None] * sum(x2) +v15: list[str | None] = [None] * sum(x2) -v16: Dict[str, List[Optional[str]]] = {n: [None] * len(n) for n in ["a", "aa", "aaa"]} +v16: dict[str, list[str | None]] = {n: [None] * len(n) for n in ["a", "aa", "aaa"]} ScalarKeysT = TypeVar("ScalarKeysT", bound=Literal["name", "country"]) @@ -91,7 +80,7 @@ def func1(by: list[ScalarKeysT]) -> ScalarKeysT: func1(["id"]) -def func2(thing: Union[str, List[Union[str, int]], List[List[Union[str, int]]]]): +def func2(thing: str | list[str | int] | list[list[str | int]]): ... diff --git a/packages/pyright-internal/src/tests/samples/list2.py b/packages/pyright-internal/src/tests/samples/list2.py index 1a6c1649ad43..eef2dac3cdfe 100644 --- a/packages/pyright-internal/src/tests/samples/list2.py +++ b/packages/pyright-internal/src/tests/samples/list2.py @@ -4,6 +4,7 @@ import random from typing_extensions import LiteralString + # The join method is overloaded with both LiteralString and str variants. # We need to use the str overload here. def func(x: LiteralString): diff --git a/packages/pyright-internal/src/tests/samples/list3.py b/packages/pyright-internal/src/tests/samples/list3.py index 07a304fc9f67..f179a353075e 100644 --- a/packages/pyright-internal/src/tests/samples/list3.py +++ b/packages/pyright-internal/src/tests/samples/list3.py @@ -1,6 +1,7 @@ # This sample tests list inference in a loop where the type of # the inferred list changes each time through the loop. + def func1(k: str): keys = ["a", "b", "c"] value = [] diff --git a/packages/pyright-internal/src/tests/samples/literalString1.py b/packages/pyright-internal/src/tests/samples/literalString1.py index 916b3ff765b0..3da49f10657b 100644 --- a/packages/pyright-internal/src/tests/samples/literalString1.py +++ b/packages/pyright-internal/src/tests/samples/literalString1.py @@ -74,6 +74,7 @@ def func6(a: LiteralString): v3: list[str] = "1 2 3".split(" ") + def func7(a: Literal["a", "b"], b: Literal["a", 1]): v1: LiteralString = f"{a}" diff --git a/packages/pyright-internal/src/tests/samples/loops1.py b/packages/pyright-internal/src/tests/samples/loop1.py similarity index 58% rename from packages/pyright-internal/src/tests/samples/loops1.py rename to packages/pyright-internal/src/tests/samples/loop1.py index f40ab42346a3..8bb46624c4b7 100644 --- a/packages/pyright-internal/src/tests/samples/loops1.py +++ b/packages/pyright-internal/src/tests/samples/loop1.py @@ -2,44 +2,44 @@ # inferences within loop constructs. -def bar(a: list): +def func1(a: list): pass -def func1(): +def func2(): data = None for x in [2, 3]: if not data: data = [1, 2] else: - # This should not generate an error because the - # type checker should be able to determine that - # data must be a list at this point in the code. - bar(data) + reveal_type(data, expected_text="list[int]") + func1(data) else: + reveal_type(data, expected_text="list[int] | None") + # This should generate an error because the # type checker should be able to determine that # data must contain None at this point. - bar(data) + func1(data) x = 20 + 20 -def func2(): +def func3(): data = None while x: if not data: data = [1, 2] else: - # This should not generate an error because the - # type checker should be able to determine that - # data must be a list at this point in the code. - bar(data) + reveal_type(data, expected_text="list[int]") + func1(data) else: + reveal_type(data, expected_text="list[int] | None") + # This should generate an error because the # type checker should be able to determine that # data must contain None at this point. - bar(data) + func1(data) diff --git a/packages/pyright-internal/src/tests/samples/loops10.py b/packages/pyright-internal/src/tests/samples/loop10.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops10.py rename to packages/pyright-internal/src/tests/samples/loop10.py diff --git a/packages/pyright-internal/src/tests/samples/loops11.py b/packages/pyright-internal/src/tests/samples/loop11.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops11.py rename to packages/pyright-internal/src/tests/samples/loop11.py diff --git a/packages/pyright-internal/src/tests/samples/loops12.py b/packages/pyright-internal/src/tests/samples/loop12.py similarity index 97% rename from packages/pyright-internal/src/tests/samples/loops12.py rename to packages/pyright-internal/src/tests/samples/loop12.py index bd7918d17aec..1da804ee1e7d 100644 --- a/packages/pyright-internal/src/tests/samples/loops12.py +++ b/packages/pyright-internal/src/tests/samples/loop12.py @@ -2,7 +2,7 @@ # within a loop body. -class Foo: +class ClassA: def non_property(self) -> int: ... diff --git a/packages/pyright-internal/src/tests/samples/loops13.py b/packages/pyright-internal/src/tests/samples/loop13.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops13.py rename to packages/pyright-internal/src/tests/samples/loop13.py diff --git a/packages/pyright-internal/src/tests/samples/loops14.py b/packages/pyright-internal/src/tests/samples/loop14.py similarity index 86% rename from packages/pyright-internal/src/tests/samples/loops14.py rename to packages/pyright-internal/src/tests/samples/loop14.py index 414e13c1d12f..6cfeb7adc70e 100644 --- a/packages/pyright-internal/src/tests/samples/loops14.py +++ b/packages/pyright-internal/src/tests/samples/loop14.py @@ -1,10 +1,8 @@ # This sample tests a loop that modifies a variable through type narrowing. -from typing import Union - class State: - def confirm_dialog(self) -> Union["State", bool]: + def confirm_dialog(self) -> "State | bool": return False diff --git a/packages/pyright-internal/src/tests/samples/loops15.py b/packages/pyright-internal/src/tests/samples/loop15.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops15.py rename to packages/pyright-internal/src/tests/samples/loop15.py diff --git a/packages/pyright-internal/src/tests/samples/loops16.py b/packages/pyright-internal/src/tests/samples/loop16.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops16.py rename to packages/pyright-internal/src/tests/samples/loop16.py diff --git a/packages/pyright-internal/src/tests/samples/loops17.py b/packages/pyright-internal/src/tests/samples/loop17.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops17.py rename to packages/pyright-internal/src/tests/samples/loop17.py diff --git a/packages/pyright-internal/src/tests/samples/loops18.py b/packages/pyright-internal/src/tests/samples/loop18.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops18.py rename to packages/pyright-internal/src/tests/samples/loop18.py diff --git a/packages/pyright-internal/src/tests/samples/loops19.py b/packages/pyright-internal/src/tests/samples/loop19.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops19.py rename to packages/pyright-internal/src/tests/samples/loop19.py diff --git a/packages/pyright-internal/src/tests/samples/loops2.py b/packages/pyright-internal/src/tests/samples/loop2.py similarity index 82% rename from packages/pyright-internal/src/tests/samples/loops2.py rename to packages/pyright-internal/src/tests/samples/loop2.py index 268bfd7f0140..fa49cd9725b1 100644 --- a/packages/pyright-internal/src/tests/samples/loops2.py +++ b/packages/pyright-internal/src/tests/samples/loop2.py @@ -1,10 +1,8 @@ # This sample tests a piece of code that involves lots # of cyclical dependencies for type resolution. -from typing import Tuple - -def needs_str(a: str) -> Tuple[str, str]: +def needs_str(a: str) -> tuple[str, str]: ... diff --git a/packages/pyright-internal/src/tests/samples/loops20.py b/packages/pyright-internal/src/tests/samples/loop20.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops20.py rename to packages/pyright-internal/src/tests/samples/loop20.py diff --git a/packages/pyright-internal/src/tests/samples/loops21.py b/packages/pyright-internal/src/tests/samples/loop21.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops21.py rename to packages/pyright-internal/src/tests/samples/loop21.py diff --git a/packages/pyright-internal/src/tests/samples/loops22.py b/packages/pyright-internal/src/tests/samples/loop22.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops22.py rename to packages/pyright-internal/src/tests/samples/loop22.py diff --git a/packages/pyright-internal/src/tests/samples/loops23.py b/packages/pyright-internal/src/tests/samples/loop23.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops23.py rename to packages/pyright-internal/src/tests/samples/loop23.py diff --git a/packages/pyright-internal/src/tests/samples/loops24.py b/packages/pyright-internal/src/tests/samples/loop24.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops24.py rename to packages/pyright-internal/src/tests/samples/loop24.py diff --git a/packages/pyright-internal/src/tests/samples/loops25.py b/packages/pyright-internal/src/tests/samples/loop25.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops25.py rename to packages/pyright-internal/src/tests/samples/loop25.py diff --git a/packages/pyright-internal/src/tests/samples/loops26.py b/packages/pyright-internal/src/tests/samples/loop26.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops26.py rename to packages/pyright-internal/src/tests/samples/loop26.py diff --git a/packages/pyright-internal/src/tests/samples/loops27.py b/packages/pyright-internal/src/tests/samples/loop27.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops27.py rename to packages/pyright-internal/src/tests/samples/loop27.py diff --git a/packages/pyright-internal/src/tests/samples/loops28.py b/packages/pyright-internal/src/tests/samples/loop28.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops28.py rename to packages/pyright-internal/src/tests/samples/loop28.py diff --git a/packages/pyright-internal/src/tests/samples/loops29.py b/packages/pyright-internal/src/tests/samples/loop29.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops29.py rename to packages/pyright-internal/src/tests/samples/loop29.py diff --git a/packages/pyright-internal/src/tests/samples/loops3.py b/packages/pyright-internal/src/tests/samples/loop3.py similarity index 77% rename from packages/pyright-internal/src/tests/samples/loops3.py rename to packages/pyright-internal/src/tests/samples/loop3.py index c9a5af45f48d..3c5109132b11 100644 --- a/packages/pyright-internal/src/tests/samples/loops3.py +++ b/packages/pyright-internal/src/tests/samples/loop3.py @@ -1,9 +1,8 @@ # This sample tests a piece of code that involves lots # of cyclical dependencies for type resolution. -from typing import Optional -n: Optional[str] = None +n: str | None = None while True: if n is None: n = "" diff --git a/packages/pyright-internal/src/tests/samples/loops30.py b/packages/pyright-internal/src/tests/samples/loop30.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops30.py rename to packages/pyright-internal/src/tests/samples/loop30.py diff --git a/packages/pyright-internal/src/tests/samples/loops31.py b/packages/pyright-internal/src/tests/samples/loop31.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops31.py rename to packages/pyright-internal/src/tests/samples/loop31.py diff --git a/packages/pyright-internal/src/tests/samples/loops32.py b/packages/pyright-internal/src/tests/samples/loop32.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops32.py rename to packages/pyright-internal/src/tests/samples/loop32.py diff --git a/packages/pyright-internal/src/tests/samples/loops33.py b/packages/pyright-internal/src/tests/samples/loop33.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops33.py rename to packages/pyright-internal/src/tests/samples/loop33.py diff --git a/packages/pyright-internal/src/tests/samples/loops34.py b/packages/pyright-internal/src/tests/samples/loop34.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops34.py rename to packages/pyright-internal/src/tests/samples/loop34.py diff --git a/packages/pyright-internal/src/tests/samples/loops35.py b/packages/pyright-internal/src/tests/samples/loop35.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops35.py rename to packages/pyright-internal/src/tests/samples/loop35.py diff --git a/packages/pyright-internal/src/tests/samples/loops36.py b/packages/pyright-internal/src/tests/samples/loop36.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops36.py rename to packages/pyright-internal/src/tests/samples/loop36.py diff --git a/packages/pyright-internal/src/tests/samples/loops37.py b/packages/pyright-internal/src/tests/samples/loop37.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops37.py rename to packages/pyright-internal/src/tests/samples/loop37.py diff --git a/packages/pyright-internal/src/tests/samples/loops38.py b/packages/pyright-internal/src/tests/samples/loop38.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops38.py rename to packages/pyright-internal/src/tests/samples/loop38.py diff --git a/packages/pyright-internal/src/tests/samples/loops4.py b/packages/pyright-internal/src/tests/samples/loop4.py similarity index 99% rename from packages/pyright-internal/src/tests/samples/loops4.py rename to packages/pyright-internal/src/tests/samples/loop4.py index a4a652e07c41..bdcc1af37ad5 100644 --- a/packages/pyright-internal/src/tests/samples/loops4.py +++ b/packages/pyright-internal/src/tests/samples/loop4.py @@ -4,7 +4,6 @@ x: int = 0 while len(input()) < 42: - x += 43 if a and a: diff --git a/packages/pyright-internal/src/tests/samples/loops5.py b/packages/pyright-internal/src/tests/samples/loop5.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/loops5.py rename to packages/pyright-internal/src/tests/samples/loop5.py diff --git a/packages/pyright-internal/src/tests/samples/loops6.py b/packages/pyright-internal/src/tests/samples/loop6.py similarity index 54% rename from packages/pyright-internal/src/tests/samples/loops6.py rename to packages/pyright-internal/src/tests/samples/loop6.py index 66721a5cbf30..68c6bb85aa1f 100644 --- a/packages/pyright-internal/src/tests/samples/loops6.py +++ b/packages/pyright-internal/src/tests/samples/loop6.py @@ -2,24 +2,24 @@ # between untyped variables. -class Foo: - def new_from_dict(self, param1): - return Foo() +class ClassA: + def method1(self, param1): + return ClassA() - def method1(self): + def method2(self): return {}, {} def method3(self, param3): while True: for key in param3.keys(): - foo1 = self.new_from_dict({key: None}) - var1, var2 = foo1.method1() + foo1 = self.method1({key: None}) + var1, var2 = foo1.method2() if len(var1) < 2: param3 = var2 break - foo2 = foo1.new_from_dict({}) - var1, var2 = foo2.method1() + foo2 = foo1.method1({}) + var1, var2 = foo2.method2() else: break diff --git a/packages/pyright-internal/src/tests/samples/loops7.py b/packages/pyright-internal/src/tests/samples/loop7.py similarity index 87% rename from packages/pyright-internal/src/tests/samples/loops7.py rename to packages/pyright-internal/src/tests/samples/loop7.py index 73cddf8c74b6..26b6750d59fe 100644 --- a/packages/pyright-internal/src/tests/samples/loops7.py +++ b/packages/pyright-internal/src/tests/samples/loop7.py @@ -5,10 +5,10 @@ from typing import Optional -class Foo: +class ClassA: name: Optional[str] - def correct(self): + def method1(self): if self.name is not None: for _ in []: self.name = self.name.replace("", "") diff --git a/packages/pyright-internal/src/tests/samples/loops8.py b/packages/pyright-internal/src/tests/samples/loop8.py similarity index 89% rename from packages/pyright-internal/src/tests/samples/loops8.py rename to packages/pyright-internal/src/tests/samples/loop8.py index a22bca83aadf..ee09691caf32 100644 --- a/packages/pyright-internal/src/tests/samples/loops8.py +++ b/packages/pyright-internal/src/tests/samples/loop8.py @@ -6,7 +6,7 @@ from typing import Iterable -def test(parts: Iterable[str]): +def func1(parts: Iterable[str]): x: list[str] = [] ns = "" for part in parts: diff --git a/packages/pyright-internal/src/tests/samples/loops9.py b/packages/pyright-internal/src/tests/samples/loop9.py similarity index 89% rename from packages/pyright-internal/src/tests/samples/loops9.py rename to packages/pyright-internal/src/tests/samples/loop9.py index 7e87318d480d..8e162cc52a6e 100644 --- a/packages/pyright-internal/src/tests/samples/loops9.py +++ b/packages/pyright-internal/src/tests/samples/loop9.py @@ -14,7 +14,7 @@ class B(A): pass -def foo(v: A, s: Dict[B, A]) -> object: +def func1(v: A, s: Dict[B, A]) -> object: if not isinstance(v, B): return v u = s.get(v) diff --git a/packages/pyright-internal/src/tests/samples/match12.py b/packages/pyright-internal/src/tests/samples/match12.py deleted file mode 100644 index 954a0d10b5ab..000000000000 --- a/packages/pyright-internal/src/tests/samples/match12.py +++ /dev/null @@ -1,64 +0,0 @@ -# This sample tests narrowing of subject subexpressions in match statements. - -from typing import Literal, TypedDict - - -class TD1(TypedDict): - name: Literal["a"] - extra_value: int - - -class TD2(TypedDict): - name: Literal["b"] - other_extra_value: int - - -def func1(item: TD1 | TD2): - match item["name"]: - case "c": - reveal_type(item, expected_text="Never") - case "a": - reveal_type(item, expected_text="TD1") - case "b": - reveal_type(item, expected_text="TD2") - - -T1 = tuple[Literal[0], int] -T2 = tuple[Literal[1], str] - - -def func2(item: T1 | T2): - match item[0]: - case 0: - reveal_type(item, expected_text="tuple[Literal[0], int]") - case 1: - reveal_type(item, expected_text="tuple[Literal[1], str]") - - -def func3(a: object, b: int) -> None: - match a, b: - case (complex(), 3): - reveal_type(a, expected_text="complex") - reveal_type(b, expected_text="Literal[3]") - - -Token = ( - str - | tuple[Literal["define"], str, str] - | tuple[Literal["include"], str] - | tuple[Literal["use"], str, int, int] -) - - -def func4(token: Token): - match token: - case str(x): - reveal_type(token, expected_text="str") - case "define", _, _: - reveal_type(token, expected_text="tuple[Literal['define'], str, str]") - case "include", _: - reveal_type(token, expected_text="tuple[Literal['include'], str]") - case "use", _, _, _: - reveal_type(token, expected_text="tuple[Literal['use'], str, int, int]") - case _: - reveal_type(token, expected_text="Never") diff --git a/packages/pyright-internal/src/tests/samples/match2.py b/packages/pyright-internal/src/tests/samples/match2.py index 209c80b3baa6..98b638aa9f01 100644 --- a/packages/pyright-internal/src/tests/samples/match2.py +++ b/packages/pyright-internal/src/tests/samples/match2.py @@ -1,378 +1,65 @@ -# This sample tests type checking for match statements (as -# described in PEP 634) that contain sequence patterns. +# This sample tests type narrowing of subject expressions for +# match statements. -from typing import Any, Generic, List, Literal, Protocol, Tuple, TypeVar, Union -def test_unknown(value_to_match): - match value_to_match: - case a1, a2: - reveal_type(a1, expected_text="Unknown") - reveal_type(a2, expected_text="Unknown") - - case *b1, b2: - reveal_type(b1, expected_text="list[Unknown]") - reveal_type(b2, expected_text="Unknown") - - case c1, *c2: - reveal_type(c1, expected_text="Unknown") - reveal_type(c2, expected_text="list[Unknown]") - - case d1, *d2, d3: - reveal_type(d1, expected_text="Unknown") - reveal_type(d2, expected_text="list[Unknown]") - reveal_type(d3, expected_text="Unknown") - - case 3, *e1: - reveal_type(e1, expected_text="list[Unknown]") - - case "hi", *f1: - reveal_type(f1, expected_text="list[Unknown]") - - case *g1, "hi": - reveal_type(g1, expected_text="list[Unknown]") - - -def test_list(value_to_match: List[str]): - match value_to_match: - case a1, a2: - reveal_type(a1, expected_text="str") - reveal_type(a2, expected_text="str") - reveal_type(value_to_match, expected_text="List[str]") - - case *b1, b2: - reveal_type(b1, expected_text="list[str]") - reveal_type(b2, expected_text="str") - reveal_type(value_to_match, expected_text="List[str]") - - case c1, *c2: - reveal_type(c1, expected_text="str") - reveal_type(c2, expected_text="list[str]") - reveal_type(value_to_match, expected_text="List[str]") - - case d1, *d2, d3: - reveal_type(d1, expected_text="str") - reveal_type(d2, expected_text="list[str]") - reveal_type(d3, expected_text="str") - reveal_type(value_to_match, expected_text="List[str]") - - case 3, *e1: - reveal_type(e1, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - case "hi", *f1: - reveal_type(f1, expected_text="list[str]") - reveal_type(value_to_match, expected_text="List[str]") - - case *g1, "hi": - reveal_type(g1, expected_text="list[str]") - reveal_type(value_to_match, expected_text="List[str]") - -def test_open_ended_tuple(value_to_match: Tuple[str, ...]): - match value_to_match: - case a1, a2: - reveal_type(a1, expected_text="str") - reveal_type(a2, expected_text="str") - reveal_type(value_to_match, expected_text="tuple[str, str]") - - case *b1, b2: - reveal_type(b1, expected_text="list[str]") - reveal_type(b2, expected_text="str") - reveal_type(value_to_match, expected_text="Tuple[str, ...]") - - case c1, *c2: - reveal_type(c1, expected_text="str") - reveal_type(c2, expected_text="list[str]") - reveal_type(value_to_match, expected_text="Tuple[str, ...]") - - case d1, *d2, d3: - reveal_type(d1, expected_text="str") - reveal_type(d2, expected_text="list[str]") - reveal_type(d3, expected_text="str") - reveal_type(value_to_match, expected_text="Tuple[str, ...]") - - case 3, *e1: - reveal_type(e1, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - case "hi", *f1: - reveal_type(f1, expected_text="list[str]") - reveal_type(value_to_match, expected_text="Tuple[str, ...]") - - case *g1, "hi": - reveal_type(g1, expected_text="list[str]") - reveal_type(value_to_match, expected_text="Tuple[str, ...]") - -def test_definite_tuple(value_to_match: Tuple[int, str, float, complex]): - match value_to_match: - case a1, a2, a3, a4 if value_to_match[0] == 0: - reveal_type(a1, expected_text="int") - reveal_type(a2, expected_text="str") - reveal_type(a3, expected_text="float") - reveal_type(a4, expected_text="complex") - reveal_type(value_to_match, expected_text="tuple[int, str, float, complex]") - - case *b1, b2 if value_to_match[0] == 0: - reveal_type(b1, expected_text="list[int | str | float]") - reveal_type(b2, expected_text="complex") - reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") - - case c1, *c2 if value_to_match[0] == 0: - reveal_type(c1, expected_text="int") - reveal_type(c2, expected_text="list[str | float | complex]") - reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") - - case d1, *d2, d3 if value_to_match[0] == 0: - reveal_type(d1, expected_text="int") - reveal_type(d2, expected_text="list[str | float]") - reveal_type(d3, expected_text="complex") - reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") - - case 3, *e1: - reveal_type(e1, expected_text="list[str | float | complex]") - reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") - - case "hi", *f1: - reveal_type(f1, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - case *g1, 3j: - reveal_type(g1, expected_text="list[int | str | float]") - reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") - - case *h1, "hi": - reveal_type(h1, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - -def test_union(value_to_match: Union[Tuple[complex, complex], Tuple[int, str, float, complex], List[str], Tuple[float, ...], Any]): - match value_to_match: - case a1, a2, a3, a4 if value_to_match[0] == 0: - reveal_type(a1, expected_text="int | str | float | Any") - reveal_type(a2, expected_text="str | float | Any") - reveal_type(a3, expected_text="float | str | Any") - reveal_type(a4, expected_text="complex | str | float | Any") - reveal_type(value_to_match, expected_text="tuple[int, str, float, complex] | List[str] | tuple[float, float, float, float] | Any") - - case *b1, b2 if value_to_match[0] == 0: - reveal_type(b1, expected_text="list[complex] | list[int | str | float] | list[str] | list[float] | list[Any]") - reveal_type(b2, expected_text="complex | str | float | Any") - reveal_type(value_to_match, expected_text="Tuple[complex, complex] | Tuple[int, str, float, complex] | List[str] | Tuple[float, ...] | Any") - - case c1, *c2 if value_to_match[0] == 0: - reveal_type(c1, expected_text="complex | int | str | float | Any") - reveal_type(c2, expected_text="list[complex] | list[str | float | complex] | list[str] | list[float] | list[Any]") - reveal_type(value_to_match, expected_text="Tuple[complex, complex] | Tuple[int, str, float, complex] | List[str] | Tuple[float, ...] | Any") - - case d1, *d2, d3 if value_to_match[0] == 0: - reveal_type(d1, expected_text="complex | int | str | float | Any") - reveal_type(d2, expected_text="list[str | float] | list[str] | list[float] | list[Any]") - reveal_type(d3, expected_text="complex | str | float | Any") - reveal_type(value_to_match, expected_text="Tuple[complex, complex] | Tuple[int, str, float, complex] | List[str] | Tuple[float, ...] | Any") - - case 3, e1: - reveal_type(e1, expected_text="complex | float | Any") - reveal_type(value_to_match, expected_text="tuple[Literal[3], complex] | tuple[Literal[3], float] | Any") - - case "hi", *f1: - reveal_type(f1, expected_text="list[str] | list[Any]") - reveal_type(value_to_match, expected_text="List[str] | Any") - - case *g1, 3j: - reveal_type(g1, expected_text="list[complex] | list[int | str | float] | list[Any]") - reveal_type(value_to_match, expected_text="tuple[complex, complex] | Tuple[int, str, float, complex] | Any") - - case *h1, "hi": - reveal_type(h1, expected_text="list[str] | list[Any]") - reveal_type(value_to_match, expected_text="List[str] | Any") - - -class SupportsLessThan(Protocol): - def __lt__(self, __other: Any) -> bool: ... - def __le__(self, __other: Any) -> bool: ... - -SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) - - -def sort(seq: List[SupportsLessThanT]) -> List[SupportsLessThanT]: - match seq: - case [] | [_]: - reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") - return seq - - case [x, y] if x <= y: - reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") - return seq - - case [x, y]: - reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") - return [y, x] - - case [x, y, z] if x <= y <= z: - reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") - return seq - - case [x, y, z] if x > y > z: - reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") - return [z, y, x] - - case [p, *rest]: - a = sort([x for x in rest if x <= p]) - b = sort([x for x in rest if p < x]) - reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") - return a + [p] + b - return seq - - -def test_exceptions(seq: Union[str, bytes, bytearray]): - match seq: - case [x, y]: - reveal_type(x, expected_text="Never") - reveal_type(y, expected_text="Never") - return seq - -def test_object(seq: object): - match seq: - case (a1, a2) as a3: - reveal_type(a1, expected_text="object") - reveal_type(a2, expected_text="object") - reveal_type(a3, expected_text="Sequence[object]") - reveal_type(seq, expected_text="Sequence[object]") - - case (*b1, b2) as b3: - reveal_type(b1, expected_text="list[object]") - reveal_type(b2, expected_text="object") - reveal_type(b3, expected_text="Sequence[object]") - reveal_type(seq, expected_text="Sequence[object]") - - case (c1, *c2) as c3: - reveal_type(c1, expected_text="object") - reveal_type(c2, expected_text="list[object]") - reveal_type(c3, expected_text="Sequence[object]") - reveal_type(seq, expected_text="Sequence[object]") - - case (d1, *d2, d3) as d4: - reveal_type(d1, expected_text="object") - reveal_type(d2, expected_text="list[object]") - reveal_type(d3, expected_text="object") - reveal_type(d4, expected_text="Sequence[object]") - reveal_type(seq, expected_text="Sequence[object]") - - case (3, *e1) as e2: - reveal_type(e1, expected_text="list[object]") - reveal_type(e2, expected_text="Sequence[object | int]") - reveal_type(seq, expected_text="Sequence[object | int]") - - case ("hi", *f1) as f2: - reveal_type(f1, expected_text="list[object]") - reveal_type(f2, expected_text="Sequence[object | str]") - reveal_type(seq, expected_text="Sequence[object | str]") - - case (*g1, "hi") as g2: - reveal_type(g1, expected_text="list[object]") - reveal_type(g2, expected_text="Sequence[object | str]") - reveal_type(seq, expected_text="Sequence[object | str]") - - case [1, "hi", True] as h1: - reveal_type(h1, expected_text="Sequence[int | str | bool]") - reveal_type(seq, expected_text="Sequence[int | str | bool]") - - case [1, i1] as i2: - reveal_type(i1, expected_text="object") - reveal_type(i2, expected_text="Sequence[object | int]") - reveal_type(seq, expected_text="Sequence[object | int]") - -_T = TypeVar('_T') - -class A(Generic[_T]): - a: _T - -class B: ... -class C: ... +def func1(subj: int | dict[str, str] | tuple[int] | str, cond: bool): + match subj: + case (3 | "hi"): + reveal_type(subj, expected_text="Literal[3, 'hi']") + return -AAlias = A + case int(y) if cond: + reveal_type(subj, expected_text="int") + return -AInt = A[int] + case int(y): + reveal_type(subj, expected_text="int") + return -BOrC = B | C + case int(): + reveal_type(subj, expected_text="Never") + return -def test_illegal_type_alias(m: object): - match m: - case AAlias(a=i): - pass + case str(z): + reveal_type(subj, expected_text="str") + return - # This should generate an error because it raises an - # exception at runtime. - case AInt(a=i): - pass + reveal_type(subj, expected_text="dict[str, str] | tuple[int]") + return subj - # This should generate an error because it raises an - # exception at runtime. - case BOrC(a=i): - pass -def test_negative_narrowing1(subj: tuple[Literal[0]] | tuple[Literal[1]]): +# This should generate an error because there is the potential +# for fall-through if the subject expression is a str. +def func2(subj: int | str) -> str: match subj: - case (1,*a) | (*a): - reveal_type(subj, expected_text="tuple[Literal[1]] | tuple[Literal[0]]") - reveal_type(a, expected_text="list[int]") + case int(): + return "int" - case b: - reveal_type(subj, expected_text="Never") - reveal_type(b, expected_text="Never") + reveal_type(subj, expected_text="str") -def test_negative_narrowing2(subj: tuple[int, ...]): +# This should generate an error because there is the potential +# for fall-through if the guard expressions are false. +def func3(subj: int | str) -> str: match subj: - case (1,*a): - reveal_type(subj, expected_text="tuple[int, ...]") - reveal_type(a, expected_text="list[int]") - - case (b,): - reveal_type(subj, expected_text="tuple[int]") - reveal_type(b, expected_text="int") + case str() if len(subj) > 0: + return "str" - case (*c,): - reveal_type(subj, expected_text="tuple[int, ...]") - reveal_type(c, expected_text="list[int]") + case int() if subj < 0: + return "int" - case d: - reveal_type(subj, expected_text="Never") - reveal_type(d, expected_text="Never") + reveal_type(subj, expected_text="int | str") -def test_negative_narrowing3(subj: tuple[Any, Any]): +def func4(subj: int | str) -> str: match subj: - case (a, b): - reveal_type(a, expected_text="Any") - reveal_type(b, expected_text="Any") + case int(): + return "int" - case x: - reveal_type(x, expected_text="Never") + case str(): + return "str" - -def test_negative_narrowing4(a: str | None, b: str | None): - match (a, b): - case (None, _) as x: - reveal_type(x, expected_text="tuple[None, str | None]") - case (_, None) as x: - reveal_type(x, expected_text="tuple[str, None]") - case (a, b) as x: - reveal_type(x, expected_text="tuple[str, str]") - - -def test_negative_narrowing5(a: str | None, b: str | None): - match (a, b): - case (None, _) | (_, None) as x: - reveal_type(x, expected_text="tuple[None, str | None] | tuple[str, None]") - case (a, b) as x: - reveal_type(x, expected_text="tuple[str, str]") - - -def test_negative_narrowing6(a: str | None, b: str | None): - match (a, b): - case (None, None) as x: - reveal_type(x, expected_text="tuple[None, None]") - case (None, _) as x if 2 > 1: - reveal_type(x, expected_text="tuple[None, str | None]") - case (a, b) as x: - reveal_type(x, expected_text="tuple[str | None, str | None]") + case _: + # This should be ignored because the pattern has already + # been exhaustively matched. + pass diff --git a/packages/pyright-internal/src/tests/samples/match3.py b/packages/pyright-internal/src/tests/samples/match3.py index 3b3102becd74..954a0d10b5ab 100644 --- a/packages/pyright-internal/src/tests/samples/match3.py +++ b/packages/pyright-internal/src/tests/samples/match3.py @@ -1,392 +1,64 @@ -# This sample tests type checking for match statements (as -# described in PEP 634) that contain class patterns. +# This sample tests narrowing of subject subexpressions in match statements. -from typing import Any, Generic, Literal, NamedTuple, Optional, TypeVar, Union -from dataclasses import dataclass, field +from typing import Literal, TypedDict -foo = 3 -T = TypeVar("T") +class TD1(TypedDict): + name: Literal["a"] + extra_value: int -class ClassA: - __match_args__ = ("attr_a", "attr_b") - attr_a: int - attr_b: str +class TD2(TypedDict): + name: Literal["b"] + other_extra_value: int -class ClassB(Generic[T]): - __match_args__ = ("attr_a", "attr_b") - attr_a: T - attr_b: str +def func1(item: TD1 | TD2): + match item["name"]: + case "c": + reveal_type(item, expected_text="Never") + case "a": + reveal_type(item, expected_text="TD1") + case "b": + reveal_type(item, expected_text="TD2") -class ClassC: - ... +T1 = tuple[Literal[0], int] +T2 = tuple[Literal[1], str] -class ClassD(ClassC): - ... +def func2(item: T1 | T2): + match item[0]: + case 0: + reveal_type(item, expected_text="tuple[Literal[0], int]") + case 1: + reveal_type(item, expected_text="tuple[Literal[1], str]") -def test_unknown(value_to_match): - match value_to_match: - case ClassA(attr_a=a2) as a1: - reveal_type(a1, expected_text="ClassA") - reveal_type(a2, expected_text="int") - reveal_type(value_to_match, expected_text="ClassA") +def func3(a: object, b: int) -> None: + match a, b: + case (complex(), 3): + reveal_type(a, expected_text="complex") + reveal_type(b, expected_text="Literal[3]") - # This should generate an error because foo isn't instantiable. - case foo() as a3: - pass +Token = ( + str + | tuple[Literal["define"], str, str] + | tuple[Literal["include"], str] + | tuple[Literal["use"], str, int, int] +) -def test_any(value_to_match: Any): - match value_to_match: - case list() as a1: - reveal_type(a1, expected_text="list[Unknown]") - reveal_type(value_to_match, expected_text="list[Unknown]") - - -def test_custom_type(value_to_match: ClassA | ClassB[int] | ClassB[str] | ClassC): - match value_to_match: - case int() as a1: - reveal_type(a1, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - case ClassA(attr_a=a4, attr_b=a5) as a3: - reveal_type(a3, expected_text="ClassA") - reveal_type(a4, expected_text="int") - reveal_type(a5, expected_text="str") - reveal_type(value_to_match, expected_text="ClassA") - reveal_type(value_to_match, expected_text="ClassA") - - case ClassB(a6, a7): - reveal_type(a6, expected_text="int | str") - reveal_type(a7, expected_text="str") - reveal_type(value_to_match, expected_text="ClassB[int] | ClassB[str]") - - case ClassD() as a2: - reveal_type(a2, expected_text="ClassD") - reveal_type(value_to_match, expected_text="ClassD") - - case ClassC() as a8: - reveal_type(a8, expected_text="ClassC") - reveal_type(value_to_match, expected_text="ClassC") - - -def test_literal(value_to_match: Literal[3]): - match value_to_match: - case int() as a1: - reveal_type(a1, expected_text="Literal[3]") - reveal_type(value_to_match, expected_text="Literal[3]") - - case float() as a2: - reveal_type(a2, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - case str() as a3: - reveal_type(a3, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - -TFloat = TypeVar("TFloat", bound=float) - - -def test_bound_typevar(value_to_match: TFloat) -> TFloat: - match value_to_match: - case int() as a1: - reveal_type(a1, expected_text="int*") - reveal_type(value_to_match, expected_text="int*") - - case float() as a2: - reveal_type(a2, expected_text="float*") - reveal_type(value_to_match, expected_text="float*") - - case str() as a3: - reveal_type(a3, expected_text="Never") - reveal_type(value_to_match, expected_text="Never") - - return value_to_match - - -TInt = TypeVar("TInt", bound=int) - - -def test_union( - value_to_match: Union[TInt, Literal[3], float, str] -) -> Union[TInt, Literal[3], float, str]: - match value_to_match: - case int() as a1: - reveal_type(a1, expected_text="int* | int") - reveal_type(value_to_match, expected_text="int* | int") - - case float() as a2: - reveal_type(a2, expected_text="float") - reveal_type(value_to_match, expected_text="float") - - case str() as a3: - reveal_type(a3, expected_text="str") - reveal_type(value_to_match, expected_text="str") - - return value_to_match - - -T = TypeVar("T") - - -class Point(Generic[T]): - __match_args__ = ("x", "y") - x: T - y: T - - -def func1(points: list[Point[float] | Point[complex]]): - match points: - case [] as a1: - reveal_type(a1, expected_text="list[Point[float] | Point[complex]]") - reveal_type(points, expected_text="list[Point[float] | Point[complex]]") - - case [Point(0, 0) as b1]: - reveal_type(b1, expected_text="Point[float] | Point[complex]") - reveal_type(points, expected_text="list[Point[float] | Point[complex]]") - - case [Point(c1, c2)]: - reveal_type(c1, expected_text="float | complex") - reveal_type(c2, expected_text="float | complex") - reveal_type(points, expected_text="list[Point[float] | Point[complex]]") - - case [Point(0, d1), Point(0, d2)]: - reveal_type(d1, expected_text="float | complex") - reveal_type(d2, expected_text="float | complex") - reveal_type(points, expected_text="list[Point[float] | Point[complex]]") - - case _ as e1: - reveal_type(e1, expected_text="list[Point[float] | Point[complex]]") - reveal_type(points, expected_text="list[Point[float] | Point[complex]]") - - -def func2(subj: object): - match subj: - case list() as a1: - reveal_type(a1, expected_text="list[Unknown]") - reveal_type(subj, expected_text="list[Unknown]") - - -def func3(subj: Union[int, str, dict[str, str]]): - match subj: - case int(x): - reveal_type(x, expected_text="int") - reveal_type(subj, expected_text="int") - - case str(x): - reveal_type(x, expected_text="str") - reveal_type(subj, expected_text="str") - - case dict(x): - reveal_type(x, expected_text="dict[str, str]") - reveal_type(subj, expected_text="dict[str, str]") - - -def func4(subj: object): - match subj: - case int(x): - reveal_type(x, expected_text="int") - reveal_type(subj, expected_text="int") +def func4(token: Token): + match token: case str(x): - reveal_type(x, expected_text="str") - reveal_type(subj, expected_text="str") - - -# Test the auto-generation of __match_args__ for dataclass. -@dataclass -class Dataclass1: - val1: int - val2: str = field(init=False) - val3: complex - - -@dataclass -class Dataclass2: - val1: int - val2: str - val3: float - - -def func5(subj: object): - match subj: - case Dataclass1(a, b): - reveal_type(a, expected_text="int") - reveal_type(b, expected_text="complex") - reveal_type(subj, expected_text="Dataclass1") - - case Dataclass2(a, b, c): - reveal_type(a, expected_text="int") - reveal_type(b, expected_text="str") - reveal_type(c, expected_text="float") - reveal_type(subj, expected_text="Dataclass2") - - -# Test the auto-generation of __match_args__ for named tuples. -NT1 = NamedTuple("NT1", [("val1", int), ("val2", complex)]) -NT2 = NamedTuple("NT2", [("val1", int), ("val2", str), ("val3", float)]) - - -def func6(subj: object): - match subj: - case NT1(a, b): - reveal_type(a, expected_text="int") - reveal_type(b, expected_text="complex") - reveal_type(subj, expected_text="NT1") - - case NT2(a, b, c): - reveal_type(a, expected_text="int") - reveal_type(b, expected_text="str") - reveal_type(c, expected_text="float") - reveal_type(subj, expected_text="NT2") - - -def func7(subj: object): - match subj: - case complex(real=a, imag=b): - reveal_type(a, expected_text="float") - reveal_type(b, expected_text="float") - - -T2 = TypeVar("T2") - - -class Parent(Generic[T]): - ... - - -class Child1(Parent[T]): - ... - - -class Child2(Parent[T], Generic[T, T2]): - ... - - -def func8(subj: Parent[int]): - match subj: - case Child1() as a1: - reveal_type(a1, expected_text="Child1[int]") - reveal_type(subj, expected_text="Child1[int]") - - case Child2() as b1: - reveal_type(b1, expected_text="Child2[int, Unknown]") - reveal_type(subj, expected_text="Child2[int, Unknown]") - - -T3 = TypeVar("T3") - - -def func9(v: T3) -> Optional[T3]: - match v: - case str(): - reveal_type(v, expected_text="str*") - return v - - case _: - return None - - -T4 = TypeVar("T4", int, str) - - -def func10(v: T4) -> Optional[T4]: - match v: - case str(): - reveal_type(v, expected_text="str*") - return v - - case int(): - reveal_type(v, expected_text="int*") - return v - - case list(): - reveal_type(v, expected_text="Never") - return v - + reveal_type(token, expected_text="str") + case "define", _, _: + reveal_type(token, expected_text="tuple[Literal['define'], str, str]") + case "include", _: + reveal_type(token, expected_text="tuple[Literal['include'], str]") + case "use", _, _, _: + reveal_type(token, expected_text="tuple[Literal['use'], str, int, int]") case _: - return None - - -def func11(subj: Any): - match subj: - case Child1() as a1: - reveal_type(a1, expected_text="Child1[Unknown]") - reveal_type(subj, expected_text="Child1[Unknown]") - - case Child2() as b1: - reveal_type(b1, expected_text="Child2[Unknown, Unknown]") - reveal_type(subj, expected_text="Child2[Unknown, Unknown]") - - -def func12(subj: int, flt_cls: type[float], union_val: float | int): - match subj: - # This should generate an error because int doesn't accept two arguments. - case int(1, 2): - pass - - match subj: - # This should generate an error because float doesn't accept keyword arguments. - case float(x=1): - pass - - match subj: - case flt_cls(): - pass - - # This should generate an error because it is a union. - case union_val(): - pass - - -def func13(subj: tuple[Literal[0]]): - match subj: - case tuple((1,)) as a: - reveal_type(subj, expected_text="Never") - reveal_type(a, expected_text="Never") - - case tuple((0, 0)) as b: - reveal_type(subj, expected_text="Never") - reveal_type(b, expected_text="Never") - - case tuple((0,)) as c: - reveal_type(subj, expected_text="tuple[Literal[0]]") - reveal_type(c, expected_text="tuple[Literal[0]]") - - case d: - reveal_type(subj, expected_text="Never") - reveal_type(d, expected_text="Never") - - -class ClassE(Generic[T]): - __match_args__ = ("x",) - x: list[T] - - -class ClassF(ClassE[T]): - pass - - -def func14(subj: ClassE[T]) -> T | None: - match subj: - case ClassF(a): - reveal_type(subj, expected_text="ClassF[T@func14]") - reveal_type(a, expected_text="list[T@func14]") - return a[0] - - -class IntPair(tuple[int, int]): - pass - - -def func15(x: IntPair | None) -> None: - match x: - case IntPair((y, z)): - reveal_type(y, expected_text="int") - reveal_type(z, expected_text="int") + reveal_type(token, expected_text="Never") diff --git a/packages/pyright-internal/src/tests/samples/match7.py b/packages/pyright-internal/src/tests/samples/match7.py deleted file mode 100644 index 7326f36b47b6..000000000000 --- a/packages/pyright-internal/src/tests/samples/match7.py +++ /dev/null @@ -1,65 +0,0 @@ -# This sample tests type narrowing of subject expressions for -# match statements. - - -def func1(subj: int | dict[str, str] | tuple[int] | str, cond: bool): - match subj: - case (3 | "hi"): - reveal_type(subj, expected_text="Literal[3, 'hi']") - return - - case int(y) if cond: - reveal_type(subj, expected_text="int") - return - - case int(y): - reveal_type(subj, expected_text="int") - return - - case int(): - reveal_type(subj, expected_text="Never") - return - - case str(z): - reveal_type(subj, expected_text="str") - return - - reveal_type(subj, expected_text="dict[str, str] | tuple[int]") - return subj - - -# This should generate an error because there is the potential -# for fall-through if the subject expression is a str. -def func2(subj: int | str) -> str: - match subj: - case int(): - return "int" - - reveal_type(subj, expected_text='str') - - -# This should generate an error because there is the potential -# for fall-through if the guard expressions are false. -def func3(subj: int | str) -> str: - match subj: - case str() if len(subj) > 0: - return "str" - - case int() if subj < 0: - return "int" - - reveal_type(subj, expected_text='int | str') - - -def func4(subj: int | str) -> str: - match subj: - case int(): - return "int" - - case str(): - return "str" - - case _: - # This should be ignored because the pattern has already - # been exhaustively matched. - pass diff --git a/packages/pyright-internal/src/tests/samples/matchClass1.py b/packages/pyright-internal/src/tests/samples/matchClass1.py new file mode 100644 index 000000000000..a32770bb9d3e --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/matchClass1.py @@ -0,0 +1,392 @@ +# This sample tests type checking for match statements (as +# described in PEP 634) that contain class patterns. + +from typing import Any, Generic, Literal, NamedTuple, TypeVar +from dataclasses import dataclass, field + +foo = 3 + +T = TypeVar("T") + + +class ClassA: + __match_args__ = ("attr_a", "attr_b") + attr_a: int + attr_b: str + + +class ClassB(Generic[T]): + __match_args__ = ("attr_a", "attr_b") + attr_a: T + attr_b: str + + +class ClassC: + ... + + +class ClassD(ClassC): + ... + + +def test_unknown(value_to_match): + match value_to_match: + case ClassA(attr_a=a2) as a1: + reveal_type(a1, expected_text="ClassA") + reveal_type(a2, expected_text="int") + reveal_type(value_to_match, expected_text="ClassA") + + # This should generate an error because foo isn't instantiable. + case foo() as a3: + pass + + +def test_any(value_to_match: Any): + match value_to_match: + case list() as a1: + reveal_type(a1, expected_text="list[Unknown]") + reveal_type(value_to_match, expected_text="list[Unknown]") + + +def test_custom_type(value_to_match: ClassA | ClassB[int] | ClassB[str] | ClassC): + match value_to_match: + case int() as a1: + reveal_type(a1, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + case ClassA(attr_a=a4, attr_b=a5) as a3: + reveal_type(a3, expected_text="ClassA") + reveal_type(a4, expected_text="int") + reveal_type(a5, expected_text="str") + reveal_type(value_to_match, expected_text="ClassA") + reveal_type(value_to_match, expected_text="ClassA") + + case ClassB(a6, a7): + reveal_type(a6, expected_text="int | str") + reveal_type(a7, expected_text="str") + reveal_type(value_to_match, expected_text="ClassB[int] | ClassB[str]") + + case ClassD() as a2: + reveal_type(a2, expected_text="ClassD") + reveal_type(value_to_match, expected_text="ClassD") + + case ClassC() as a8: + reveal_type(a8, expected_text="ClassC") + reveal_type(value_to_match, expected_text="ClassC") + + +def test_literal(value_to_match: Literal[3]): + match value_to_match: + case int() as a1: + reveal_type(a1, expected_text="Literal[3]") + reveal_type(value_to_match, expected_text="Literal[3]") + + case float() as a2: + reveal_type(a2, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + case str() as a3: + reveal_type(a3, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + +TFloat = TypeVar("TFloat", bound=float) + + +def test_bound_typevar(value_to_match: TFloat) -> TFloat: + match value_to_match: + case int() as a1: + reveal_type(a1, expected_text="int*") + reveal_type(value_to_match, expected_text="int*") + + case float() as a2: + reveal_type(a2, expected_text="float*") + reveal_type(value_to_match, expected_text="float*") + + case str() as a3: + reveal_type(a3, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + return value_to_match + + +TInt = TypeVar("TInt", bound=int) + + +def test_union( + value_to_match: TInt | Literal[3] | float | str, +) -> TInt | Literal[3] | float | str: + match value_to_match: + case int() as a1: + reveal_type(a1, expected_text="int* | int") + reveal_type(value_to_match, expected_text="int* | int") + + case float() as a2: + reveal_type(a2, expected_text="float") + reveal_type(value_to_match, expected_text="float") + + case str() as a3: + reveal_type(a3, expected_text="str") + reveal_type(value_to_match, expected_text="str") + + return value_to_match + + +T = TypeVar("T") + + +class Point(Generic[T]): + __match_args__ = ("x", "y") + x: T + y: T + + +def func1(points: list[Point[float] | Point[complex]]): + match points: + case [] as a1: + reveal_type(a1, expected_text="list[Point[float] | Point[complex]]") + reveal_type(points, expected_text="list[Point[float] | Point[complex]]") + + case [Point(0, 0) as b1]: + reveal_type(b1, expected_text="Point[float] | Point[complex]") + reveal_type(points, expected_text="list[Point[float] | Point[complex]]") + + case [Point(c1, c2)]: + reveal_type(c1, expected_text="float | complex") + reveal_type(c2, expected_text="float | complex") + reveal_type(points, expected_text="list[Point[float] | Point[complex]]") + + case [Point(0, d1), Point(0, d2)]: + reveal_type(d1, expected_text="float | complex") + reveal_type(d2, expected_text="float | complex") + reveal_type(points, expected_text="list[Point[float] | Point[complex]]") + + case _ as e1: + reveal_type(e1, expected_text="list[Point[float] | Point[complex]]") + reveal_type(points, expected_text="list[Point[float] | Point[complex]]") + + +def func2(subj: object): + match subj: + case list() as a1: + reveal_type(a1, expected_text="list[Unknown]") + reveal_type(subj, expected_text="list[Unknown]") + + +def func3(subj: int | str | dict[str, str]): + match subj: + case int(x): + reveal_type(x, expected_text="int") + reveal_type(subj, expected_text="int") + + case str(x): + reveal_type(x, expected_text="str") + reveal_type(subj, expected_text="str") + + case dict(x): + reveal_type(x, expected_text="dict[str, str]") + reveal_type(subj, expected_text="dict[str, str]") + + +def func4(subj: object): + match subj: + case int(x): + reveal_type(x, expected_text="int") + reveal_type(subj, expected_text="int") + + case str(x): + reveal_type(x, expected_text="str") + reveal_type(subj, expected_text="str") + + +# Test the auto-generation of __match_args__ for dataclass. +@dataclass +class Dataclass1: + val1: int + val2: str = field(init=False) + val3: complex + + +@dataclass +class Dataclass2: + val1: int + val2: str + val3: float + + +def func5(subj: object): + match subj: + case Dataclass1(a, b): + reveal_type(a, expected_text="int") + reveal_type(b, expected_text="complex") + reveal_type(subj, expected_text="Dataclass1") + + case Dataclass2(a, b, c): + reveal_type(a, expected_text="int") + reveal_type(b, expected_text="str") + reveal_type(c, expected_text="float") + reveal_type(subj, expected_text="Dataclass2") + + +# Test the auto-generation of __match_args__ for named tuples. +NT1 = NamedTuple("NT1", [("val1", int), ("val2", complex)]) +NT2 = NamedTuple("NT2", [("val1", int), ("val2", str), ("val3", float)]) + + +def func6(subj: object): + match subj: + case NT1(a, b): + reveal_type(a, expected_text="int") + reveal_type(b, expected_text="complex") + reveal_type(subj, expected_text="NT1") + + case NT2(a, b, c): + reveal_type(a, expected_text="int") + reveal_type(b, expected_text="str") + reveal_type(c, expected_text="float") + reveal_type(subj, expected_text="NT2") + + +def func7(subj: object): + match subj: + case complex(real=a, imag=b): + reveal_type(a, expected_text="float") + reveal_type(b, expected_text="float") + + +T2 = TypeVar("T2") + + +class Parent(Generic[T]): + ... + + +class Child1(Parent[T]): + ... + + +class Child2(Parent[T], Generic[T, T2]): + ... + + +def func8(subj: Parent[int]): + match subj: + case Child1() as a1: + reveal_type(a1, expected_text="Child1[int]") + reveal_type(subj, expected_text="Child1[int]") + + case Child2() as b1: + reveal_type(b1, expected_text="Child2[int, Unknown]") + reveal_type(subj, expected_text="Child2[int, Unknown]") + + +T3 = TypeVar("T3") + + +def func9(v: T3) -> T3 | None: + match v: + case str(): + reveal_type(v, expected_text="str*") + return v + + case _: + return None + + +T4 = TypeVar("T4", int, str) + + +def func10(v: T4) -> T4 | None: + match v: + case str(): + reveal_type(v, expected_text="str*") + return v + + case int(): + reveal_type(v, expected_text="int*") + return v + + case list(): + reveal_type(v, expected_text="Never") + return v + + case _: + return None + + +def func11(subj: Any): + match subj: + case Child1() as a1: + reveal_type(a1, expected_text="Child1[Unknown]") + reveal_type(subj, expected_text="Child1[Unknown]") + + case Child2() as b1: + reveal_type(b1, expected_text="Child2[Unknown, Unknown]") + reveal_type(subj, expected_text="Child2[Unknown, Unknown]") + + +def func12(subj: int, flt_cls: type[float], union_val: float | int): + match subj: + # This should generate an error because int doesn't accept two arguments. + case int(1, 2): + pass + + match subj: + # This should generate an error because float doesn't accept keyword arguments. + case float(x=1): + pass + + match subj: + case flt_cls(): + pass + + # This should generate an error because it is a union. + case union_val(): + pass + + +def func13(subj: tuple[Literal[0]]): + match subj: + case tuple((1,)) as a: + reveal_type(subj, expected_text="Never") + reveal_type(a, expected_text="Never") + + case tuple((0, 0)) as b: + reveal_type(subj, expected_text="Never") + reveal_type(b, expected_text="Never") + + case tuple((0,)) as c: + reveal_type(subj, expected_text="tuple[Literal[0]]") + reveal_type(c, expected_text="tuple[Literal[0]]") + + case d: + reveal_type(subj, expected_text="Never") + reveal_type(d, expected_text="Never") + + +class ClassE(Generic[T]): + __match_args__ = ("x",) + x: list[T] + + +class ClassF(ClassE[T]): + pass + + +def func14(subj: ClassE[T]) -> T | None: + match subj: + case ClassF(a): + reveal_type(subj, expected_text="ClassF[T@func14]") + reveal_type(a, expected_text="list[T@func14]") + return a[0] + + +class IntPair(tuple[int, int]): + pass + + +def func15(x: IntPair | None) -> None: + match x: + case IntPair((y, z)): + reveal_type(y, expected_text="int") + reveal_type(z, expected_text="int") diff --git a/packages/pyright-internal/src/tests/samples/match8.py b/packages/pyright-internal/src/tests/samples/matchClass2.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/match8.py rename to packages/pyright-internal/src/tests/samples/matchClass2.py diff --git a/packages/pyright-internal/src/tests/samples/match9.py b/packages/pyright-internal/src/tests/samples/matchClass3.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/match9.py rename to packages/pyright-internal/src/tests/samples/matchClass3.py diff --git a/packages/pyright-internal/src/tests/samples/match10.py b/packages/pyright-internal/src/tests/samples/matchExhaustion1.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/match10.py rename to packages/pyright-internal/src/tests/samples/matchExhaustion1.py diff --git a/packages/pyright-internal/src/tests/samples/match6.py b/packages/pyright-internal/src/tests/samples/matchLiteral1.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/match6.py rename to packages/pyright-internal/src/tests/samples/matchLiteral1.py diff --git a/packages/pyright-internal/src/tests/samples/match5.py b/packages/pyright-internal/src/tests/samples/matchMapping1.py similarity index 89% rename from packages/pyright-internal/src/tests/samples/match5.py rename to packages/pyright-internal/src/tests/samples/matchMapping1.py index d889f31b04e4..5c8b0e91f5ef 100644 --- a/packages/pyright-internal/src/tests/samples/match5.py +++ b/packages/pyright-internal/src/tests/samples/matchMapping1.py @@ -1,7 +1,7 @@ # This sample tests type checking for match statements (as # described in PEP 634) that contain mapping patterns. -from typing import Dict, Literal, TypedDict +from typing import Literal, TypedDict from typing_extensions import NotRequired @@ -13,17 +13,17 @@ def test_unknown(value_to_match): reveal_type(value_to_match, expected_text="Unknown") -def test_dict(value_to_match: Dict[str | int, str | int]): +def test_dict(value_to_match: dict[str | int, str | int]): match value_to_match: case {1: a1}: reveal_type(a1, expected_text="str | int") - reveal_type(value_to_match, expected_text="Dict[str | int, str | int]") + reveal_type(value_to_match, expected_text="dict[str | int, str | int]") case {"hi": b1, "hi2": b2, **b3}: reveal_type(b1, expected_text="str | int") reveal_type(b2, expected_text="str | int") reveal_type(b3, expected_text="dict[str | int, str | int]") - reveal_type(value_to_match, expected_text="Dict[str | int, str | int]") + reveal_type(value_to_match, expected_text="dict[str | int, str | int]") case {3j: c1}: reveal_type(c1, expected_text="Never") @@ -62,16 +62,16 @@ def test_typed_dict(value_to_match: Movie): reveal_type(value_to_match, expected_text="Movie") -def test_union(value_to_match: Dict[str | int, str | int] | Movie | str): +def test_union(value_to_match: dict[str | int, str | int] | Movie | str): match value_to_match: case {3: a1}: reveal_type(a1, expected_text="str | int") - reveal_type(value_to_match, expected_text="Dict[str | int, str | int]") + reveal_type(value_to_match, expected_text="dict[str | int, str | int]") case {"gross_earnings": b1}: reveal_type(b1, expected_text="str | int | float") reveal_type( - value_to_match, expected_text="Dict[str | int, str | int] | Movie" + value_to_match, expected_text="dict[str | int, str | int] | Movie" ) diff --git a/packages/pyright-internal/src/tests/samples/matchSequence1.py b/packages/pyright-internal/src/tests/samples/matchSequence1.py new file mode 100644 index 000000000000..209c80b3baa6 --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/matchSequence1.py @@ -0,0 +1,378 @@ +# This sample tests type checking for match statements (as +# described in PEP 634) that contain sequence patterns. + +from typing import Any, Generic, List, Literal, Protocol, Tuple, TypeVar, Union + +def test_unknown(value_to_match): + match value_to_match: + case a1, a2: + reveal_type(a1, expected_text="Unknown") + reveal_type(a2, expected_text="Unknown") + + case *b1, b2: + reveal_type(b1, expected_text="list[Unknown]") + reveal_type(b2, expected_text="Unknown") + + case c1, *c2: + reveal_type(c1, expected_text="Unknown") + reveal_type(c2, expected_text="list[Unknown]") + + case d1, *d2, d3: + reveal_type(d1, expected_text="Unknown") + reveal_type(d2, expected_text="list[Unknown]") + reveal_type(d3, expected_text="Unknown") + + case 3, *e1: + reveal_type(e1, expected_text="list[Unknown]") + + case "hi", *f1: + reveal_type(f1, expected_text="list[Unknown]") + + case *g1, "hi": + reveal_type(g1, expected_text="list[Unknown]") + + +def test_list(value_to_match: List[str]): + match value_to_match: + case a1, a2: + reveal_type(a1, expected_text="str") + reveal_type(a2, expected_text="str") + reveal_type(value_to_match, expected_text="List[str]") + + case *b1, b2: + reveal_type(b1, expected_text="list[str]") + reveal_type(b2, expected_text="str") + reveal_type(value_to_match, expected_text="List[str]") + + case c1, *c2: + reveal_type(c1, expected_text="str") + reveal_type(c2, expected_text="list[str]") + reveal_type(value_to_match, expected_text="List[str]") + + case d1, *d2, d3: + reveal_type(d1, expected_text="str") + reveal_type(d2, expected_text="list[str]") + reveal_type(d3, expected_text="str") + reveal_type(value_to_match, expected_text="List[str]") + + case 3, *e1: + reveal_type(e1, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + case "hi", *f1: + reveal_type(f1, expected_text="list[str]") + reveal_type(value_to_match, expected_text="List[str]") + + case *g1, "hi": + reveal_type(g1, expected_text="list[str]") + reveal_type(value_to_match, expected_text="List[str]") + +def test_open_ended_tuple(value_to_match: Tuple[str, ...]): + match value_to_match: + case a1, a2: + reveal_type(a1, expected_text="str") + reveal_type(a2, expected_text="str") + reveal_type(value_to_match, expected_text="tuple[str, str]") + + case *b1, b2: + reveal_type(b1, expected_text="list[str]") + reveal_type(b2, expected_text="str") + reveal_type(value_to_match, expected_text="Tuple[str, ...]") + + case c1, *c2: + reveal_type(c1, expected_text="str") + reveal_type(c2, expected_text="list[str]") + reveal_type(value_to_match, expected_text="Tuple[str, ...]") + + case d1, *d2, d3: + reveal_type(d1, expected_text="str") + reveal_type(d2, expected_text="list[str]") + reveal_type(d3, expected_text="str") + reveal_type(value_to_match, expected_text="Tuple[str, ...]") + + case 3, *e1: + reveal_type(e1, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + case "hi", *f1: + reveal_type(f1, expected_text="list[str]") + reveal_type(value_to_match, expected_text="Tuple[str, ...]") + + case *g1, "hi": + reveal_type(g1, expected_text="list[str]") + reveal_type(value_to_match, expected_text="Tuple[str, ...]") + +def test_definite_tuple(value_to_match: Tuple[int, str, float, complex]): + match value_to_match: + case a1, a2, a3, a4 if value_to_match[0] == 0: + reveal_type(a1, expected_text="int") + reveal_type(a2, expected_text="str") + reveal_type(a3, expected_text="float") + reveal_type(a4, expected_text="complex") + reveal_type(value_to_match, expected_text="tuple[int, str, float, complex]") + + case *b1, b2 if value_to_match[0] == 0: + reveal_type(b1, expected_text="list[int | str | float]") + reveal_type(b2, expected_text="complex") + reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") + + case c1, *c2 if value_to_match[0] == 0: + reveal_type(c1, expected_text="int") + reveal_type(c2, expected_text="list[str | float | complex]") + reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") + + case d1, *d2, d3 if value_to_match[0] == 0: + reveal_type(d1, expected_text="int") + reveal_type(d2, expected_text="list[str | float]") + reveal_type(d3, expected_text="complex") + reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") + + case 3, *e1: + reveal_type(e1, expected_text="list[str | float | complex]") + reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") + + case "hi", *f1: + reveal_type(f1, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + case *g1, 3j: + reveal_type(g1, expected_text="list[int | str | float]") + reveal_type(value_to_match, expected_text="Tuple[int, str, float, complex]") + + case *h1, "hi": + reveal_type(h1, expected_text="Never") + reveal_type(value_to_match, expected_text="Never") + + +def test_union(value_to_match: Union[Tuple[complex, complex], Tuple[int, str, float, complex], List[str], Tuple[float, ...], Any]): + match value_to_match: + case a1, a2, a3, a4 if value_to_match[0] == 0: + reveal_type(a1, expected_text="int | str | float | Any") + reveal_type(a2, expected_text="str | float | Any") + reveal_type(a3, expected_text="float | str | Any") + reveal_type(a4, expected_text="complex | str | float | Any") + reveal_type(value_to_match, expected_text="tuple[int, str, float, complex] | List[str] | tuple[float, float, float, float] | Any") + + case *b1, b2 if value_to_match[0] == 0: + reveal_type(b1, expected_text="list[complex] | list[int | str | float] | list[str] | list[float] | list[Any]") + reveal_type(b2, expected_text="complex | str | float | Any") + reveal_type(value_to_match, expected_text="Tuple[complex, complex] | Tuple[int, str, float, complex] | List[str] | Tuple[float, ...] | Any") + + case c1, *c2 if value_to_match[0] == 0: + reveal_type(c1, expected_text="complex | int | str | float | Any") + reveal_type(c2, expected_text="list[complex] | list[str | float | complex] | list[str] | list[float] | list[Any]") + reveal_type(value_to_match, expected_text="Tuple[complex, complex] | Tuple[int, str, float, complex] | List[str] | Tuple[float, ...] | Any") + + case d1, *d2, d3 if value_to_match[0] == 0: + reveal_type(d1, expected_text="complex | int | str | float | Any") + reveal_type(d2, expected_text="list[str | float] | list[str] | list[float] | list[Any]") + reveal_type(d3, expected_text="complex | str | float | Any") + reveal_type(value_to_match, expected_text="Tuple[complex, complex] | Tuple[int, str, float, complex] | List[str] | Tuple[float, ...] | Any") + + case 3, e1: + reveal_type(e1, expected_text="complex | float | Any") + reveal_type(value_to_match, expected_text="tuple[Literal[3], complex] | tuple[Literal[3], float] | Any") + + case "hi", *f1: + reveal_type(f1, expected_text="list[str] | list[Any]") + reveal_type(value_to_match, expected_text="List[str] | Any") + + case *g1, 3j: + reveal_type(g1, expected_text="list[complex] | list[int | str | float] | list[Any]") + reveal_type(value_to_match, expected_text="tuple[complex, complex] | Tuple[int, str, float, complex] | Any") + + case *h1, "hi": + reveal_type(h1, expected_text="list[str] | list[Any]") + reveal_type(value_to_match, expected_text="List[str] | Any") + + +class SupportsLessThan(Protocol): + def __lt__(self, __other: Any) -> bool: ... + def __le__(self, __other: Any) -> bool: ... + +SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) + + +def sort(seq: List[SupportsLessThanT]) -> List[SupportsLessThanT]: + match seq: + case [] | [_]: + reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") + return seq + + case [x, y] if x <= y: + reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") + return seq + + case [x, y]: + reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") + return [y, x] + + case [x, y, z] if x <= y <= z: + reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") + return seq + + case [x, y, z] if x > y > z: + reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") + return [z, y, x] + + case [p, *rest]: + a = sort([x for x in rest if x <= p]) + b = sort([x for x in rest if p < x]) + reveal_type(seq, expected_text="List[SupportsLessThanT@sort]") + return a + [p] + b + return seq + + +def test_exceptions(seq: Union[str, bytes, bytearray]): + match seq: + case [x, y]: + reveal_type(x, expected_text="Never") + reveal_type(y, expected_text="Never") + return seq + +def test_object(seq: object): + match seq: + case (a1, a2) as a3: + reveal_type(a1, expected_text="object") + reveal_type(a2, expected_text="object") + reveal_type(a3, expected_text="Sequence[object]") + reveal_type(seq, expected_text="Sequence[object]") + + case (*b1, b2) as b3: + reveal_type(b1, expected_text="list[object]") + reveal_type(b2, expected_text="object") + reveal_type(b3, expected_text="Sequence[object]") + reveal_type(seq, expected_text="Sequence[object]") + + case (c1, *c2) as c3: + reveal_type(c1, expected_text="object") + reveal_type(c2, expected_text="list[object]") + reveal_type(c3, expected_text="Sequence[object]") + reveal_type(seq, expected_text="Sequence[object]") + + case (d1, *d2, d3) as d4: + reveal_type(d1, expected_text="object") + reveal_type(d2, expected_text="list[object]") + reveal_type(d3, expected_text="object") + reveal_type(d4, expected_text="Sequence[object]") + reveal_type(seq, expected_text="Sequence[object]") + + case (3, *e1) as e2: + reveal_type(e1, expected_text="list[object]") + reveal_type(e2, expected_text="Sequence[object | int]") + reveal_type(seq, expected_text="Sequence[object | int]") + + case ("hi", *f1) as f2: + reveal_type(f1, expected_text="list[object]") + reveal_type(f2, expected_text="Sequence[object | str]") + reveal_type(seq, expected_text="Sequence[object | str]") + + case (*g1, "hi") as g2: + reveal_type(g1, expected_text="list[object]") + reveal_type(g2, expected_text="Sequence[object | str]") + reveal_type(seq, expected_text="Sequence[object | str]") + + case [1, "hi", True] as h1: + reveal_type(h1, expected_text="Sequence[int | str | bool]") + reveal_type(seq, expected_text="Sequence[int | str | bool]") + + case [1, i1] as i2: + reveal_type(i1, expected_text="object") + reveal_type(i2, expected_text="Sequence[object | int]") + reveal_type(seq, expected_text="Sequence[object | int]") + +_T = TypeVar('_T') + +class A(Generic[_T]): + a: _T + +class B: ... +class C: ... + +AAlias = A + +AInt = A[int] + +BOrC = B | C + +def test_illegal_type_alias(m: object): + match m: + case AAlias(a=i): + pass + + # This should generate an error because it raises an + # exception at runtime. + case AInt(a=i): + pass + + # This should generate an error because it raises an + # exception at runtime. + case BOrC(a=i): + pass + +def test_negative_narrowing1(subj: tuple[Literal[0]] | tuple[Literal[1]]): + match subj: + case (1,*a) | (*a): + reveal_type(subj, expected_text="tuple[Literal[1]] | tuple[Literal[0]]") + reveal_type(a, expected_text="list[int]") + + case b: + reveal_type(subj, expected_text="Never") + reveal_type(b, expected_text="Never") + + +def test_negative_narrowing2(subj: tuple[int, ...]): + match subj: + case (1,*a): + reveal_type(subj, expected_text="tuple[int, ...]") + reveal_type(a, expected_text="list[int]") + + case (b,): + reveal_type(subj, expected_text="tuple[int]") + reveal_type(b, expected_text="int") + + case (*c,): + reveal_type(subj, expected_text="tuple[int, ...]") + reveal_type(c, expected_text="list[int]") + + case d: + reveal_type(subj, expected_text="Never") + reveal_type(d, expected_text="Never") + + +def test_negative_narrowing3(subj: tuple[Any, Any]): + match subj: + case (a, b): + reveal_type(a, expected_text="Any") + reveal_type(b, expected_text="Any") + + case x: + reveal_type(x, expected_text="Never") + + +def test_negative_narrowing4(a: str | None, b: str | None): + match (a, b): + case (None, _) as x: + reveal_type(x, expected_text="tuple[None, str | None]") + case (_, None) as x: + reveal_type(x, expected_text="tuple[str, None]") + case (a, b) as x: + reveal_type(x, expected_text="tuple[str, str]") + + +def test_negative_narrowing5(a: str | None, b: str | None): + match (a, b): + case (None, _) | (_, None) as x: + reveal_type(x, expected_text="tuple[None, str | None] | tuple[str, None]") + case (a, b) as x: + reveal_type(x, expected_text="tuple[str, str]") + + +def test_negative_narrowing6(a: str | None, b: str | None): + match (a, b): + case (None, None) as x: + reveal_type(x, expected_text="tuple[None, None]") + case (None, _) as x if 2 > 1: + reveal_type(x, expected_text="tuple[None, str | None]") + case (a, b) as x: + reveal_type(x, expected_text="tuple[str | None, str | None]") diff --git a/packages/pyright-internal/src/tests/samples/match11.py b/packages/pyright-internal/src/tests/samples/matchUnnecessary1.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/match11.py rename to packages/pyright-internal/src/tests/samples/matchUnnecessary1.py diff --git a/packages/pyright-internal/src/tests/samples/match4.py b/packages/pyright-internal/src/tests/samples/matchValue1.py similarity index 93% rename from packages/pyright-internal/src/tests/samples/match4.py rename to packages/pyright-internal/src/tests/samples/matchValue1.py index 4e7d7fca8017..de6b0372dc6d 100644 --- a/packages/pyright-internal/src/tests/samples/match4.py +++ b/packages/pyright-internal/src/tests/samples/matchValue1.py @@ -3,11 +3,11 @@ from dataclasses import dataclass from enum import Enum, auto -from typing import Annotated, Tuple, TypeVar, Union +from typing import Annotated, TypeVar from http import HTTPStatus -def handle_reply(reply: Tuple[HTTPStatus, str] | Tuple[HTTPStatus]): +def handle_reply(reply: tuple[HTTPStatus, str] | tuple[HTTPStatus]): match reply: case (HTTPStatus.OK as a1, a2): reveal_type(a1, expected_text="Literal[HTTPStatus.OK]") @@ -53,7 +53,7 @@ def test_class_var(value_to_match: str): TInt = TypeVar("TInt", bound=MyEnum) -def test_union(value_to_match: Union[TInt, MyEnum]) -> Union[TInt, MyEnum]: +def test_union(value_to_match: TInt | MyEnum) -> TInt | MyEnum: match value_to_match: case MyEnum.V1 as a1: reveal_type(a1, expected_text="Literal[MyEnum.V1]") @@ -74,7 +74,7 @@ class Color(Enum): green = 3 -def test_enum_narrowing(m: Union[Medal, Color, int]): +def test_enum_narrowing(m: Medal | Color | int): match m: case Medal.gold as a1: reveal_type(a1, expected_text="Literal[Medal.gold]") diff --git a/packages/pyright-internal/src/tests/samples/memberAccess1.py b/packages/pyright-internal/src/tests/samples/memberAccess1.py index c29e2f0bb518..90caf6ca917f 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess1.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess1.py @@ -2,7 +2,7 @@ # like __get__ and __set__ are handled correctly. from contextlib import ExitStack -from typing import Any, ContextManager, Generic, Optional, Type, TypeVar, overload +from typing import Any, ContextManager, Generic, TypeVar, overload from functools import cached_property _T = TypeVar("_T") @@ -41,7 +41,7 @@ def baz(self) -> int: class Factory: - def __get__(self, obj: Any, cls: Type[_T]) -> _T: + def __get__(self, obj: Any, cls: type[_T]) -> _T: return cls() @@ -55,7 +55,7 @@ class ClassC: class GenericDescriptor(Generic[_T]): value: _T - def __get__(self, instance: Optional[object], cls: Type[object]) -> _T: + def __get__(self, instance: object | None, cls: type[object]) -> _T: ... def __set__(self, instance: object, value: _T) -> None: diff --git a/packages/pyright-internal/src/tests/samples/memberAccess11.py b/packages/pyright-internal/src/tests/samples/memberAccess11.py index bbaa7cb7f4a4..fb0ae7eb6609 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess11.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess11.py @@ -3,12 +3,10 @@ from typing import Callable -UnboundMethodThatTakesIntAndReturnsStr = Callable[["MyClass", int], str] +Callback = Callable[["MyClass", int], str] -def method_decorator( - method: UnboundMethodThatTakesIntAndReturnsStr, -) -> UnboundMethodThatTakesIntAndReturnsStr: +def decorator1(method: Callback) -> Callback: def wrapper(self: "MyClass", a: int) -> str: return "wrapped " + method(self, a) @@ -19,14 +17,14 @@ class MyClass: def __init__(self): self.method4 = lambda x: x - @method_decorator + @decorator1 def method1(self, a: int) -> str: return "foo" def method2(self, a: int) -> str: return "foo" - method3 = method_decorator(method2) + method3 = decorator1(method2) mc = MyClass() diff --git a/packages/pyright-internal/src/tests/samples/memberAccess12.py b/packages/pyright-internal/src/tests/samples/memberAccess12.py index d16955764f13..0bf4ba09d556 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess12.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess12.py @@ -1,7 +1,7 @@ # This sample tests a member access when the metaclass implements a descriptor # protocol. -from typing import Any, Optional, Union, Type, TypeVar, overload +from typing import Any, TypeVar, overload T = TypeVar("T") @@ -9,16 +9,14 @@ class MetaClass(type): @overload - def __get__(self: Type[T], instance: None, owner: Any) -> Type[T]: + def __get__(self: type[T], instance: None, owner: Any) -> type[T]: ... @overload - def __get__(self: Type[T], instance: object, owner: Any) -> T: + def __get__(self: type[T], instance: object, owner: Any) -> T: ... - def __get__( - self: Type[T], instance: Optional[object], owner: Any - ) -> Union[Type[T], T]: + def __get__(self: type[T], instance: object | None, owner: Any) -> type[T] | T: if instance is None: return self return self() diff --git a/packages/pyright-internal/src/tests/samples/memberAccess13.py b/packages/pyright-internal/src/tests/samples/memberAccess13.py index c04021a50d8f..19fdf437db60 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess13.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess13.py @@ -1,12 +1,11 @@ # This sample tests a member access when the member is a class # that inherits from Any. -from typing import Type from unittest.mock import Mock class MockProducer: - produce: Type[Mock] = Mock + produce: type[Mock] = Mock reveal_type(MockProducer.produce, expected_text="type[Mock]") diff --git a/packages/pyright-internal/src/tests/samples/memberAccess14.py b/packages/pyright-internal/src/tests/samples/memberAccess14.py index 1b8205e85352..3b442959b0d5 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess14.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess14.py @@ -3,7 +3,7 @@ # the descriptor. -from typing import Any, Callable, Generic, TypeVar, Union, overload +from typing import Any, Callable, Generic, TypeVar, overload T = TypeVar("T") T_contra = TypeVar("T_contra", contravariant=True) @@ -28,8 +28,8 @@ def __get__(self, instance: T_contra, owner: Any) -> V_co: ... def __get__( - self: CachedSlotPropertyT, instance: Union[T_contra, None], owner: Any - ) -> Union[CachedSlotPropertyT, V_co]: + self: CachedSlotPropertyT, instance: T_contra | None, owner: Any + ) -> CachedSlotPropertyT | V_co: ... diff --git a/packages/pyright-internal/src/tests/samples/memberAccess19.py b/packages/pyright-internal/src/tests/samples/memberAccess19.py index fbf6bd339d2c..059d4e1db0fc 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess19.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess19.py @@ -1,4 +1,4 @@ -# This sample tests the handling of __getattr__, __setattr__, and +# This sample tests the handling of __getattr__, __setattr__, and # __delattr__ methods. from typing import Any, Literal, TypeVar, overload diff --git a/packages/pyright-internal/src/tests/samples/memberAccess2.py b/packages/pyright-internal/src/tests/samples/memberAccess2.py index 484f8dd55ea5..f142e27243b9 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess2.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess2.py @@ -4,6 +4,7 @@ from typing import Callable, NamedTuple, TypedDict + # This class follows the normal rules where variable # b, which is callable, acts like a class member and # is bound to an instance by the member access operator. diff --git a/packages/pyright-internal/src/tests/samples/memberAccess4.py b/packages/pyright-internal/src/tests/samples/memberAccess4.py index 231089fe817b..0a46b109eaba 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess4.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess4.py @@ -2,7 +2,7 @@ # "self" or "cls" parameter type is honored when binding the # method to an object or class. -from typing import Protocol, Type, TypeVar +from typing import Protocol, TypeVar class HasItemProtocol1(Protocol): @@ -44,7 +44,7 @@ def must_have(self) -> None: class Mixin2: @classmethod - def do_stuff(cls: Type[HasItemProtocol2]): + def do_stuff(cls: type[HasItemProtocol2]): pass diff --git a/packages/pyright-internal/src/tests/samples/memberAccess5.py b/packages/pyright-internal/src/tests/samples/memberAccess5.py index 6bbd8dbb71d3..c86e1de5a7ad 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess5.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess5.py @@ -2,7 +2,7 @@ # objects that provide a __get__ method and those # that do not. -from typing import Any, Union +from typing import Any class IntProvider: @@ -11,7 +11,7 @@ def __get__(self, instance: object, owner: Any) -> int: class Foo: - _int_value_declared: Union[IntProvider, int] = 3 + _int_value_declared: IntProvider | int = 3 _int_value_inferred = 3 def __init__(self): diff --git a/packages/pyright-internal/src/tests/samples/memberAccess6.py b/packages/pyright-internal/src/tests/samples/memberAccess6.py index 6715e2010401..c97c6bc36dbb 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess6.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess6.py @@ -3,18 +3,18 @@ # pyright: strict -from typing import Any, Generic, Optional, Type, TypeVar, overload +from typing import Any, Generic, TypeVar, overload _T = TypeVar("_T") -class FooBase: +class ParentA: pass class Column(Generic[_T]): - def __init__(self: "Column[_T]", type: Type[_T]) -> None: + def __init__(self: "Column[_T]", type: type[_T]) -> None: ... @overload @@ -22,31 +22,29 @@ def __get__(self: "Column[_T]", instance: None, type: Any) -> "Column[_T]": ... @overload - def __get__(self: "Column[_T]", instance: FooBase, type: Any) -> _T: + def __get__(self: "Column[_T]", instance: ParentA, type: Any) -> _T: ... - def __get__( - self, instance: Optional[FooBase], type: Any - ) -> Optional[_T] | "Column[_T]": + def __get__(self, instance: ParentA | None, type: Any) -> _T | None | "Column[_T]": ... -class Foo(FooBase): - bar: Column[str] = Column(str) - baz = Column(str) +class ChildA(ParentA): + attr1: Column[str] = Column(str) + attr2 = Column(str) -Foo.bar -Foo().bar -Foo.baz -Foo().baz +ChildA.attr1 +ChildA().attr1 +ChildA.attr2 +ChildA().attr2 -foo = Foo() +foo = ChildA() # This should generate an error because bar is declared as containing a # Column[str], which doesn't provide a __set__ method. -foo.bar = "" +foo.attr1 = "" # This should generate an error because baz's inferred type is # Column[str], which doesn't provide a __set__ method. -foo.baz = "" +foo.attr2 = "" diff --git a/packages/pyright-internal/src/tests/samples/memberAccess8.py b/packages/pyright-internal/src/tests/samples/memberAccess8.py index fb18905e752d..7bd249e66fea 100644 --- a/packages/pyright-internal/src/tests/samples/memberAccess8.py +++ b/packages/pyright-internal/src/tests/samples/memberAccess8.py @@ -1,6 +1,6 @@ # This sample tests the use of a generic descriptor class. -from typing import Any, Callable, Generic, Optional, Type, TypeVar, overload +from typing import Any, Callable, Generic, TypeVar, overload _T = TypeVar("_T") @@ -44,14 +44,14 @@ def __init__(self, name: str, func: Callable[[_T], _T_co]): ... @overload - def __get__(self, instance: None, owner: Type[_T]) -> "Minimal[_T, _T_co]": + def __get__(self, instance: None, owner: type[_T]) -> "Minimal[_T, _T_co]": ... @overload - def __get__(self, instance: _T, owner: Type[_T]) -> _T_co: + def __get__(self, instance: _T, owner: type[_T]) -> _T_co: ... - def __get__(self, instance: Optional[_T], owner: Type[_T]) -> Any: + def __get__(self, instance: _T | None, owner: type[_T]) -> Any: ... diff --git a/packages/pyright-internal/src/tests/samples/metaclass1.py b/packages/pyright-internal/src/tests/samples/metaclass1.py index 488c8eec1b6c..e4adb7081eef 100644 --- a/packages/pyright-internal/src/tests/samples/metaclass1.py +++ b/packages/pyright-internal/src/tests/samples/metaclass1.py @@ -1,7 +1,7 @@ # This sample tests pyright's ability to use metaclasses. from ctypes import Array, c_uint64 -from typing import Any, Generic, TypeAlias, TypeVar +from typing import Any, TypeAlias, TypeVar myArray1 = (c_uint64 * 5)() diff --git a/packages/pyright-internal/src/tests/samples/metaclass5.py b/packages/pyright-internal/src/tests/samples/metaclass5.py index 7967a0860d02..8e5c641a0ccf 100644 --- a/packages/pyright-internal/src/tests/samples/metaclass5.py +++ b/packages/pyright-internal/src/tests/samples/metaclass5.py @@ -1,33 +1,31 @@ # This sample tests the handling of metaclass magic methods for # binary operators. -from typing import Type - -class MetaFoo(type): - def __eq__(self, a: "Type[Foo]") -> str: +class MetaA(type): + def __eq__(self, a: "type[ClassA]") -> str: return "hi" - def __add__(self, a: "Type[Foo]") -> int: + def __add__(self, a: "type[ClassA]") -> int: return 0 -class Foo(metaclass=MetaFoo): +class ClassA(metaclass=MetaA): pass -def func1(a: Foo): - reveal_type(type(a), expected_text="type[Foo]") +def func1(a: ClassA): + reveal_type(type(a), expected_text="type[ClassA]") reveal_type(type("string1"), expected_text="type[str]") reveal_type(type(a) == type("hi"), expected_text="bool") reveal_type(type("hi") == type("hi"), expected_text="bool") reveal_type(str != str, expected_text="bool") - reveal_type(Foo == type(a), expected_text="str") - reveal_type(Foo != type(a), expected_text="bool") - reveal_type(type(a) == Foo, expected_text="str") + reveal_type(ClassA == type(a), expected_text="str") + reveal_type(ClassA != type(a), expected_text="bool") + reveal_type(type(a) == ClassA, expected_text="str") # This should generate an error x = str + str - reveal_type(Foo + Foo, expected_text="int") + reveal_type(ClassA + ClassA, expected_text="int") diff --git a/packages/pyright-internal/src/tests/samples/metaclass9.py b/packages/pyright-internal/src/tests/samples/metaclass9.py index 7fdf2b7445f2..c0aa464d23e6 100644 --- a/packages/pyright-internal/src/tests/samples/metaclass9.py +++ b/packages/pyright-internal/src/tests/samples/metaclass9.py @@ -1,15 +1,15 @@ # This sample tests the handling of metaclass keyword arguments. -from typing import Tuple, Dict, Any, Type +from typing import Any from typing_extensions import Self class Meta1(type): def __new__( - cls: Type[Self], + cls: type[Self], cls_name: str, - bases: Tuple[type, ...], - attrs: Dict[str, Any], + bases: tuple[type, ...], + attrs: dict[str, Any], *, param1: int, param2: str, @@ -43,10 +43,10 @@ class Class1_5(metaclass=Meta1, param2="", param1=1, param4=3): class Meta2(type): def __new__( - cls: Type[Self], + cls: type[Self], cls_name: str, - bases: Tuple[type, ...], - attrs: Dict[str, Any], + bases: tuple[type, ...], + attrs: dict[str, Any], *, param1: int, **kwargs: str, diff --git a/packages/pyright-internal/src/tests/samples/methodOverride1.py b/packages/pyright-internal/src/tests/samples/methodOverride1.py index d648c467cd97..7846cf09b3b4 100644 --- a/packages/pyright-internal/src/tests/samples/methodOverride1.py +++ b/packages/pyright-internal/src/tests/samples/methodOverride1.py @@ -6,14 +6,10 @@ Callable, Generic, Iterable, - List, - Optional, ParamSpec, Sequence, - Type, TypedDict, TypeVar, - Union, overload, ) @@ -61,7 +57,7 @@ def my_method10(self, a: int, b: int): def my_method11(self, a: int, b: int): return 1 - def my_method12(self, a: Union[int, str]) -> Union[int, str]: + def my_method12(self, a: int | str) -> int | str: return 1 def my_method13(self, a: int) -> int: @@ -86,7 +82,7 @@ def my_method19(self, a: str, b: int, c: float, d: bool) -> None: ... @classmethod - def my_method20(cls: Type[T_ParentClass], a: str) -> T_ParentClass: + def my_method20(cls: type[T_ParentClass], a: str) -> T_ParentClass: ... def my_method21(self, var: int) -> None: @@ -128,11 +124,11 @@ def my_method30(cls, /) -> None: ... @staticmethod - def my_method31(a: "Type[ParentClass]", /) -> None: + def my_method31(a: "type[ParentClass]", /) -> None: ... @staticmethod - def my_method32(a: "Type[ParentClass]", /) -> None: + def my_method32(a: "type[ParentClass]", /) -> None: ... def my_method33(self, /) -> None: @@ -220,12 +216,12 @@ def my_method11(self, a: int, b: int, *, c: str = "", **kwargs): def my_method12(self, a: int) -> int: return 1 - def my_method13(self, a: Union[int, str]) -> int: + def my_method13(self, a: int | str) -> int: return 1 # This should generate an error because the return type is # wider than in the original method. - def my_method14(self, a: int) -> Union[int, str]: + def my_method14(self, a: int) -> int | str: return 1 # This should generate an error because we're overriding a @@ -248,7 +244,7 @@ def my_method19(self, b: str, *args: object, **kwargs: object) -> None: ... @classmethod - def my_method20(cls: Type[T_ChildClass], a: str) -> T_ChildClass: + def my_method20(cls: type[T_ChildClass], a: str) -> T_ChildClass: ... # This should generate an error. @@ -293,7 +289,7 @@ def my_method29(self, /) -> None: # This should generate an error because it is not a classmethod. @staticmethod - def my_method30(a: Type[ParentClass], /) -> None: + def my_method30(a: type[ParentClass], /) -> None: ... # This should generate an error because it is not a staticmethod. @@ -312,7 +308,7 @@ def my_method33(cls, /) -> None: # This should generate an error because it is not an instance method. @staticmethod - def my_method34(a: Type[ParentClass], /) -> None: + def my_method34(a: type[ParentClass], /) -> None: ... def my_method35(self, **kwargs: int) -> None: @@ -366,14 +362,14 @@ def test(self, t: Iterable[int], bbb: str = "") -> Sequence[str]: class NarrowerArgument(A): - # This should generate error because List[int] is narrower + # This should generate error because list[int] is narrower # than Iterable[int]. - def test(self, t: List[int]) -> Sequence[str]: + def test(self, t: list[int]) -> Sequence[str]: ... class NarrowerReturn(A): - def test(self, t: Sequence[int]) -> List[str]: + def test(self, t: Sequence[int]) -> list[str]: ... @@ -385,9 +381,9 @@ def test(self, t: Sequence[int]) -> Iterable[str]: class GeneralizedReturn2(A): - # This should generate an error because List[int] is + # This should generate an error because list[int] is # incompatible with Sequence[str]. - def test(self, t: Sequence[int]) -> List[int]: + def test(self, t: Sequence[int]) -> list[int]: ... @@ -396,12 +392,12 @@ def test(self, t: Sequence[int]) -> List[int]: class Base1: - def submit(self, fn: Callable[..., _T1], *args: Any, **kwargs: Any) -> List[_T1]: + def submit(self, fn: Callable[..., _T1], *args: Any, **kwargs: Any) -> list[_T1]: return [] class Base2(Base1): - def submit(self, fn: Callable[..., _T2], *args: Any, **kwargs: Any) -> List[_T2]: + def submit(self, fn: Callable[..., _T2], *args: Any, **kwargs: Any) -> list[_T2]: return [] @@ -414,15 +410,15 @@ class Foo: class ClassA(Generic[_T2A]): - def func1(self) -> Optional[_T2A]: + def func1(self) -> _T2A | None: return None @property - def prop1(self) -> Optional[_T2A]: + def prop1(self) -> _T2A | None: return None @property - def prop2(self) -> Optional[_T2A]: + def prop2(self) -> _T2A | None: return None @prop2.setter @@ -434,7 +430,7 @@ def prop2(self): pass @property - def prop3(self) -> Optional[_T2A]: + def prop3(self) -> _T2A | None: return None @prop3.setter @@ -442,7 +438,7 @@ def prop3(self, val: _T2A): pass @property - def prop4(self) -> Optional[_T2A]: + def prop4(self) -> _T2A | None: return None @prop4.deleter @@ -459,7 +455,7 @@ class ClassB(ClassA[_T2B]): # cannot override a property. prop1: _T2B - def func1(self) -> Optional[_T2B]: + def func1(self) -> _T2B | None: return None @property @@ -477,13 +473,13 @@ def prop2(self): # This should generate an error because it is missing # a setter (fset method). @property - def prop3(self) -> Optional[_T2B]: + def prop3(self) -> _T2B | None: return None # This should generate an error because it is missing # a deleter (fdel method). @property - def prop4(self) -> Optional[_T2B]: + def prop4(self) -> _T2B | None: return None # This should generate an error because prop4's getter @@ -529,4 +525,4 @@ def a(self) -> float: class MyObject(TypedDict): - values: List[str] + values: list[str] diff --git a/packages/pyright-internal/src/tests/samples/methodOverride5.py b/packages/pyright-internal/src/tests/samples/methodOverride5.py index 36ae2da6dac9..5424963337d3 100644 --- a/packages/pyright-internal/src/tests/samples/methodOverride5.py +++ b/packages/pyright-internal/src/tests/samples/methodOverride5.py @@ -8,11 +8,12 @@ Ts = TypeVarTuple("Ts") + class Parent(Generic[*Ts]): def method_1(self, *args: *Ts) -> None: ... - def method_2(self, *args: *tuple[*Ts]) -> None: + def method_2(self, *args: * tuple[*Ts]) -> None: ... @@ -22,4 +23,3 @@ def method_1(self, arg1: int) -> None: def method_2(self, arg1: int) -> None: ... - diff --git a/packages/pyright-internal/src/tests/samples/methods1.py b/packages/pyright-internal/src/tests/samples/methods1.py index 62f3f40c3fab..aa40c1b2a4b8 100644 --- a/packages/pyright-internal/src/tests/samples/methods1.py +++ b/packages/pyright-internal/src/tests/samples/methods1.py @@ -1,15 +1,7 @@ # This sample tests that instance methods, regardless of how they're # defined or decorated, act like instance methods. -from typing import ( - Any, - Callable, - ClassVar, - Concatenate, - Generic, - ParamSpec, - TypeVar, -) +from typing import Any, Callable, ClassVar, Concatenate, Generic, ParamSpec, TypeVar P = ParamSpec("P") R = TypeVar("R") diff --git a/packages/pyright-internal/src/tests/samples/missingTypeArg1.py b/packages/pyright-internal/src/tests/samples/missingTypeArg1.py index 1f54cf634734..0a2f093f0d89 100644 --- a/packages/pyright-internal/src/tests/samples/missingTypeArg1.py +++ b/packages/pyright-internal/src/tests/samples/missingTypeArg1.py @@ -1,7 +1,7 @@ # This sample tests the reportMissingTypeArgument diagnostic rule. import collections -from typing import Generic, Optional, TypeVar, Union +from typing import Generic, TypeVar _T1 = TypeVar("_T1") @@ -21,14 +21,14 @@ class Class2(Class1): # This should generate an error when reportMissingTypeArgument is enabled. -var1: Optional[Class1] = None +var1: Class1 | None = None -GenericTypeAlias = Union[Class1[_T1], int] +GenericTypeAlias = Class1[_T1] | int # This should generate an error when reportMissingTypeArgument is enabled. -var2: Optional[GenericTypeAlias] = None +var2: GenericTypeAlias | None = None class Class3(Generic[_T1, _T2]): diff --git a/packages/pyright-internal/src/tests/samples/nameBindings1.py b/packages/pyright-internal/src/tests/samples/nameBinding1.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/nameBindings1.py rename to packages/pyright-internal/src/tests/samples/nameBinding1.py diff --git a/packages/pyright-internal/src/tests/samples/nameBindings2.py b/packages/pyright-internal/src/tests/samples/nameBinding2.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/nameBindings2.py rename to packages/pyright-internal/src/tests/samples/nameBinding2.py diff --git a/packages/pyright-internal/src/tests/samples/nameBindings3.py b/packages/pyright-internal/src/tests/samples/nameBinding3.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/nameBindings3.py rename to packages/pyright-internal/src/tests/samples/nameBinding3.py diff --git a/packages/pyright-internal/src/tests/samples/nameBindings4.py b/packages/pyright-internal/src/tests/samples/nameBinding4.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/nameBindings4.py rename to packages/pyright-internal/src/tests/samples/nameBinding4.py diff --git a/packages/pyright-internal/src/tests/samples/nameBindings5.py b/packages/pyright-internal/src/tests/samples/nameBinding5.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/nameBindings5.py rename to packages/pyright-internal/src/tests/samples/nameBinding5.py diff --git a/packages/pyright-internal/src/tests/samples/isinstance10.py b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance13.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/isinstance10.py rename to packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance13.py diff --git a/packages/pyright-internal/src/tests/samples/isinstance9.py b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance14.py similarity index 83% rename from packages/pyright-internal/src/tests/samples/isinstance9.py rename to packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance14.py index a0fc82d14eb0..4fed42982437 100644 --- a/packages/pyright-internal/src/tests/samples/isinstance9.py +++ b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance14.py @@ -1,7 +1,7 @@ # This sample tests the isinstance narrowing when the list # of classes includes a type defined by a type variable. -from typing import Any, Type, TypeVar, Union +from typing import Any, Type, TypeVar T = TypeVar("T") @@ -16,7 +16,7 @@ def func1(cls: Type[T], obj: Any) -> T: reveal_type(v1, expected_text="int") -def func2(klass: Type[T], obj: Union[T, int]) -> T: +def func2(klass: Type[T], obj: T | int) -> T: assert isinstance(obj, klass) reveal_type(obj, expected_text="T@func2") return obj diff --git a/packages/pyright-internal/src/tests/samples/isinstance7.py b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance15.py similarity index 100% rename from packages/pyright-internal/src/tests/samples/isinstance7.py rename to packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance15.py diff --git a/packages/pyright-internal/src/tests/samples/isinstance6.py b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance16.py similarity index 55% rename from packages/pyright-internal/src/tests/samples/isinstance6.py rename to packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance16.py index e7b2ad824189..a7b7281b7e54 100644 --- a/packages/pyright-internal/src/tests/samples/isinstance6.py +++ b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance16.py @@ -2,18 +2,18 @@ # based on cls and self parameters. -class Foo: +class ClassA: @classmethod def bar(cls, other: type): if issubclass(other, cls): - reveal_type(other, expected_text="type[Self@Foo]") + reveal_type(other, expected_text="type[Self@ClassA]") if issubclass(other, (int, cls)): - reveal_type(other, expected_text="type[Self@Foo] | type[int]") + reveal_type(other, expected_text="type[Self@ClassA] | type[int]") def baz(self, other: object): if isinstance(other, type(self)): - reveal_type(other, expected_text="Self@Foo") + reveal_type(other, expected_text="Self@ClassA") if isinstance(other, (int, type(self))): - reveal_type(other, expected_text="Self@Foo | int") + reveal_type(other, expected_text="Self@ClassA | int") diff --git a/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance17.py b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance17.py new file mode 100644 index 000000000000..5a8d6292986a --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/typeNarrowingIsinstance17.py @@ -0,0 +1,57 @@ +# This sample tests basic type narrowing behavior for +# the isinstance call. + +from typing import Any, List, Optional, Type, TypedDict, Union + + +def func1(x: Union[List[str], int]): + if isinstance(x, list): + reveal_type(x, expected_text="List[str]") + else: + reveal_type(x, expected_text="int") + + +def func2(x: Any): + if isinstance(x, list): + reveal_type(x, expected_text="list[Unknown]") + else: + reveal_type(x, expected_text="Any") + + +def func3(x): + if isinstance(x, list): + reveal_type(x, expected_text="list[Unknown]") + else: + reveal_type(x, expected_text="Unknown") + + +class SomeTypedDict(TypedDict): + name: str + + +def func4(x: Union[int, SomeTypedDict]): + if isinstance(x, dict): + reveal_type(x, expected_text="SomeTypedDict") + else: + reveal_type(x, expected_text="int") + + +def func5(x: int | str | complex): + if isinstance(x, (int, str)): + reveal_type(x, expected_text="int | str") + else: + reveal_type(x, expected_text="complex") + + +def func6(x: Type[int] | Type[str] | Type[complex]): + if issubclass(x, (int, str)): + reveal_type(x, expected_text="type[int] | type[str]") + else: + reveal_type(x, expected_text="type[complex]") + + +def func7(x: Optional[Union[int, SomeTypedDict]]): + if isinstance(x, (dict, type(None))): + reveal_type(x, expected_text="SomeTypedDict | None") + else: + reveal_type(x, expected_text="int") diff --git a/packages/pyright-internal/src/tests/typeEvaluator1.test.ts b/packages/pyright-internal/src/tests/typeEvaluator1.test.ts index 209302f51467..e3895ba1a804 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator1.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator1.test.ts @@ -417,6 +417,39 @@ test('TypeNarrowingIsinstance12', () => { TestUtils.validateResults(analysisResults, 0); }); +test('TypeNarrowingIsinstance13.py', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeNarrowingIsinstance13.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + +test('TypeNarrowingIsinstance14', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeNarrowingIsinstance14.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + +test('TypeNarrowingIsinstance15', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeNarrowingIsinstance15.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + +test('TypeNarrowingIsinstance16', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeNarrowingIsinstance16.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + +test('TypeNarrowingIsinstance17', () => { + // This test requires Python 3.10 because it uses PEP 604 notation for unions. + const configOptions = new ConfigOptions('.'); + configOptions.defaultPythonVersion = PythonVersion.V3_10; + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeNarrowingIsinstance17.py'], configOptions); + + TestUtils.validateResults(analysisResults, 0); +}); + test('TypeNarrowingTupleLength1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeNarrowingTupleLength1.py']); diff --git a/packages/pyright-internal/src/tests/typeEvaluator2.test.ts b/packages/pyright-internal/src/tests/typeEvaluator2.test.ts index 1a65b9f8fe9a..4a87f96210aa 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator2.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator2.test.ts @@ -269,10 +269,7 @@ test('NewType6', () => { }); test('isInstance1', () => { - // This test requires Python 3.10 because it uses PEP 604 notation for unions. - const configOptions = new ConfigOptions('.'); - configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['isinstance1.py'], configOptions); + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['isinstance1.py']); TestUtils.validateResults(analysisResults, 0); }); @@ -301,36 +298,6 @@ test('isInstance4', () => { TestUtils.validateResults(analysisResults, 2); }); -test('isInstance5', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['isinstance5.py']); - - TestUtils.validateResults(analysisResults, 0); -}); - -test('isInstance6', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['isinstance6.py']); - - TestUtils.validateResults(analysisResults, 0); -}); - -test('isInstance7', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['isinstance7.py']); - - TestUtils.validateResults(analysisResults, 0); -}); - -test('isInstance9', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['isinstance9.py']); - - TestUtils.validateResults(analysisResults, 0); -}); - -test('isInstance10', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['isinstance10.py']); - - TestUtils.validateResults(analysisResults, 0); -}); - test('Unbound1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['unbound1.py']); @@ -385,32 +352,32 @@ test('AssertType1', () => { TestUtils.validateResults(analysisResults, 11); }); -test('NameBindings1', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBindings1.py']); +test('NameBinding1', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBinding1.py']); TestUtils.validateResults(analysisResults, 5); }); -test('NameBindings2', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBindings2.py']); +test('NameBinding2', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBinding2.py']); TestUtils.validateResults(analysisResults, 1); }); -test('NameBindings3', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBindings3.py']); +test('NameBinding3', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBinding3.py']); TestUtils.validateResults(analysisResults, 3); }); -test('NameBindings4', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBindings4.py']); +test('NameBinding4', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBinding4.py']); TestUtils.validateResults(analysisResults, 0); }); -test('NameBindings5', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBindings5.py']); +test('NameBinding5', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['nameBinding5.py']); TestUtils.validateResults(analysisResults, 0); }); diff --git a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts index 77e012302c2e..b090db46b4f8 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts @@ -166,230 +166,230 @@ test('Coroutines3', () => { TestUtils.validateResults(analysisResults, 0); }); -test('Loops1', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops1.py']); +test('Loop1', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop1.py']); TestUtils.validateResults(analysisResults, 2); }); -test('Loops2', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops2.py']); +test('Loop2', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop2.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops3', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops3.py']); +test('Loop3', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop3.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops4', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops4.py']); +test('Loop4', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop4.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops5', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops5.py']); +test('Loop5', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop5.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops6', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops6.py']); +test('Loop6', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop6.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops7', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops7.py']); +test('Loop7', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop7.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops8', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops8.py']); +test('Loop8', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop8.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops9', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops9.py']); +test('Loop9', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop9.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops10', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops10.py']); +test('Loop10', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop10.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops11', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops11.py']); +test('Loop11', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop11.py']); TestUtils.validateResults(analysisResults, 3); }); -test('Loops12', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops12.py']); +test('Loop12', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop12.py']); TestUtils.validateResults(analysisResults, 1); }); -test('Loops13', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops13.py']); +test('Loop13', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop13.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops14', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops14.py']); +test('Loop14', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop14.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops15', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops15.py']); +test('Loop15', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop15.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops16', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops16.py']); +test('Loop16', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop16.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops17', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops17.py']); +test('Loop17', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop17.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops18', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops18.py']); +test('Loop18', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop18.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops19', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops19.py']); +test('Loop19', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop19.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops20', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops20.py']); +test('Loop20', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop20.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops21', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops21.py']); +test('Loop21', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop21.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops22', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops22.py']); +test('Loop22', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop22.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops23', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops23.py']); +test('Loop23', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop23.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops24', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops24.py']); +test('Loop24', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop24.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops25', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops25.py']); +test('Loop25', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop25.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops26', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops26.py']); +test('Loop26', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop26.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops27', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops27.py']); +test('Loop27', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop27.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops28', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops28.py']); +test('Loop28', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop28.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops29', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops29.py']); +test('Loop29', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop29.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops30', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops30.py']); +test('Loop30', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop30.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops31', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops31.py']); +test('Loop31', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop31.py']); TestUtils.validateResults(analysisResults, 1); }); -test('Loops32', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops32.py']); +test('Loop32', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop32.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops33', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops33.py']); +test('Loop33', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop33.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops34', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops34.py']); +test('Loop34', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop34.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops35', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops35.py']); +test('Loop35', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop35.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops36', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops36.py']); +test('Loop36', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop36.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops37', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops37.py']); +test('Loop37', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop37.py']); TestUtils.validateResults(analysisResults, 0); }); -test('Loops38', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loops38.py']); +test('Loop38', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop38.py']); TestUtils.validateResults(analysisResults, 0); }); @@ -406,56 +406,56 @@ test('ForLoop2', () => { TestUtils.validateResults(analysisResults, 7); }); -test('ListComprehension1', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension1.py']); +test('Comprehension1', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension1.py']); TestUtils.validateResults(analysisResults, 2); }); -test('ListComprehension2', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension2.py']); +test('Comprehension2', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension2.py']); TestUtils.validateResults(analysisResults, 0); }); -test('ListComprehension3', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension3.py']); +test('Comprehension3', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension3.py']); TestUtils.validateResults(analysisResults, 0); }); -test('ListComprehension4', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension4.py']); +test('Comprehension4', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension4.py']); TestUtils.validateResults(analysisResults, 0); }); -test('ListComprehension5', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension5.py']); +test('Comprehension5', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension5.py']); TestUtils.validateResults(analysisResults, 0); }); -test('ListComprehension6', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension6.py']); +test('Comprehension6', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension6.py']); TestUtils.validateResults(analysisResults, 4); }); -test('ListComprehension7', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension7.py']); +test('Comprehension7', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension7.py']); TestUtils.validateResults(analysisResults, 1); }); -test('ListComprehension8', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension8.py']); +test('Comprehension8', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension8.py']); TestUtils.validateResults(analysisResults, 0); }); -test('ListComprehension9', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['listComprehension9.py']); +test('Comprehension9', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['comprehension9.py']); TestUtils.validateResults(analysisResults, 0); }); @@ -1187,90 +1187,90 @@ test('Match3', () => { configOptions.defaultPythonVersion = PythonVersion.V3_10; const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match3.py'], configOptions); - TestUtils.validateResults(analysisResults, 4); + TestUtils.validateResults(analysisResults, 0); }); -test('Match4', () => { +test('MatchSequence1', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match4.py'], configOptions); - TestUtils.validateResults(analysisResults, 0); + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['matchSequence1.py'], configOptions); + TestUtils.validateResults(analysisResults, 2); }); -test('Match5', () => { +test('MatchClass1', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match5.py'], configOptions); - TestUtils.validateResults(analysisResults, 2); + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['matchClass1.py'], configOptions); + TestUtils.validateResults(analysisResults, 4); }); -test('Match6', () => { +test('MatchClass2', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match6.py'], configOptions); + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['matchClass2.py'], configOptions); TestUtils.validateResults(analysisResults, 0); }); -test('Match7', () => { +test('MatchClass3', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match7.py'], configOptions); - TestUtils.validateResults(analysisResults, 2); + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['matchClass3.py'], configOptions); + TestUtils.validateResults(analysisResults, 0); }); -test('Match8', () => { +test('MatchValue1', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match8.py'], configOptions); + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['matchValue1.py'], configOptions); TestUtils.validateResults(analysisResults, 0); }); -test('Match9', () => { +test('MatchMapping1', () => { + const configOptions = new ConfigOptions('.'); + + configOptions.defaultPythonVersion = PythonVersion.V3_10; + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['matchMapping1.py'], configOptions); + TestUtils.validateResults(analysisResults, 2); +}); + +test('MatchLiteral1', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match9.py'], configOptions); + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['matchLiteral1.py'], configOptions); TestUtils.validateResults(analysisResults, 0); }); -test('Match10', () => { +test('MatchExhaustion1', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; configOptions.diagnosticRuleSet.reportMatchNotExhaustive = 'none'; - const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['match10.py'], configOptions); + const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['matchExhaustion1.py'], configOptions); TestUtils.validateResults(analysisResults1, 0); configOptions.diagnosticRuleSet.reportMatchNotExhaustive = 'error'; - const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['match10.py'], configOptions); + const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['matchExhaustion1.py'], configOptions); TestUtils.validateResults(analysisResults2, 4); }); -test('Match11', () => { +test('MatchUnnecessary1', () => { const configOptions = new ConfigOptions('.'); configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['match11.py'], configOptions); + const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['matchUnnecessary1.py'], configOptions); TestUtils.validateResults(analysisResults1, 0); configOptions.diagnosticRuleSet.reportUnnecessaryComparison = 'error'; - const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['match11.py'], configOptions); + const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['matchUnnecessary1.py'], configOptions); TestUtils.validateResults(analysisResults2, 7); }); -test('Match12', () => { - const configOptions = new ConfigOptions('.'); - - configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['match12.py'], configOptions); - TestUtils.validateResults(analysisResults, 0); -}); - test('List1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['list1.py']); TestUtils.validateResults(analysisResults, 3);