From d082c1b2026afdc0fda0d90553f0d71157877242 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Mon, 3 Feb 2025 14:57:29 +0530 Subject: [PATCH] [red-knot] Add missing imports in mdtests (#15869) ## Summary Related to #15848, this PR adds the imports explicitly as we'll now flag these symbols as undefined. --------- Co-authored-by: Alex Waygood --- .../resources/mdtest/binary/custom.md | 8 ++++++++ .../resources/mdtest/boundness_declaredness/public.md | 2 ++ .../resources/mdtest/comparison/intersections.md | 2 ++ .../resources/mdtest/directives/assert_type.md | 2 +- .../resources/mdtest/expression/if.md | 2 ++ .../resources/mdtest/intersection_types.md | 2 ++ .../resources/mdtest/mdtest_config.md | 10 ++++++++++ .../resources/mdtest/narrow/boolean.md | 4 ++++ .../resources/mdtest/narrow/truthiness.md | 10 ++++++++++ .../resources/mdtest/statically_known_branches.md | 2 ++ .../resources/mdtest/subscript/tuple.md | 2 +- .../resources/mdtest/type_api.md | 6 +++++- .../resources/mdtest/type_of/dynamic.md | 2 ++ .../mdtest/type_properties/is_assignable_to.md | 4 ++-- .../mdtest/type_properties/is_disjoint_from.md | 3 ++- .../mdtest/type_properties/is_gradual_equivalent_to.md | 1 + .../resources/mdtest/type_properties/is_subtype_of.md | 4 +++- .../resources/mdtest/type_qualifiers/classvar.md | 6 ++++++ .../resources/mdtest/unary/not.md | 2 ++ .../resources/mdtest/unpacking.md | 2 ++ .../resources/mdtest/with/sync.md | 2 ++ 21 files changed, 71 insertions(+), 7 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/binary/custom.md b/crates/red_knot_python_semantic/resources/mdtest/binary/custom.md index 70b50f17cefdd..8fdca951c6182 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/binary/custom.md +++ b/crates/red_knot_python_semantic/resources/mdtest/binary/custom.md @@ -3,6 +3,8 @@ ## Class instances ```py +from typing import Literal + class Yes: def __add__(self, other) -> Literal["+"]: return "+" @@ -136,6 +138,8 @@ reveal_type(No() // Yes()) # revealed: Unknown ## Subclass reflections override superclass dunders ```py +from typing import Literal + class Yes: def __add__(self, other) -> Literal["+"]: return "+" @@ -294,6 +298,8 @@ itself. (For these operators to work on the class itself, they would have to be class's type, i.e. `type`.) ```py +from typing import Literal + class Yes: def __add__(self, other) -> Literal["+"]: return "+" @@ -312,6 +318,8 @@ reveal_type(No + No) # revealed: Unknown ## Subclass ```py +from typing import Literal + class Yes: def __add__(self, other) -> Literal["+"]: return "+" diff --git a/crates/red_knot_python_semantic/resources/mdtest/boundness_declaredness/public.md b/crates/red_knot_python_semantic/resources/mdtest/boundness_declaredness/public.md index f2b9e2ce7c89e..7ad8c991c63aa 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/boundness_declaredness/public.md +++ b/crates/red_knot_python_semantic/resources/mdtest/boundness_declaredness/public.md @@ -152,6 +152,8 @@ same as the "possibly bound" definition (symbol `b`). Note that we raise a `poss error for both `a` and `b`: ```py path=mod.py +from typing import Any + def flag() -> bool: ... if flag(): diff --git a/crates/red_knot_python_semantic/resources/mdtest/comparison/intersections.md b/crates/red_knot_python_semantic/resources/mdtest/comparison/intersections.md index 3d40f79663c18..4cbe9de116859 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/comparison/intersections.md +++ b/crates/red_knot_python_semantic/resources/mdtest/comparison/intersections.md @@ -6,6 +6,8 @@ If we have an intersection type `A & B` and we get a definitive true/false answe types, we can infer that the result for the intersection type is also true/false: ```py +from typing import Literal + class Base: ... class Child1(Base): diff --git a/crates/red_knot_python_semantic/resources/mdtest/directives/assert_type.md b/crates/red_knot_python_semantic/resources/mdtest/directives/assert_type.md index b6c6c4d6038ef..af0291493d63d 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/directives/assert_type.md +++ b/crates/red_knot_python_semantic/resources/mdtest/directives/assert_type.md @@ -78,7 +78,7 @@ def _(a: type[Unknown], b: type[Any]): Tuple types with the same elements are the same. ```py -from typing_extensions import assert_type +from typing_extensions import Any, assert_type from knot_extensions import Unknown diff --git a/crates/red_knot_python_semantic/resources/mdtest/expression/if.md b/crates/red_knot_python_semantic/resources/mdtest/expression/if.md index d2c6131def818..50ba10270c1d3 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/expression/if.md +++ b/crates/red_knot_python_semantic/resources/mdtest/expression/if.md @@ -28,6 +28,8 @@ reveal_type(1 if 0 else 2) # revealed: Literal[2] The test inside an if expression should not affect code outside of the expression. ```py +from typing import Literal + def _(flag: bool): x: Literal[42, "hello"] = 42 if flag else "hello" diff --git a/crates/red_knot_python_semantic/resources/mdtest/intersection_types.md b/crates/red_knot_python_semantic/resources/mdtest/intersection_types.md index dfe023daa45e5..a7f0441653aa9 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/intersection_types.md +++ b/crates/red_knot_python_semantic/resources/mdtest/intersection_types.md @@ -808,6 +808,7 @@ Dynamic types do not cancel each other out. Intersecting an unknown set of value of another unknown set of values is not necessarily empty, so we keep the positive contribution: ```py +from typing import Any from knot_extensions import Intersection, Not, Unknown def any( @@ -830,6 +831,7 @@ def unknown( We currently do not simplify mixed dynamic types, but might consider doing so in the future: ```py +from typing import Any from knot_extensions import Intersection, Not, Unknown def mixed( diff --git a/crates/red_knot_python_semantic/resources/mdtest/mdtest_config.md b/crates/red_knot_python_semantic/resources/mdtest/mdtest_config.md index d2b03b39ba8e5..d028c7a84a7a7 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/mdtest_config.md +++ b/crates/red_knot_python_semantic/resources/mdtest/mdtest_config.md @@ -13,6 +13,8 @@ python-version = "3.10" Here, we simply make sure that we pick up the global configuration from the root section: ```py +import sys + reveal_type(sys.version_info[:2] == (3, 10)) # revealed: Literal[True] ``` @@ -25,6 +27,8 @@ reveal_type(sys.version_info[:2] == (3, 10)) # revealed: Literal[True] The same should work for arbitrarily nested sections: ```py +import sys + reveal_type(sys.version_info[:2] == (3, 10)) # revealed: Literal[True] ``` @@ -38,6 +42,8 @@ python-version = "3.11" ``` ```py +import sys + reveal_type(sys.version_info[:2] == (3, 11)) # revealed: Literal[True] ``` @@ -46,6 +52,8 @@ reveal_type(sys.version_info[:2] == (3, 11)) # revealed: Literal[True] There is no global state. This section should again use the root configuration: ```py +import sys + reveal_type(sys.version_info[:2] == (3, 10)) # revealed: Literal[True] ``` @@ -63,5 +71,7 @@ python-version = "3.12" ### Grandchild ```py +import sys + reveal_type(sys.version_info[:2] == (3, 12)) # revealed: Literal[True] ``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/narrow/boolean.md b/crates/red_knot_python_semantic/resources/mdtest/narrow/boolean.md index 48553faf0c795..17f4454ff2173 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/narrow/boolean.md +++ b/crates/red_knot_python_semantic/resources/mdtest/narrow/boolean.md @@ -57,6 +57,8 @@ def _(flag1: bool, flag2: bool, flag3: bool, flag4: bool): ## Multiple predicates ```py +from typing import Literal + def _(flag1: bool, flag2: bool): class A: ... x: A | None | Literal[1] = A() if flag1 else None if flag2 else 1 @@ -67,6 +69,8 @@ def _(flag1: bool, flag2: bool): ## Mix of `and` and `or` ```py +from typing import Literal + def _(flag1: bool, flag2: bool): class A: ... x: A | None | Literal[1] = A() if flag1 else None if flag2 else 1 diff --git a/crates/red_knot_python_semantic/resources/mdtest/narrow/truthiness.md b/crates/red_knot_python_semantic/resources/mdtest/narrow/truthiness.md index b3975c1a813b7..03884b95e5c2d 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/narrow/truthiness.md +++ b/crates/red_knot_python_semantic/resources/mdtest/narrow/truthiness.md @@ -3,6 +3,8 @@ ## Value Literals ```py +from typing import Literal + def foo() -> Literal[0, -1, True, False, "", "foo", b"", b"bar", None] | tuple[()]: return 0 @@ -123,6 +125,8 @@ always returns a fixed value. These types can always be fully narrowed in boolean contexts, as shown below: ```py +from typing import Literal + class T: def __bool__(self) -> Literal[True]: return True @@ -149,6 +153,8 @@ else: ## Narrowing Complex Intersection and Union ```py +from typing import Literal + class A: ... class B: ... @@ -181,6 +187,8 @@ if isinstance(x, str) and not isinstance(x, B): ## Narrowing Multiple Variables ```py +from typing import Literal + def f(x: Literal[0, 1], y: Literal["", "hello"]): if x and y and not x and not y: reveal_type(x) # revealed: Never @@ -222,6 +230,8 @@ reveal_type(y) # revealed: A ## Truthiness of classes ```py +from typing import Literal + class MetaAmbiguous(type): def __bool__(self) -> bool: ... diff --git a/crates/red_knot_python_semantic/resources/mdtest/statically_known_branches.md b/crates/red_knot_python_semantic/resources/mdtest/statically_known_branches.md index eb1ea7f204ded..5b5f7c686c7b3 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/statically_known_branches.md +++ b/crates/red_knot_python_semantic/resources/mdtest/statically_known_branches.md @@ -168,6 +168,8 @@ not some special handling of specific conditions in semantic index building. We demonstrate this, since semantic index building is inherently single-module: ```py path=module.py +from typing import Literal + class AlwaysTrue: def __bool__(self) -> Literal[True]: return True diff --git a/crates/red_knot_python_semantic/resources/mdtest/subscript/tuple.md b/crates/red_knot_python_semantic/resources/mdtest/subscript/tuple.md index 528c518c8d4dd..594bb1bd2f98a 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/subscript/tuple.md +++ b/crates/red_knot_python_semantic/resources/mdtest/subscript/tuple.md @@ -97,7 +97,7 @@ reveal_type(A.__mro__) # revealed: tuple[Literal[A], Unknown, Literal[object]] `typing.Tuple` can be used interchangeably with `tuple`: ```py -from typing import Tuple +from typing import Any, Tuple class A: ... diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_api.md b/crates/red_knot_python_semantic/resources/mdtest/type_api.md index 715ceef584d41..9f03e16c0c972 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_api.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_api.md @@ -15,6 +15,7 @@ directly. ### Negation ```py +from typing import Literal from knot_extensions import Not, static_assert def negate(n1: Not[int], n2: Not[Not[int]], n3: Not[Not[Not[int]]]) -> None: @@ -34,7 +35,7 @@ n: Not[int, str] ```py from knot_extensions import Intersection, Not, is_subtype_of, static_assert -from typing_extensions import Never +from typing_extensions import Literal, Never class S: ... class T: ... @@ -304,6 +305,7 @@ static_assert(not is_assignable_to(int, str)) ```py from knot_extensions import is_disjoint_from, static_assert +from typing import Literal static_assert(is_disjoint_from(None, int)) static_assert(not is_disjoint_from(Literal[2] | str, int)) @@ -326,6 +328,7 @@ static_assert(not is_fully_static(type[Any])) ```py from knot_extensions import is_singleton, static_assert +from typing import Literal static_assert(is_singleton(None)) static_assert(is_singleton(Literal[True])) @@ -338,6 +341,7 @@ static_assert(not is_singleton(Literal["a"])) ```py from knot_extensions import is_single_valued, static_assert +from typing import Literal static_assert(is_single_valued(None)) static_assert(is_single_valued(Literal[True])) diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_of/dynamic.md b/crates/red_knot_python_semantic/resources/mdtest/type_of/dynamic.md index da7836d4f79b9..5a9243a7375b0 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_of/dynamic.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_of/dynamic.md @@ -6,6 +6,8 @@ This file contains tests for non-fully-static `type[]` types, such as `type[Any] ## Simple ```py +from typing import Any + def f(x: type[Any], y: type[str]): reveal_type(x) # revealed: type[Any] # TODO: could be ` & Any` diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md index 06ee56aaf0d5f..c7d9f92b02236 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md @@ -41,7 +41,7 @@ static types can be assignable to gradual types): ```py from knot_extensions import static_assert, is_assignable_to, Unknown -from typing import Any +from typing import Any, Literal static_assert(is_assignable_to(Unknown, Literal[1])) static_assert(is_assignable_to(Any, Literal[1])) @@ -333,7 +333,7 @@ assignable to any arbitrary type. ```py from knot_extensions import static_assert, is_assignable_to, Unknown -from typing_extensions import Never, Any +from typing_extensions import Never, Any, Literal static_assert(is_assignable_to(Never, str)) static_assert(is_assignable_to(Never, Literal[1])) diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_disjoint_from.md b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_disjoint_from.md index 2535d84bfb93f..d88100e8b496d 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_disjoint_from.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_disjoint_from.md @@ -151,7 +151,7 @@ static_assert(is_disjoint_from(Never, object)) ### `None` ```py -from typing_extensions import Literal +from typing_extensions import Literal, LiteralString from knot_extensions import is_disjoint_from, static_assert static_assert(is_disjoint_from(None, Literal[True])) @@ -245,6 +245,7 @@ static_assert(not is_disjoint_from(TypeOf[f], object)) ```py from knot_extensions import AlwaysFalsy, AlwaysTruthy, is_disjoint_from, static_assert +from typing import Literal static_assert(is_disjoint_from(None, AlwaysTruthy)) static_assert(not is_disjoint_from(None, AlwaysFalsy)) diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_gradual_equivalent_to.md b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_gradual_equivalent_to.md index 35b6b02340916..5dab6ebeab6a2 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_gradual_equivalent_to.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_gradual_equivalent_to.md @@ -54,6 +54,7 @@ static_assert(not is_gradual_equivalent_to(str | int | bytes, int | str | dict)) ```py from knot_extensions import Unknown, is_gradual_equivalent_to, static_assert +from typing import Any static_assert(is_gradual_equivalent_to(tuple[str, Any], tuple[str, Unknown])) diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_subtype_of.md b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_subtype_of.md index 4e081338d38bc..17c7f7dc13f8f 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_subtype_of.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_subtype_of.md @@ -148,6 +148,7 @@ static_assert(is_subtype_of(tuple[int], tuple)) ```py from knot_extensions import is_subtype_of, static_assert +from typing import Literal class A: ... class B1(A): ... @@ -271,6 +272,7 @@ static_assert(is_subtype_of(Never, AlwaysFalsy)) ```py from knot_extensions import AlwaysTruthy, AlwaysFalsy, is_subtype_of, static_assert +from typing import Literal static_assert(is_subtype_of(Literal[1], AlwaysTruthy)) static_assert(is_subtype_of(Literal[0], AlwaysFalsy)) @@ -309,7 +311,7 @@ static_assert(is_subtype_of(TypeOf[1:2:3], slice)) ### Special forms ```py -from typing import _SpecialForm +from typing import _SpecialForm, Literal from knot_extensions import TypeOf, is_subtype_of, static_assert static_assert(is_subtype_of(TypeOf[Literal], _SpecialForm)) diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_qualifiers/classvar.md b/crates/red_knot_python_semantic/resources/mdtest/type_qualifiers/classvar.md index 26060e685d3bb..a3e73e971aef4 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_qualifiers/classvar.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_qualifiers/classvar.md @@ -67,6 +67,8 @@ c.a = 2 ## Too many arguments ```py +from typing import ClassVar + class C: # error: [invalid-type-form] "Type qualifier `typing.ClassVar` expects exactly one type parameter" x: ClassVar[int, str] = 1 @@ -75,6 +77,8 @@ class C: ## Illegal `ClassVar` in type expression ```py +from typing import ClassVar + class C: # error: [invalid-type-form] "Type qualifier `typing.ClassVar` is not allowed in type expressions (only in annotation expressions)" x: ClassVar | int @@ -86,6 +90,8 @@ class C: ## Used outside of a class ```py +from typing import ClassVar + # TODO: this should be an error x: ClassVar[int] = 1 ``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/unary/not.md b/crates/red_knot_python_semantic/resources/mdtest/unary/not.md index b35783be799a9..8153ffeacf13d 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/unary/not.md +++ b/crates/red_knot_python_semantic/resources/mdtest/unary/not.md @@ -123,6 +123,8 @@ classes without a `__bool__` method, with or without `__len__`, must be inferred truthiness. ```py +from typing import Literal + class AlwaysTrue: def __bool__(self) -> Literal[True]: return True diff --git a/crates/red_knot_python_semantic/resources/mdtest/unpacking.md b/crates/red_knot_python_semantic/resources/mdtest/unpacking.md index 3b41f794cf53e..236ee664eb25d 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/unpacking.md +++ b/crates/red_knot_python_semantic/resources/mdtest/unpacking.md @@ -361,6 +361,8 @@ def _(arg: tuple[int, int, int] | tuple[int, str, bytes] | tuple[int, int, str]) ### Nested ```py +from typing import Literal + def _(arg: tuple[int, tuple[str, bytes]] | tuple[tuple[int, bytes], Literal["ab"]]): a, (b, c) = arg reveal_type(a) # revealed: int | tuple[int, bytes] diff --git a/crates/red_knot_python_semantic/resources/mdtest/with/sync.md b/crates/red_knot_python_semantic/resources/mdtest/with/sync.md index 48ea3c2c41a62..6d19288ed5a1c 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/with/sync.md +++ b/crates/red_knot_python_semantic/resources/mdtest/with/sync.md @@ -88,6 +88,8 @@ with Manager(): ## Context manager with non-callable `__exit__` attribute ```py +from typing_extensions import Self + class Manager: def __enter__(self) -> Self: ...