[red-knot] Format mdtest Python snippets more concisely (#13905)

This commit is contained in:
Alex Waygood 2024-10-24 12:09:31 +01:00 committed by GitHub
parent 77ae0ccf0f
commit 3eb454699a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 4 additions and 193 deletions

View file

@ -15,13 +15,11 @@ Name lookups within a class scope fall back to globals, but lookups of class att
```py
x = 1
class C:
y = x
if flag:
x = 2
reveal_type(C.x) # revealed: Literal[2]
reveal_type(C.y) # revealed: Literal[1]
```

View file

@ -4,15 +4,12 @@
```py
if flag:
class C:
x = 1
else:
class C:
x = 2
reveal_type(C.x) # revealed: Literal[1, 2]
```

View file

@ -53,10 +53,8 @@ class A:
def __or__(self, other) -> A:
return self
class B: ...
reveal_type(A() + B()) # revealed: A
reveal_type(A() - B()) # revealed: A
reveal_type(A() * B()) # revealed: A
@ -117,10 +115,8 @@ class A:
def __ror__(self, other) -> A:
return self
class B: ...
reveal_type(B() + A()) # revealed: A
reveal_type(B() - A()) # revealed: A
reveal_type(B() * A()) # revealed: A
@ -148,10 +144,8 @@ class A:
def __rsub__(self, other) -> int:
return 1
class B: ...
reveal_type(A() + B()) # revealed: int
reveal_type(B() - A()) # revealed: int
```
@ -167,15 +161,12 @@ class A:
def __add__(self, other: B) -> int:
return 42
class B:
def __radd__(self, other: A) -> str:
return "foo"
reveal_type(A() + B()) # revealed: int
# Edge case: C is a subtype of C, *but* if the two sides are of *equal* types,
# the lhs *still* takes precedence
class C:
@ -185,7 +176,6 @@ class C:
def __radd__(self, other: C) -> str:
return "foo"
reveal_type(C() + C()) # revealed: int
```
@ -203,22 +193,17 @@ class A:
def __radd__(self, other) -> str:
return "foo"
class MyString(str): ...
class B(A):
def __radd__(self, other) -> MyString:
return MyString()
reveal_type(A() + B()) # revealed: MyString
# N.B. Still a subtype of `A`, even though `A` does not appear directly in the class's `__bases__`
class C(B): ...
# TODO: we currently only understand direct subclasses as subtypes of the superclass.
# We need to iterate through the full MRO rather than just the class's bases;
# if we do, we'll understand `C` as a subtype of `A`, and correctly understand this as being
@ -240,10 +225,8 @@ class A:
def __radd__(self, other) -> int:
return 42
class B(A): ...
reveal_type(A() + B()) # revealed: str
```
@ -266,12 +249,10 @@ class A:
def __sub__(self, other: A) -> A:
return A()
class B:
def __rsub__(self, other: A) -> B:
return B()
# TODO: this should be `B` (the return annotation of `B.__rsub__`),
# because `A.__sub__` is annotated as only accepting `A`,
# but `B.__rsub__` will accept `A`.
@ -287,11 +268,9 @@ class A:
def __call__(self, other) -> int:
return 42
class B:
__add__ = A()
reveal_type(B() + B()) # revealed: int
```
@ -311,15 +290,12 @@ reveal_type(42 + 4.2) # revealed: int
# TODO should be complex, need to check arg type and fall back to `rhs.__radd__`
reveal_type(3 + 3j) # revealed: int
def returns_int() -> int:
return 42
def returns_bool() -> bool:
return True
x = returns_bool()
y = returns_int()
@ -343,7 +319,6 @@ class A:
def __radd__(self, other) -> A:
return self
reveal_type(A() + 1) # revealed: A
# TODO should be `A` since `int.__add__` doesn't support `A` instances
reveal_type(1 + A()) # revealed: int
@ -388,15 +363,12 @@ from does_not_exist import Foo # error: [unresolved-import]
reveal_type(Foo) # revealed: Unknown
class X:
def __add__(self, other: object) -> int:
return 42
class Y(Foo): ...
# TODO: Should be `int | Unknown`; see above discussion.
reveal_type(X() + Y()) # revealed: int
```
@ -411,12 +383,10 @@ The magic method must exist on the class, not just on the instance:
def add_impl(self, other) -> int:
return 1
class A:
def __init__(self):
self.__add__ = add_impl
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `A` and `A`"
# revealed: Unknown
reveal_type(A() + A())
@ -427,7 +397,6 @@ reveal_type(A() + A())
```py
class A: ...
# error: [unsupported-operator]
# revealed: Unknown
reveal_type(A() + A())
@ -441,14 +410,11 @@ A left-hand dunder method doesn't apply for the right-hand operand, or vice vers
class A:
def __add__(self, other) -> int: ...
class B:
def __radd__(self, other) -> int: ...
class C: ...
# error: [unsupported-operator]
# revealed: Unknown
reveal_type(C() + A())
@ -471,7 +437,6 @@ class Foo:
def __radd__(self, other: Foo) -> Foo:
return self
# error: [unsupported-operator]
# revealed: Unknown
reveal_type(Foo() + Foo())

View file

@ -62,10 +62,8 @@ bool(1) / False
# revealed: float
reveal_type(1.0 / 0)
class MyInt(int): ...
# No error for a subclass of int
# revealed: float
reveal_type(MyInt(3) / 0)

View file

@ -10,14 +10,11 @@ class Multiplier:
def __call__(self, number: float) -> float:
return number * self.factor
a = Multiplier(2.0)(3.0)
reveal_type(a) # revealed: float
class Unit: ...
b = Unit()(3.0) # error: "Object of type `Unit` is not callable"
reveal_type(b) # revealed: Unknown
```

View file

@ -3,6 +3,5 @@
```py
class Foo: ...
reveal_type(Foo()) # revealed: Foo
```

View file

@ -6,7 +6,6 @@
def get_int() -> int:
return 42
reveal_type(get_int()) # revealed: int
```
@ -16,7 +15,6 @@ reveal_type(get_int()) # revealed: int
async def get_int_async() -> int:
return 42
# TODO: we don't yet support `types.CoroutineType`, should be generic `Coroutine[Any, Any, int]`
reveal_type(get_int_async()) # revealed: @Todo
```
@ -26,20 +24,16 @@ reveal_type(get_int_async()) # revealed: @Todo
```py
from typing import Callable
def foo() -> int:
return 42
def decorator(func) -> Callable[[], int]:
return foo
@decorator
def bar() -> str:
return "bar"
# TODO: should reveal `int`, as the decorator replaces `bar` with `foo`
reveal_type(bar()) # revealed: @Todo
```

View file

@ -13,7 +13,6 @@ else:
def f() -> str:
return "foo"
reveal_type(f()) # revealed: int | str
```
@ -27,7 +26,6 @@ if flag:
def f() -> int:
return 1
reveal_type(f()) # revealed: Unknown | int
```
@ -43,7 +41,6 @@ else:
def f() -> int:
return 1
x = f() # error: "Object of type `Literal[1] | Literal[f]` is not callable (due to union element `Literal[1]`)"
reveal_type(x) # revealed: Unknown | int
```
@ -62,7 +59,6 @@ else:
def f() -> int:
return 1
# error: "Object of type `Literal[1] | Literal["foo"] | Literal[f]` is not callable (due to union elements Literal[1], Literal["foo"])"
# revealed: Unknown | int
reveal_type(f())

View file

@ -21,7 +21,6 @@ reveal_type(1 <= "" and 0 < 1) # revealed: @Todo | Literal[True]
# TODO: implement lookup of `__eq__` on typeshed `int` stub.
def int_instance() -> int: ...
reveal_type(1 == int_instance()) # revealed: @Todo
reveal_type(9 < int_instance()) # revealed: bool
reveal_type(int_instance() < int_instance()) # revealed: bool

View file

@ -21,15 +21,15 @@ Walking through examples:
```py
from __future__ import annotations
class A:
def __lt__(self, other) -> A: ...
class B:
def __lt__(self, other) -> B: ...
class C:
def __lt__(self, other) -> C: ...
x = A() < B() < C()
reveal_type(x) # revealed: A | B

View file

@ -5,7 +5,6 @@
```py
def str_instance() -> str: ...
reveal_type("abc" == "abc") # revealed: Literal[True]
reveal_type("ab_cd" <= "ab_ce") # revealed: Literal[True]
reveal_type("abc" in "ab cd") # revealed: Literal[False]

View file

@ -61,7 +61,6 @@ reveal_type(c >= d) # revealed: Literal[True]
def bool_instance() -> bool: ...
def int_instance() -> int: ...
a = (bool_instance(),)
b = (int_instance(),)
@ -144,7 +143,6 @@ class A:
def __gt__(self, o) -> tuple: ...
def __ge__(self, o) -> list: ...
a = (A(), A())
# TODO: All @Todo should be bool
@ -163,7 +161,6 @@ reveal_type(a >= a) # revealed: @Todo
```py
def int_instance() -> int: ...
a = (1, 2)
b = ((3, 4), (1, 2))
c = ((1, 2, 3), (4, 5, 6))

View file

@ -40,7 +40,6 @@ to the `except` suite *after* that redefinition.
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -63,7 +62,6 @@ unify and `x` is not inferred as having a union type following the
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -88,7 +86,6 @@ possibility when it comes to control-flow analysis.
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -119,7 +116,6 @@ the three suites:
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -153,7 +149,6 @@ the end of the `except` suite:
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -182,7 +177,6 @@ in their entireties:
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -216,7 +210,6 @@ therefore `Literal[2]`:
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -244,7 +237,6 @@ suites, however; this is still a TODO item for us.)
def could_raise_returns_str() -> str:
return "foo"
x = 1
try:
@ -277,15 +269,12 @@ following possibilities inside `finally` suites:
def could_raise_returns_str() -> str:
return "foo"
def could_raise_returns_bytes() -> bytes:
return b"foo"
def could_raise_returns_bool() -> bool:
return True
x = 1
try:
@ -318,15 +307,12 @@ conclusion of the `finally` suite.)
def could_raise_returns_str() -> str:
return "foo"
def could_raise_returns_bytes() -> bytes:
return b"foo"
def could_raise_returns_bool() -> bool:
return True
x = 1
try:
@ -352,23 +338,18 @@ An example with multiple `except` branches and a `finally` branch:
def could_raise_returns_str() -> str:
return "foo"
def could_raise_returns_bytes() -> bytes:
return b"foo"
def could_raise_returns_bool() -> bool:
return True
def could_raise_returns_memoryview() -> memoryview:
return memoryview(b"")
def could_raise_returns_float() -> float:
return 3.14
x = 1
try:
@ -404,23 +385,18 @@ partway through the `else` suite due to an exception raised *there*.
def could_raise_returns_str() -> str:
return "foo"
def could_raise_returns_bytes() -> bytes:
return b"foo"
def could_raise_returns_bool() -> bool:
return True
def could_raise_returns_memoryview() -> memoryview:
return memoryview(b"")
def could_raise_returns_float() -> float:
return 3.14
x = 1
try:
@ -452,31 +428,24 @@ The same again, this time with multiple `except` branches:
def could_raise_returns_str() -> str:
return "foo"
def could_raise_returns_bytes() -> bytes:
return b"foo"
def could_raise_returns_bool() -> bool:
return True
def could_raise_returns_memoryview() -> memoryview:
return memoryview(b"")
def could_raise_returns_float() -> float:
return 3.14
def could_raise_returns_range() -> range:
return range(42)
def could_raise_returns_slice() -> slice:
return slice(None)
x = 1
try:
@ -524,53 +493,39 @@ prior to the suite running to completion.
def could_raise_returns_str() -> str:
return "foo"
def could_raise_returns_bytes() -> bytes:
return b"foo"
def could_raise_returns_bool() -> bool:
return True
def could_raise_returns_memoryview() -> memoryview:
return memoryview(b"")
def could_raise_returns_float() -> float:
return 3.14
def could_raise_returns_range() -> range:
return range(42)
def could_raise_returns_slice() -> slice:
return slice(None)
def could_raise_returns_complex() -> complex:
return 3j
def could_raise_returns_bytearray() -> bytearray:
return bytearray()
class Foo: ...
class Bar: ...
def could_raise_returns_Foo() -> Foo:
return Foo()
def could_raise_returns_Bar() -> Bar:
return Bar()
x = 1
try:
@ -632,23 +587,18 @@ variable by that name in the outer scope:
def could_raise_returns_str() -> str:
return "foo"
def could_raise_returns_bytes() -> bytes:
return b"foo"
def could_raise_returns_range() -> range:
return range(42)
def could_raise_returns_bytearray() -> bytearray:
return bytearray()
def could_raise_returns_float() -> float:
return 3.14
x = 1
try:
@ -670,7 +620,6 @@ try:
# TODO: should be `str | bytes | bytearray | float`
reveal_type(x) # revealed: bytes | float
reveal_type(x) # revealed: bytes | float
x = foo
reveal_type(x) # revealed: Literal[foo]
except:

View file

@ -6,7 +6,6 @@
def foo() -> str:
pass
reveal_type(True or False) # revealed: Literal[True]
reveal_type("x" or "y" or "z") # revealed: Literal["x"]
reveal_type("" or "y" or "z") # revealed: Literal["y"]
@ -23,7 +22,6 @@ reveal_type(foo() or True) # revealed: str | Literal[True]
def foo() -> str:
pass
reveal_type(True and False) # revealed: Literal[False]
reveal_type(False and True) # revealed: Literal[False]
reveal_type(foo() and False) # revealed: str | Literal[False]
@ -39,7 +37,6 @@ reveal_type("" and "y") # revealed: Literal[""]
def returns_bool() -> bool:
return True
if returns_bool():
x = True
else:
@ -54,7 +51,6 @@ reveal_type(x) # revealed: bool
def foo() -> str:
pass
reveal_type("x" and "y" or "z") # revealed: Literal["y"]
reveal_type("x" or "y" and "z") # revealed: Literal["x"]
reveal_type("" and "y" or "z") # revealed: Literal["z"]
@ -70,7 +66,6 @@ reveal_type("x" or "y" and "") # revealed: Literal["x"]
```py path=a.py
redefined_builtin_bool = bool
def my_bool(x) -> bool:
return True
```
@ -90,10 +85,8 @@ reveal_type(bool((0,))) # revealed: Literal[True]
reveal_type(bool("NON EMPTY")) # revealed: Literal[True]
reveal_type(bool(True)) # revealed: Literal[True]
def foo(): ...
reveal_type(bool(foo)) # revealed: Literal[True]
```

View file

@ -12,7 +12,6 @@ class MyBox[T]:
def __init__(self, data: T):
self.data = data
# TODO not error (should be subscriptable)
box: MyBox[int] = MyBox(5) # error: [non-subscriptable]
# TODO error differently (str and int don't unify)
@ -32,11 +31,9 @@ class MyBox[T]:
def __init__(self, data: T):
self.data = data
# TODO not error on the subscripting
class MySecureBox[T](MyBox[T]): ... # error: [non-subscriptable]
secure_box: MySecureBox[int] = MySecureBox(5)
reveal_type(secure_box) # revealed: MySecureBox
# TODO reveal int
@ -52,10 +49,8 @@ This should hold true even with generics at play.
```py path=a.pyi
class Seq[T]: ...
# TODO not error on the subscripting
class S[T](Seq[S]): ... # error: [non-subscriptable]
reveal_type(S) # revealed: Literal[S]
```

View file

@ -7,12 +7,10 @@ class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
for x in IntIterable():
pass
@ -26,12 +24,10 @@ class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
x = "foo"
for x in IntIterable():
@ -47,12 +43,10 @@ class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
for x in IntIterable():
pass
else:
@ -68,12 +62,10 @@ class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
for x in IntIterable():
if x > 5:
break
@ -90,7 +82,6 @@ class OldStyleIterable:
def __getitem__(self, key: int) -> int:
return 42
for x in OldStyleIterable():
pass
@ -115,7 +106,6 @@ class NotIterable:
else:
__iter__ = None
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
pass
@ -136,10 +126,8 @@ for x in nonsense: # error: "Object of type `Literal[123]` is not iterable"
class NotIterable:
def __getitem__(self, key: int) -> int:
return 42
__iter__ = None
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
pass
```

View file

@ -5,16 +5,13 @@
```py
class NotIterable: ...
class Iterator:
def __next__(self) -> int:
return 42
class Iterable:
def __iter__(self) -> Iterator: ...
def generator_function():
yield from Iterable()
yield from NotIterable() # error: "Object of type `NotIterable` is not iterable"

View file

@ -16,7 +16,6 @@ reveal_type(x) # revealed: None | Literal[1]
```py
class A: ...
x = A()
y = x if flag else None

View file

@ -5,7 +5,6 @@
```py
def int_instance() -> int: ...
x = int_instance()
if x != 1:

View file

@ -31,11 +31,8 @@ if x != 1:
```py
class A: ...
class B: ...
C = A if flag else B
if C != A:
@ -49,7 +46,6 @@ Only single-valued types should narrow the type:
```py
def int_instance() -> int: ...
x = int_instance() if flag else None
y = int_instance()

View file

@ -66,14 +66,10 @@ if isinstance(x, (bool, (bytes, int))):
```py
class A: ...
class B: ...
def get_object() -> object: ...
x = get_object()
if isinstance(x, A):
@ -101,7 +97,6 @@ if isinstance(x, t):
def isinstance(x, t):
return True
x = 1 if flag else "a"
if isinstance(x, int):
reveal_type(x) # revealed: Literal[1] | Literal["a"]

View file

@ -9,11 +9,9 @@ with the conditionally-defined type:
def returns_bool() -> bool:
return True
if returns_bool():
copyright = 1
def f():
reveal_type(copyright) # revealed: Literal[copyright] | Literal[1]
```
@ -26,11 +24,9 @@ Same is true if the name is annotated:
def returns_bool() -> bool:
return True
if returns_bool():
copyright: int = 1
def f():
reveal_type(copyright) # revealed: Literal[copyright] | int
```

View file

@ -5,7 +5,6 @@
```py
class C: ...
C = 1 # error: "Implicit shadowing of class `C`; annotate to make it explicit if this is intentional"
```
@ -16,6 +15,5 @@ No diagnostic is raised in the case of explicit shadowing:
```py
class C: ...
C: int = 1
```

View file

@ -14,7 +14,6 @@ def f(x: str):
```py path=a.py
def f(): ...
f = 1 # error: "Implicit shadowing of function `f`; annotate to make it explicit if this is intentional"
```
@ -23,6 +22,5 @@ f = 1 # error: "Implicit shadowing of function `f`; annotate to make it explici
```py path=a.py
def f(): ...
f: int = 1
```

View file

@ -7,6 +7,5 @@ In type stubs, classes can reference themselves in their base class definitions.
```py path=a.pyi
class C(C): ...
reveal_type(C) # revealed: Literal[C]
```

View file

@ -28,7 +28,6 @@ reveal_type(y) # revealed: Unknown
```py
def int_instance() -> int: ...
a = b"abcde"[int_instance()]
# TODO: Support overloads... Should be `bytes`
reveal_type(a) # revealed: @Todo

View file

@ -5,7 +5,6 @@
```py
class NotSubscriptable: ...
a = NotSubscriptable[0] # error: "Cannot subscript object of type `Literal[NotSubscriptable]` with no `__class_getitem__` method"
```
@ -16,7 +15,6 @@ class Identity:
def __class_getitem__(cls, item: int) -> str:
return item
reveal_type(Identity[0]) # revealed: str
```
@ -25,19 +23,16 @@ reveal_type(Identity[0]) # revealed: str
```py
flag = True
class UnionClassGetItem:
if flag:
def __class_getitem__(cls, item: int) -> str:
return item
else:
def __class_getitem__(cls, item: int) -> int:
return item
reveal_type(UnionClassGetItem[0]) # revealed: str | int
```
@ -46,17 +41,14 @@ reveal_type(UnionClassGetItem[0]) # revealed: str | int
```py
flag = True
class A:
def __class_getitem__(cls, item: int) -> str:
return item
class B:
def __class_getitem__(cls, item: int) -> int:
return item
x = A if flag else B
reveal_type(x) # revealed: Literal[A, B]
@ -69,16 +61,13 @@ reveal_type(x[0]) # revealed: str | int
flag = True
if flag:
class Spam:
def __class_getitem__(self, x: int) -> str:
return "foo"
else:
class Spam: ...
# error: [call-non-callable] "Method `__class_getitem__` of type `Literal[__class_getitem__] | Unbound` is not callable on object of type `Literal[Spam, Spam]`"
# revealed: str | Unknown
reveal_type(Spam[42])
@ -90,7 +79,6 @@ reveal_type(Spam[42])
flag = True
if flag:
class Eggs:
def __class_getitem__(self, x: int) -> str:
return "foo"

View file

@ -5,7 +5,6 @@
```py
class NotSubscriptable: ...
a = NotSubscriptable()[0] # error: "Cannot subscript object of type `NotSubscriptable` with no `__getitem__` method"
```
@ -15,7 +14,6 @@ a = NotSubscriptable()[0] # error: "Cannot subscript object of type `NotSubscri
class NotSubscriptable:
__getitem__ = None
a = NotSubscriptable()[0] # error: "Method `__getitem__` of type `None` is not callable on object of type `NotSubscriptable`"
```
@ -26,7 +24,6 @@ class Identity:
def __getitem__(self, index: int) -> int:
return index
reveal_type(Identity()[0]) # revealed: int
```
@ -35,18 +32,15 @@ reveal_type(Identity()[0]) # revealed: int
```py
flag = True
class Identity:
if flag:
def __getitem__(self, index: int) -> int:
return index
else:
def __getitem__(self, index: int) -> str:
return str(index)
reveal_type(Identity()[0]) # revealed: int | str
```

View file

@ -25,7 +25,6 @@ reveal_type(b) # revealed: Unknown
```py
def int_instance() -> int: ...
a = "abcde"[int_instance()]
# TODO: Support overloads... Should be `str`
reveal_type(a) # revealed: @Todo

View file

@ -14,17 +14,14 @@ class Number:
def __invert__(self) -> Literal[True]:
return True
a = Number()
reveal_type(+a) # revealed: int
reveal_type(-a) # revealed: int
reveal_type(~a) # revealed: @Todo
class NoDunder: ...
b = NoDunder()
+b # error: [unsupported-operator] "Unary operator `+` is unsupported for type `NoDunder`"
-b # error: [unsupported-operator] "Unary operator `-` is unsupported for type `NoDunder`"

View file

@ -12,11 +12,9 @@ reveal_type(not not None) # revealed: Literal[False]
```py
from typing import reveal_type
def f():
return 1
reveal_type(not f) # revealed: Literal[False]
# TODO Unknown should not be part of the type of typing.reveal_type
# reveal_type(not reveal_type) revealed: Literal[False]
@ -28,7 +26,6 @@ reveal_type(not f) # revealed: Literal[False]
import b
import warnings
reveal_type(not b) # revealed: Literal[False]
reveal_type(not warnings) # revealed: Literal[False]
```

View file

@ -155,12 +155,10 @@ class Iterator:
def __next__(self) -> int:
return 42
class Iterable:
def __iter__(self) -> Iterator:
return Iterator()
(a, b) = Iterable()
reveal_type(a) # revealed: int
reveal_type(b) # revealed: int
@ -173,12 +171,10 @@ class Iterator:
def __next__(self) -> int:
return 42
class Iterable:
def __iter__(self) -> Iterator:
return Iterator()
(a, (b, c), d) = (1, Iterable(), 2)
reveal_type(a) # revealed: Literal[1]
reveal_type(b) # revealed: int