Skip to content

Commit

Permalink
[red-knot] Add missing imports in mdtests (#15869)
Browse files Browse the repository at this point in the history
## Summary

Related to #15848, this PR adds the imports explicitly as we'll now flag
these symbols as undefined.

---------

Co-authored-by: Alex Waygood <[email protected]>
  • Loading branch information
dhruvmanila and AlexWaygood authored Feb 3, 2025
1 parent 30d5e9a commit d082c1b
Show file tree
Hide file tree
Showing 21 changed files with 71 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## Class instances

```py
from typing import Literal

class Yes:
def __add__(self, other) -> Literal["+"]:
return "+"
Expand Down Expand Up @@ -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 "+"
Expand Down Expand Up @@ -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 "+"
Expand All @@ -312,6 +318,8 @@ reveal_type(No + No) # revealed: Unknown
## Subclass

```py
from typing import Literal

class Yes:
def __add__(self, other) -> Literal["+"]:
return "+"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand Down
10 changes: 10 additions & 0 deletions crates/red_knot_python_semantic/resources/mdtest/mdtest_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
```

Expand All @@ -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]
```

Expand All @@ -38,6 +42,8 @@ python-version = "3.11"
```

```py
import sys

reveal_type(sys.version_info[:2] == (3, 11)) # revealed: Literal[True]
```

Expand All @@ -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]
```

Expand All @@ -63,5 +71,7 @@ python-version = "3.12"
### Grandchild

```py
import sys

reveal_type(sys.version_info[:2] == (3, 12)) # revealed: Literal[True]
```
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -149,6 +153,8 @@ else:
## Narrowing Complex Intersection and Union

```py
from typing import Literal

class A: ...
class B: ...

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -222,6 +230,8 @@ reveal_type(y) # revealed: A
## Truthiness of classes

```py
from typing import Literal

class MetaAmbiguous(type):
def __bool__(self) -> bool: ...

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: ...

Expand Down
6 changes: 5 additions & 1 deletion crates/red_knot_python_semantic/resources/mdtest/type_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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: ...
Expand Down Expand Up @@ -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))
Expand All @@ -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]))
Expand All @@ -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]))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<object.__repr__ type> & Any`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down Expand Up @@ -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]))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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): ...
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
```
Expand Down
2 changes: 2 additions & 0 deletions crates/red_knot_python_semantic/resources/mdtest/unary/not.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions crates/red_knot_python_semantic/resources/mdtest/unpacking.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 2 additions & 0 deletions crates/red_knot_python_semantic/resources/mdtest/with/sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: ...

Expand Down

0 comments on commit d082c1b

Please sign in to comment.