mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 07:04:37 +00:00
[red-knot] Format mdtest Python snippets more concisely (#13905)
This commit is contained in:
parent
77ae0ccf0f
commit
3eb454699a
33 changed files with 4 additions and 193 deletions
|
@ -46,10 +46,10 @@ repos:
|
||||||
)$
|
)$
|
||||||
|
|
||||||
- repo: https://github.com/adamchainz/blacken-docs
|
- repo: https://github.com/adamchainz/blacken-docs
|
||||||
rev: 1.19.0
|
rev: 1.19.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: blacken-docs
|
- id: blacken-docs
|
||||||
args: ["--line-length", "130"]
|
args: ["--pyi", "--line-length", "130"]
|
||||||
files: '^crates/.*/resources/mdtest/.*\.md'
|
files: '^crates/.*/resources/mdtest/.*\.md'
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- black==24.10.0
|
- black==24.10.0
|
||||||
|
|
|
@ -15,13 +15,11 @@ Name lookups within a class scope fall back to globals, but lookups of class att
|
||||||
```py
|
```py
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
y = x
|
y = x
|
||||||
if flag:
|
if flag:
|
||||||
x = 2
|
x = 2
|
||||||
|
|
||||||
|
|
||||||
reveal_type(C.x) # revealed: Literal[2]
|
reveal_type(C.x) # revealed: Literal[2]
|
||||||
reveal_type(C.y) # revealed: Literal[1]
|
reveal_type(C.y) # revealed: Literal[1]
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,15 +4,12 @@
|
||||||
|
|
||||||
```py
|
```py
|
||||||
if flag:
|
if flag:
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
x = 2
|
x = 2
|
||||||
|
|
||||||
|
|
||||||
reveal_type(C.x) # revealed: Literal[1, 2]
|
reveal_type(C.x) # revealed: Literal[1, 2]
|
||||||
```
|
```
|
||||||
|
|
|
@ -53,10 +53,8 @@ class A:
|
||||||
def __or__(self, other) -> A:
|
def __or__(self, other) -> A:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class B: ...
|
class B: ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(A() + B()) # revealed: A
|
reveal_type(A() + B()) # revealed: A
|
||||||
reveal_type(A() - B()) # revealed: A
|
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:
|
def __ror__(self, other) -> A:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class B: ...
|
class B: ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(B() + A()) # revealed: A
|
reveal_type(B() + A()) # revealed: A
|
||||||
reveal_type(B() - A()) # revealed: A
|
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:
|
def __rsub__(self, other) -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class B: ...
|
class B: ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(A() + B()) # revealed: int
|
reveal_type(A() + B()) # revealed: int
|
||||||
reveal_type(B() - A()) # revealed: int
|
reveal_type(B() - A()) # revealed: int
|
||||||
```
|
```
|
||||||
|
@ -167,15 +161,12 @@ class A:
|
||||||
def __add__(self, other: B) -> int:
|
def __add__(self, other: B) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class B:
|
class B:
|
||||||
def __radd__(self, other: A) -> str:
|
def __radd__(self, other: A) -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
reveal_type(A() + B()) # revealed: int
|
reveal_type(A() + B()) # revealed: int
|
||||||
|
|
||||||
|
|
||||||
# Edge case: C is a subtype of C, *but* if the two sides are of *equal* types,
|
# Edge case: C is a subtype of C, *but* if the two sides are of *equal* types,
|
||||||
# the lhs *still* takes precedence
|
# the lhs *still* takes precedence
|
||||||
class C:
|
class C:
|
||||||
|
@ -185,7 +176,6 @@ class C:
|
||||||
def __radd__(self, other: C) -> str:
|
def __radd__(self, other: C) -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
reveal_type(C() + C()) # revealed: int
|
reveal_type(C() + C()) # revealed: int
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -203,22 +193,17 @@ class A:
|
||||||
def __radd__(self, other) -> str:
|
def __radd__(self, other) -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
class MyString(str): ...
|
class MyString(str): ...
|
||||||
|
|
||||||
|
|
||||||
class B(A):
|
class B(A):
|
||||||
def __radd__(self, other) -> MyString:
|
def __radd__(self, other) -> MyString:
|
||||||
return MyString()
|
return MyString()
|
||||||
|
|
||||||
|
|
||||||
reveal_type(A() + B()) # revealed: 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__`
|
# N.B. Still a subtype of `A`, even though `A` does not appear directly in the class's `__bases__`
|
||||||
class C(B): ...
|
class C(B): ...
|
||||||
|
|
||||||
|
|
||||||
# TODO: we currently only understand direct subclasses as subtypes of the superclass.
|
# 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;
|
# 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
|
# 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:
|
def __radd__(self, other) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class B(A): ...
|
class B(A): ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(A() + B()) # revealed: str
|
reveal_type(A() + B()) # revealed: str
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -266,12 +249,10 @@ class A:
|
||||||
def __sub__(self, other: A) -> A:
|
def __sub__(self, other: A) -> A:
|
||||||
return A()
|
return A()
|
||||||
|
|
||||||
|
|
||||||
class B:
|
class B:
|
||||||
def __rsub__(self, other: A) -> B:
|
def __rsub__(self, other: A) -> B:
|
||||||
return B()
|
return B()
|
||||||
|
|
||||||
|
|
||||||
# TODO: this should be `B` (the return annotation of `B.__rsub__`),
|
# TODO: this should be `B` (the return annotation of `B.__rsub__`),
|
||||||
# because `A.__sub__` is annotated as only accepting `A`,
|
# because `A.__sub__` is annotated as only accepting `A`,
|
||||||
# but `B.__rsub__` will accept `A`.
|
# but `B.__rsub__` will accept `A`.
|
||||||
|
@ -287,11 +268,9 @@ class A:
|
||||||
def __call__(self, other) -> int:
|
def __call__(self, other) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class B:
|
class B:
|
||||||
__add__ = A()
|
__add__ = A()
|
||||||
|
|
||||||
|
|
||||||
reveal_type(B() + B()) # revealed: int
|
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__`
|
# TODO should be complex, need to check arg type and fall back to `rhs.__radd__`
|
||||||
reveal_type(3 + 3j) # revealed: int
|
reveal_type(3 + 3j) # revealed: int
|
||||||
|
|
||||||
|
|
||||||
def returns_int() -> int:
|
def returns_int() -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
def returns_bool() -> bool:
|
def returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
x = returns_bool()
|
x = returns_bool()
|
||||||
y = returns_int()
|
y = returns_int()
|
||||||
|
|
||||||
|
@ -343,7 +319,6 @@ class A:
|
||||||
def __radd__(self, other) -> A:
|
def __radd__(self, other) -> A:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
reveal_type(A() + 1) # revealed: A
|
reveal_type(A() + 1) # revealed: A
|
||||||
# TODO should be `A` since `int.__add__` doesn't support `A` instances
|
# TODO should be `A` since `int.__add__` doesn't support `A` instances
|
||||||
reveal_type(1 + A()) # revealed: int
|
reveal_type(1 + A()) # revealed: int
|
||||||
|
@ -388,15 +363,12 @@ from does_not_exist import Foo # error: [unresolved-import]
|
||||||
|
|
||||||
reveal_type(Foo) # revealed: Unknown
|
reveal_type(Foo) # revealed: Unknown
|
||||||
|
|
||||||
|
|
||||||
class X:
|
class X:
|
||||||
def __add__(self, other: object) -> int:
|
def __add__(self, other: object) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class Y(Foo): ...
|
class Y(Foo): ...
|
||||||
|
|
||||||
|
|
||||||
# TODO: Should be `int | Unknown`; see above discussion.
|
# TODO: Should be `int | Unknown`; see above discussion.
|
||||||
reveal_type(X() + Y()) # revealed: int
|
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:
|
def add_impl(self, other) -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class A:
|
class A:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__add__ = add_impl
|
self.__add__ = add_impl
|
||||||
|
|
||||||
|
|
||||||
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `A` and `A`"
|
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `A` and `A`"
|
||||||
# revealed: Unknown
|
# revealed: Unknown
|
||||||
reveal_type(A() + A())
|
reveal_type(A() + A())
|
||||||
|
@ -427,7 +397,6 @@ reveal_type(A() + A())
|
||||||
```py
|
```py
|
||||||
class A: ...
|
class A: ...
|
||||||
|
|
||||||
|
|
||||||
# error: [unsupported-operator]
|
# error: [unsupported-operator]
|
||||||
# revealed: Unknown
|
# revealed: Unknown
|
||||||
reveal_type(A() + A())
|
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:
|
class A:
|
||||||
def __add__(self, other) -> int: ...
|
def __add__(self, other) -> int: ...
|
||||||
|
|
||||||
|
|
||||||
class B:
|
class B:
|
||||||
def __radd__(self, other) -> int: ...
|
def __radd__(self, other) -> int: ...
|
||||||
|
|
||||||
|
|
||||||
class C: ...
|
class C: ...
|
||||||
|
|
||||||
|
|
||||||
# error: [unsupported-operator]
|
# error: [unsupported-operator]
|
||||||
# revealed: Unknown
|
# revealed: Unknown
|
||||||
reveal_type(C() + A())
|
reveal_type(C() + A())
|
||||||
|
@ -471,7 +437,6 @@ class Foo:
|
||||||
def __radd__(self, other: Foo) -> Foo:
|
def __radd__(self, other: Foo) -> Foo:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
# error: [unsupported-operator]
|
# error: [unsupported-operator]
|
||||||
# revealed: Unknown
|
# revealed: Unknown
|
||||||
reveal_type(Foo() + Foo())
|
reveal_type(Foo() + Foo())
|
||||||
|
|
|
@ -62,10 +62,8 @@ bool(1) / False
|
||||||
# revealed: float
|
# revealed: float
|
||||||
reveal_type(1.0 / 0)
|
reveal_type(1.0 / 0)
|
||||||
|
|
||||||
|
|
||||||
class MyInt(int): ...
|
class MyInt(int): ...
|
||||||
|
|
||||||
|
|
||||||
# No error for a subclass of int
|
# No error for a subclass of int
|
||||||
# revealed: float
|
# revealed: float
|
||||||
reveal_type(MyInt(3) / 0)
|
reveal_type(MyInt(3) / 0)
|
||||||
|
|
|
@ -10,14 +10,11 @@ class Multiplier:
|
||||||
def __call__(self, number: float) -> float:
|
def __call__(self, number: float) -> float:
|
||||||
return number * self.factor
|
return number * self.factor
|
||||||
|
|
||||||
|
|
||||||
a = Multiplier(2.0)(3.0)
|
a = Multiplier(2.0)(3.0)
|
||||||
reveal_type(a) # revealed: float
|
reveal_type(a) # revealed: float
|
||||||
|
|
||||||
|
|
||||||
class Unit: ...
|
class Unit: ...
|
||||||
|
|
||||||
|
|
||||||
b = Unit()(3.0) # error: "Object of type `Unit` is not callable"
|
b = Unit()(3.0) # error: "Object of type `Unit` is not callable"
|
||||||
reveal_type(b) # revealed: Unknown
|
reveal_type(b) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,6 +3,5 @@
|
||||||
```py
|
```py
|
||||||
class Foo: ...
|
class Foo: ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(Foo()) # revealed: Foo
|
reveal_type(Foo()) # revealed: Foo
|
||||||
```
|
```
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
def get_int() -> int:
|
def get_int() -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
reveal_type(get_int()) # revealed: int
|
reveal_type(get_int()) # revealed: int
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ reveal_type(get_int()) # revealed: int
|
||||||
async def get_int_async() -> int:
|
async def get_int_async() -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
# TODO: we don't yet support `types.CoroutineType`, should be generic `Coroutine[Any, Any, int]`
|
# TODO: we don't yet support `types.CoroutineType`, should be generic `Coroutine[Any, Any, int]`
|
||||||
reveal_type(get_int_async()) # revealed: @Todo
|
reveal_type(get_int_async()) # revealed: @Todo
|
||||||
```
|
```
|
||||||
|
@ -26,20 +24,16 @@ reveal_type(get_int_async()) # revealed: @Todo
|
||||||
```py
|
```py
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
def foo() -> int:
|
def foo() -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
def decorator(func) -> Callable[[], int]:
|
def decorator(func) -> Callable[[], int]:
|
||||||
return foo
|
return foo
|
||||||
|
|
||||||
|
|
||||||
@decorator
|
@decorator
|
||||||
def bar() -> str:
|
def bar() -> str:
|
||||||
return "bar"
|
return "bar"
|
||||||
|
|
||||||
|
|
||||||
# TODO: should reveal `int`, as the decorator replaces `bar` with `foo`
|
# TODO: should reveal `int`, as the decorator replaces `bar` with `foo`
|
||||||
reveal_type(bar()) # revealed: @Todo
|
reveal_type(bar()) # revealed: @Todo
|
||||||
```
|
```
|
||||||
|
|
|
@ -13,7 +13,6 @@ else:
|
||||||
def f() -> str:
|
def f() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
reveal_type(f()) # revealed: int | str
|
reveal_type(f()) # revealed: int | str
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -27,7 +26,6 @@ if flag:
|
||||||
def f() -> int:
|
def f() -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
reveal_type(f()) # revealed: Unknown | int
|
reveal_type(f()) # revealed: Unknown | int
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -43,7 +41,6 @@ else:
|
||||||
def f() -> int:
|
def f() -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
x = f() # error: "Object of type `Literal[1] | Literal[f]` is not callable (due to union element `Literal[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
|
reveal_type(x) # revealed: Unknown | int
|
||||||
```
|
```
|
||||||
|
@ -62,7 +59,6 @@ else:
|
||||||
def f() -> int:
|
def f() -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
# error: "Object of type `Literal[1] | Literal["foo"] | Literal[f]` is not callable (due to union elements Literal[1], Literal["foo"])"
|
# error: "Object of type `Literal[1] | Literal["foo"] | Literal[f]` is not callable (due to union elements Literal[1], Literal["foo"])"
|
||||||
# revealed: Unknown | int
|
# revealed: Unknown | int
|
||||||
reveal_type(f())
|
reveal_type(f())
|
||||||
|
|
|
@ -21,7 +21,6 @@ reveal_type(1 <= "" and 0 < 1) # revealed: @Todo | Literal[True]
|
||||||
# TODO: implement lookup of `__eq__` on typeshed `int` stub.
|
# TODO: implement lookup of `__eq__` on typeshed `int` stub.
|
||||||
def int_instance() -> int: ...
|
def int_instance() -> int: ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(1 == int_instance()) # revealed: @Todo
|
reveal_type(1 == int_instance()) # revealed: @Todo
|
||||||
reveal_type(9 < int_instance()) # revealed: bool
|
reveal_type(9 < int_instance()) # revealed: bool
|
||||||
reveal_type(int_instance() < int_instance()) # revealed: bool
|
reveal_type(int_instance() < int_instance()) # revealed: bool
|
||||||
|
|
|
@ -21,15 +21,15 @@ Walking through examples:
|
||||||
```py
|
```py
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
class A:
|
class A:
|
||||||
def __lt__(self, other) -> A: ...
|
def __lt__(self, other) -> A: ...
|
||||||
|
|
||||||
class B:
|
class B:
|
||||||
def __lt__(self, other) -> B: ...
|
def __lt__(self, other) -> B: ...
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
def __lt__(self, other) -> C: ...
|
def __lt__(self, other) -> C: ...
|
||||||
|
|
||||||
|
|
||||||
x = A() < B() < C()
|
x = A() < B() < C()
|
||||||
reveal_type(x) # revealed: A | B
|
reveal_type(x) # revealed: A | B
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
```py
|
```py
|
||||||
def str_instance() -> str: ...
|
def str_instance() -> str: ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type("abc" == "abc") # revealed: Literal[True]
|
reveal_type("abc" == "abc") # revealed: Literal[True]
|
||||||
reveal_type("ab_cd" <= "ab_ce") # revealed: Literal[True]
|
reveal_type("ab_cd" <= "ab_ce") # revealed: Literal[True]
|
||||||
reveal_type("abc" in "ab cd") # revealed: Literal[False]
|
reveal_type("abc" in "ab cd") # revealed: Literal[False]
|
||||||
|
|
|
@ -61,7 +61,6 @@ reveal_type(c >= d) # revealed: Literal[True]
|
||||||
def bool_instance() -> bool: ...
|
def bool_instance() -> bool: ...
|
||||||
def int_instance() -> int: ...
|
def int_instance() -> int: ...
|
||||||
|
|
||||||
|
|
||||||
a = (bool_instance(),)
|
a = (bool_instance(),)
|
||||||
b = (int_instance(),)
|
b = (int_instance(),)
|
||||||
|
|
||||||
|
@ -144,7 +143,6 @@ class A:
|
||||||
def __gt__(self, o) -> tuple: ...
|
def __gt__(self, o) -> tuple: ...
|
||||||
def __ge__(self, o) -> list: ...
|
def __ge__(self, o) -> list: ...
|
||||||
|
|
||||||
|
|
||||||
a = (A(), A())
|
a = (A(), A())
|
||||||
|
|
||||||
# TODO: All @Todo should be bool
|
# TODO: All @Todo should be bool
|
||||||
|
@ -163,7 +161,6 @@ reveal_type(a >= a) # revealed: @Todo
|
||||||
```py
|
```py
|
||||||
def int_instance() -> int: ...
|
def int_instance() -> int: ...
|
||||||
|
|
||||||
|
|
||||||
a = (1, 2)
|
a = (1, 2)
|
||||||
b = ((3, 4), (1, 2))
|
b = ((3, 4), (1, 2))
|
||||||
c = ((1, 2, 3), (4, 5, 6))
|
c = ((1, 2, 3), (4, 5, 6))
|
||||||
|
|
|
@ -40,7 +40,6 @@ to the `except` suite *after* that redefinition.
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -63,7 +62,6 @@ unify and `x` is not inferred as having a union type following the
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -88,7 +86,6 @@ possibility when it comes to control-flow analysis.
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -119,7 +116,6 @@ the three suites:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -153,7 +149,6 @@ the end of the `except` suite:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -182,7 +177,6 @@ in their entireties:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -216,7 +210,6 @@ therefore `Literal[2]`:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -244,7 +237,6 @@ suites, however; this is still a TODO item for us.)
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -277,15 +269,12 @@ following possibilities inside `finally` suites:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytes() -> bytes:
|
def could_raise_returns_bytes() -> bytes:
|
||||||
return b"foo"
|
return b"foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bool() -> bool:
|
def could_raise_returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -318,15 +307,12 @@ conclusion of the `finally` suite.)
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytes() -> bytes:
|
def could_raise_returns_bytes() -> bytes:
|
||||||
return b"foo"
|
return b"foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bool() -> bool:
|
def could_raise_returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -352,23 +338,18 @@ An example with multiple `except` branches and a `finally` branch:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytes() -> bytes:
|
def could_raise_returns_bytes() -> bytes:
|
||||||
return b"foo"
|
return b"foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bool() -> bool:
|
def could_raise_returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_memoryview() -> memoryview:
|
def could_raise_returns_memoryview() -> memoryview:
|
||||||
return memoryview(b"")
|
return memoryview(b"")
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_float() -> float:
|
def could_raise_returns_float() -> float:
|
||||||
return 3.14
|
return 3.14
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -404,23 +385,18 @@ partway through the `else` suite due to an exception raised *there*.
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytes() -> bytes:
|
def could_raise_returns_bytes() -> bytes:
|
||||||
return b"foo"
|
return b"foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bool() -> bool:
|
def could_raise_returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_memoryview() -> memoryview:
|
def could_raise_returns_memoryview() -> memoryview:
|
||||||
return memoryview(b"")
|
return memoryview(b"")
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_float() -> float:
|
def could_raise_returns_float() -> float:
|
||||||
return 3.14
|
return 3.14
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -452,31 +428,24 @@ The same again, this time with multiple `except` branches:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytes() -> bytes:
|
def could_raise_returns_bytes() -> bytes:
|
||||||
return b"foo"
|
return b"foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bool() -> bool:
|
def could_raise_returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_memoryview() -> memoryview:
|
def could_raise_returns_memoryview() -> memoryview:
|
||||||
return memoryview(b"")
|
return memoryview(b"")
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_float() -> float:
|
def could_raise_returns_float() -> float:
|
||||||
return 3.14
|
return 3.14
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_range() -> range:
|
def could_raise_returns_range() -> range:
|
||||||
return range(42)
|
return range(42)
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_slice() -> slice:
|
def could_raise_returns_slice() -> slice:
|
||||||
return slice(None)
|
return slice(None)
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -524,53 +493,39 @@ prior to the suite running to completion.
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytes() -> bytes:
|
def could_raise_returns_bytes() -> bytes:
|
||||||
return b"foo"
|
return b"foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bool() -> bool:
|
def could_raise_returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_memoryview() -> memoryview:
|
def could_raise_returns_memoryview() -> memoryview:
|
||||||
return memoryview(b"")
|
return memoryview(b"")
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_float() -> float:
|
def could_raise_returns_float() -> float:
|
||||||
return 3.14
|
return 3.14
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_range() -> range:
|
def could_raise_returns_range() -> range:
|
||||||
return range(42)
|
return range(42)
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_slice() -> slice:
|
def could_raise_returns_slice() -> slice:
|
||||||
return slice(None)
|
return slice(None)
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_complex() -> complex:
|
def could_raise_returns_complex() -> complex:
|
||||||
return 3j
|
return 3j
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytearray() -> bytearray:
|
def could_raise_returns_bytearray() -> bytearray:
|
||||||
return bytearray()
|
return bytearray()
|
||||||
|
|
||||||
|
|
||||||
class Foo: ...
|
class Foo: ...
|
||||||
|
|
||||||
|
|
||||||
class Bar: ...
|
class Bar: ...
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_Foo() -> Foo:
|
def could_raise_returns_Foo() -> Foo:
|
||||||
return Foo()
|
return Foo()
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_Bar() -> Bar:
|
def could_raise_returns_Bar() -> Bar:
|
||||||
return Bar()
|
return Bar()
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -632,23 +587,18 @@ variable by that name in the outer scope:
|
||||||
def could_raise_returns_str() -> str:
|
def could_raise_returns_str() -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytes() -> bytes:
|
def could_raise_returns_bytes() -> bytes:
|
||||||
return b"foo"
|
return b"foo"
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_range() -> range:
|
def could_raise_returns_range() -> range:
|
||||||
return range(42)
|
return range(42)
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_bytearray() -> bytearray:
|
def could_raise_returns_bytearray() -> bytearray:
|
||||||
return bytearray()
|
return bytearray()
|
||||||
|
|
||||||
|
|
||||||
def could_raise_returns_float() -> float:
|
def could_raise_returns_float() -> float:
|
||||||
return 3.14
|
return 3.14
|
||||||
|
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -670,7 +620,6 @@ try:
|
||||||
# TODO: should be `str | bytes | bytearray | float`
|
# TODO: should be `str | bytes | bytearray | float`
|
||||||
reveal_type(x) # revealed: bytes | float
|
reveal_type(x) # revealed: bytes | float
|
||||||
reveal_type(x) # revealed: bytes | float
|
reveal_type(x) # revealed: bytes | float
|
||||||
|
|
||||||
x = foo
|
x = foo
|
||||||
reveal_type(x) # revealed: Literal[foo]
|
reveal_type(x) # revealed: Literal[foo]
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
def foo() -> str:
|
def foo() -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
reveal_type(True or False) # revealed: Literal[True]
|
reveal_type(True or False) # revealed: Literal[True]
|
||||||
reveal_type("x" or "y" or "z") # revealed: Literal["x"]
|
reveal_type("x" or "y" or "z") # revealed: Literal["x"]
|
||||||
reveal_type("" or "y" or "z") # revealed: Literal["y"]
|
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:
|
def foo() -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
reveal_type(True and False) # revealed: Literal[False]
|
reveal_type(True and False) # revealed: Literal[False]
|
||||||
reveal_type(False and True) # revealed: Literal[False]
|
reveal_type(False and True) # revealed: Literal[False]
|
||||||
reveal_type(foo() and False) # revealed: str | 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:
|
def returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
if returns_bool():
|
if returns_bool():
|
||||||
x = True
|
x = True
|
||||||
else:
|
else:
|
||||||
|
@ -54,7 +51,6 @@ reveal_type(x) # revealed: bool
|
||||||
def foo() -> str:
|
def foo() -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
reveal_type("x" and "y" or "z") # revealed: Literal["y"]
|
reveal_type("x" and "y" or "z") # revealed: Literal["y"]
|
||||||
reveal_type("x" or "y" and "z") # revealed: Literal["x"]
|
reveal_type("x" or "y" and "z") # revealed: Literal["x"]
|
||||||
reveal_type("" and "y" or "z") # revealed: Literal["z"]
|
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
|
```py path=a.py
|
||||||
redefined_builtin_bool = bool
|
redefined_builtin_bool = bool
|
||||||
|
|
||||||
|
|
||||||
def my_bool(x) -> bool:
|
def my_bool(x) -> bool:
|
||||||
return True
|
return True
|
||||||
```
|
```
|
||||||
|
@ -90,10 +85,8 @@ reveal_type(bool((0,))) # revealed: Literal[True]
|
||||||
reveal_type(bool("NON EMPTY")) # revealed: Literal[True]
|
reveal_type(bool("NON EMPTY")) # revealed: Literal[True]
|
||||||
reveal_type(bool(True)) # revealed: Literal[True]
|
reveal_type(bool(True)) # revealed: Literal[True]
|
||||||
|
|
||||||
|
|
||||||
def foo(): ...
|
def foo(): ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(bool(foo)) # revealed: Literal[True]
|
reveal_type(bool(foo)) # revealed: Literal[True]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ class MyBox[T]:
|
||||||
def __init__(self, data: T):
|
def __init__(self, data: T):
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
||||||
|
|
||||||
# TODO not error (should be subscriptable)
|
# TODO not error (should be subscriptable)
|
||||||
box: MyBox[int] = MyBox(5) # error: [non-subscriptable]
|
box: MyBox[int] = MyBox(5) # error: [non-subscriptable]
|
||||||
# TODO error differently (str and int don't unify)
|
# TODO error differently (str and int don't unify)
|
||||||
|
@ -32,11 +31,9 @@ class MyBox[T]:
|
||||||
def __init__(self, data: T):
|
def __init__(self, data: T):
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
||||||
|
|
||||||
# TODO not error on the subscripting
|
# TODO not error on the subscripting
|
||||||
class MySecureBox[T](MyBox[T]): ... # error: [non-subscriptable]
|
class MySecureBox[T](MyBox[T]): ... # error: [non-subscriptable]
|
||||||
|
|
||||||
|
|
||||||
secure_box: MySecureBox[int] = MySecureBox(5)
|
secure_box: MySecureBox[int] = MySecureBox(5)
|
||||||
reveal_type(secure_box) # revealed: MySecureBox
|
reveal_type(secure_box) # revealed: MySecureBox
|
||||||
# TODO reveal int
|
# TODO reveal int
|
||||||
|
@ -52,10 +49,8 @@ This should hold true even with generics at play.
|
||||||
```py path=a.pyi
|
```py path=a.pyi
|
||||||
class Seq[T]: ...
|
class Seq[T]: ...
|
||||||
|
|
||||||
|
|
||||||
# TODO not error on the subscripting
|
# TODO not error on the subscripting
|
||||||
class S[T](Seq[S]): ... # error: [non-subscriptable]
|
class S[T](Seq[S]): ... # error: [non-subscriptable]
|
||||||
|
|
||||||
|
|
||||||
reveal_type(S) # revealed: Literal[S]
|
reveal_type(S) # revealed: Literal[S]
|
||||||
```
|
```
|
||||||
|
|
|
@ -7,12 +7,10 @@ class IntIterator:
|
||||||
def __next__(self) -> int:
|
def __next__(self) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class IntIterable:
|
class IntIterable:
|
||||||
def __iter__(self) -> IntIterator:
|
def __iter__(self) -> IntIterator:
|
||||||
return IntIterator()
|
return IntIterator()
|
||||||
|
|
||||||
|
|
||||||
for x in IntIterable():
|
for x in IntIterable():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -26,12 +24,10 @@ class IntIterator:
|
||||||
def __next__(self) -> int:
|
def __next__(self) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class IntIterable:
|
class IntIterable:
|
||||||
def __iter__(self) -> IntIterator:
|
def __iter__(self) -> IntIterator:
|
||||||
return IntIterator()
|
return IntIterator()
|
||||||
|
|
||||||
|
|
||||||
x = "foo"
|
x = "foo"
|
||||||
|
|
||||||
for x in IntIterable():
|
for x in IntIterable():
|
||||||
|
@ -47,12 +43,10 @@ class IntIterator:
|
||||||
def __next__(self) -> int:
|
def __next__(self) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class IntIterable:
|
class IntIterable:
|
||||||
def __iter__(self) -> IntIterator:
|
def __iter__(self) -> IntIterator:
|
||||||
return IntIterator()
|
return IntIterator()
|
||||||
|
|
||||||
|
|
||||||
for x in IntIterable():
|
for x in IntIterable():
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -68,12 +62,10 @@ class IntIterator:
|
||||||
def __next__(self) -> int:
|
def __next__(self) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class IntIterable:
|
class IntIterable:
|
||||||
def __iter__(self) -> IntIterator:
|
def __iter__(self) -> IntIterator:
|
||||||
return IntIterator()
|
return IntIterator()
|
||||||
|
|
||||||
|
|
||||||
for x in IntIterable():
|
for x in IntIterable():
|
||||||
if x > 5:
|
if x > 5:
|
||||||
break
|
break
|
||||||
|
@ -90,7 +82,6 @@ class OldStyleIterable:
|
||||||
def __getitem__(self, key: int) -> int:
|
def __getitem__(self, key: int) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
for x in OldStyleIterable():
|
for x in OldStyleIterable():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -115,7 +106,6 @@ class NotIterable:
|
||||||
else:
|
else:
|
||||||
__iter__ = None
|
__iter__ = None
|
||||||
|
|
||||||
|
|
||||||
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
|
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -136,10 +126,8 @@ for x in nonsense: # error: "Object of type `Literal[123]` is not iterable"
|
||||||
class NotIterable:
|
class NotIterable:
|
||||||
def __getitem__(self, key: int) -> int:
|
def __getitem__(self, key: int) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
__iter__ = None
|
__iter__ = None
|
||||||
|
|
||||||
|
|
||||||
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
|
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
|
|
@ -5,16 +5,13 @@
|
||||||
```py
|
```py
|
||||||
class NotIterable: ...
|
class NotIterable: ...
|
||||||
|
|
||||||
|
|
||||||
class Iterator:
|
class Iterator:
|
||||||
def __next__(self) -> int:
|
def __next__(self) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class Iterable:
|
class Iterable:
|
||||||
def __iter__(self) -> Iterator: ...
|
def __iter__(self) -> Iterator: ...
|
||||||
|
|
||||||
|
|
||||||
def generator_function():
|
def generator_function():
|
||||||
yield from Iterable()
|
yield from Iterable()
|
||||||
yield from NotIterable() # error: "Object of type `NotIterable` is not iterable"
|
yield from NotIterable() # error: "Object of type `NotIterable` is not iterable"
|
||||||
|
|
|
@ -16,7 +16,6 @@ reveal_type(x) # revealed: None | Literal[1]
|
||||||
```py
|
```py
|
||||||
class A: ...
|
class A: ...
|
||||||
|
|
||||||
|
|
||||||
x = A()
|
x = A()
|
||||||
y = x if flag else None
|
y = x if flag else None
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
```py
|
```py
|
||||||
def int_instance() -> int: ...
|
def int_instance() -> int: ...
|
||||||
|
|
||||||
|
|
||||||
x = int_instance()
|
x = int_instance()
|
||||||
|
|
||||||
if x != 1:
|
if x != 1:
|
||||||
|
|
|
@ -31,11 +31,8 @@ if x != 1:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
class A: ...
|
class A: ...
|
||||||
|
|
||||||
|
|
||||||
class B: ...
|
class B: ...
|
||||||
|
|
||||||
|
|
||||||
C = A if flag else B
|
C = A if flag else B
|
||||||
|
|
||||||
if C != A:
|
if C != A:
|
||||||
|
@ -49,7 +46,6 @@ Only single-valued types should narrow the type:
|
||||||
```py
|
```py
|
||||||
def int_instance() -> int: ...
|
def int_instance() -> int: ...
|
||||||
|
|
||||||
|
|
||||||
x = int_instance() if flag else None
|
x = int_instance() if flag else None
|
||||||
y = int_instance()
|
y = int_instance()
|
||||||
|
|
||||||
|
|
|
@ -66,14 +66,10 @@ if isinstance(x, (bool, (bytes, int))):
|
||||||
|
|
||||||
```py
|
```py
|
||||||
class A: ...
|
class A: ...
|
||||||
|
|
||||||
|
|
||||||
class B: ...
|
class B: ...
|
||||||
|
|
||||||
|
|
||||||
def get_object() -> object: ...
|
def get_object() -> object: ...
|
||||||
|
|
||||||
|
|
||||||
x = get_object()
|
x = get_object()
|
||||||
|
|
||||||
if isinstance(x, A):
|
if isinstance(x, A):
|
||||||
|
@ -101,7 +97,6 @@ if isinstance(x, t):
|
||||||
def isinstance(x, t):
|
def isinstance(x, t):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
x = 1 if flag else "a"
|
x = 1 if flag else "a"
|
||||||
if isinstance(x, int):
|
if isinstance(x, int):
|
||||||
reveal_type(x) # revealed: Literal[1] | Literal["a"]
|
reveal_type(x) # revealed: Literal[1] | Literal["a"]
|
||||||
|
|
|
@ -9,11 +9,9 @@ with the conditionally-defined type:
|
||||||
def returns_bool() -> bool:
|
def returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
if returns_bool():
|
if returns_bool():
|
||||||
copyright = 1
|
copyright = 1
|
||||||
|
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
reveal_type(copyright) # revealed: Literal[copyright] | Literal[1]
|
reveal_type(copyright) # revealed: Literal[copyright] | Literal[1]
|
||||||
```
|
```
|
||||||
|
@ -26,11 +24,9 @@ Same is true if the name is annotated:
|
||||||
def returns_bool() -> bool:
|
def returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
if returns_bool():
|
if returns_bool():
|
||||||
copyright: int = 1
|
copyright: int = 1
|
||||||
|
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
reveal_type(copyright) # revealed: Literal[copyright] | int
|
reveal_type(copyright) # revealed: Literal[copyright] | int
|
||||||
```
|
```
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
```py
|
```py
|
||||||
class C: ...
|
class C: ...
|
||||||
|
|
||||||
|
|
||||||
C = 1 # error: "Implicit shadowing of class `C`; annotate to make it explicit if this is intentional"
|
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
|
```py
|
||||||
class C: ...
|
class C: ...
|
||||||
|
|
||||||
|
|
||||||
C: int = 1
|
C: int = 1
|
||||||
```
|
```
|
||||||
|
|
|
@ -14,7 +14,6 @@ def f(x: str):
|
||||||
```py path=a.py
|
```py path=a.py
|
||||||
def f(): ...
|
def f(): ...
|
||||||
|
|
||||||
|
|
||||||
f = 1 # error: "Implicit shadowing of function `f`; annotate to make it explicit if this is intentional"
|
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
|
```py path=a.py
|
||||||
def f(): ...
|
def f(): ...
|
||||||
|
|
||||||
|
|
||||||
f: int = 1
|
f: int = 1
|
||||||
```
|
```
|
||||||
|
|
|
@ -7,6 +7,5 @@ In type stubs, classes can reference themselves in their base class definitions.
|
||||||
```py path=a.pyi
|
```py path=a.pyi
|
||||||
class C(C): ...
|
class C(C): ...
|
||||||
|
|
||||||
|
|
||||||
reveal_type(C) # revealed: Literal[C]
|
reveal_type(C) # revealed: Literal[C]
|
||||||
```
|
```
|
||||||
|
|
|
@ -28,7 +28,6 @@ reveal_type(y) # revealed: Unknown
|
||||||
```py
|
```py
|
||||||
def int_instance() -> int: ...
|
def int_instance() -> int: ...
|
||||||
|
|
||||||
|
|
||||||
a = b"abcde"[int_instance()]
|
a = b"abcde"[int_instance()]
|
||||||
# TODO: Support overloads... Should be `bytes`
|
# TODO: Support overloads... Should be `bytes`
|
||||||
reveal_type(a) # revealed: @Todo
|
reveal_type(a) # revealed: @Todo
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
```py
|
```py
|
||||||
class NotSubscriptable: ...
|
class NotSubscriptable: ...
|
||||||
|
|
||||||
|
|
||||||
a = NotSubscriptable[0] # error: "Cannot subscript object of type `Literal[NotSubscriptable]` with no `__class_getitem__` method"
|
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:
|
def __class_getitem__(cls, item: int) -> str:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
reveal_type(Identity[0]) # revealed: str
|
reveal_type(Identity[0]) # revealed: str
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -25,19 +23,16 @@ reveal_type(Identity[0]) # revealed: str
|
||||||
```py
|
```py
|
||||||
flag = True
|
flag = True
|
||||||
|
|
||||||
|
|
||||||
class UnionClassGetItem:
|
class UnionClassGetItem:
|
||||||
if flag:
|
if flag:
|
||||||
|
|
||||||
def __class_getitem__(cls, item: int) -> str:
|
def __class_getitem__(cls, item: int) -> str:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
def __class_getitem__(cls, item: int) -> int:
|
def __class_getitem__(cls, item: int) -> int:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
reveal_type(UnionClassGetItem[0]) # revealed: str | int
|
reveal_type(UnionClassGetItem[0]) # revealed: str | int
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -46,17 +41,14 @@ reveal_type(UnionClassGetItem[0]) # revealed: str | int
|
||||||
```py
|
```py
|
||||||
flag = True
|
flag = True
|
||||||
|
|
||||||
|
|
||||||
class A:
|
class A:
|
||||||
def __class_getitem__(cls, item: int) -> str:
|
def __class_getitem__(cls, item: int) -> str:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
class B:
|
class B:
|
||||||
def __class_getitem__(cls, item: int) -> int:
|
def __class_getitem__(cls, item: int) -> int:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
x = A if flag else B
|
x = A if flag else B
|
||||||
|
|
||||||
reveal_type(x) # revealed: Literal[A, B]
|
reveal_type(x) # revealed: Literal[A, B]
|
||||||
|
@ -69,16 +61,13 @@ reveal_type(x[0]) # revealed: str | int
|
||||||
flag = True
|
flag = True
|
||||||
|
|
||||||
if flag:
|
if flag:
|
||||||
|
|
||||||
class Spam:
|
class Spam:
|
||||||
def __class_getitem__(self, x: int) -> str:
|
def __class_getitem__(self, x: int) -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
class Spam: ...
|
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]`"
|
# 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
|
# revealed: str | Unknown
|
||||||
reveal_type(Spam[42])
|
reveal_type(Spam[42])
|
||||||
|
@ -90,7 +79,6 @@ reveal_type(Spam[42])
|
||||||
flag = True
|
flag = True
|
||||||
|
|
||||||
if flag:
|
if flag:
|
||||||
|
|
||||||
class Eggs:
|
class Eggs:
|
||||||
def __class_getitem__(self, x: int) -> str:
|
def __class_getitem__(self, x: int) -> str:
|
||||||
return "foo"
|
return "foo"
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
```py
|
```py
|
||||||
class NotSubscriptable: ...
|
class NotSubscriptable: ...
|
||||||
|
|
||||||
|
|
||||||
a = NotSubscriptable()[0] # error: "Cannot subscript object of type `NotSubscriptable` with no `__getitem__` method"
|
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:
|
class NotSubscriptable:
|
||||||
__getitem__ = None
|
__getitem__ = None
|
||||||
|
|
||||||
|
|
||||||
a = NotSubscriptable()[0] # error: "Method `__getitem__` of type `None` is not callable on object of type `NotSubscriptable`"
|
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:
|
def __getitem__(self, index: int) -> int:
|
||||||
return index
|
return index
|
||||||
|
|
||||||
|
|
||||||
reveal_type(Identity()[0]) # revealed: int
|
reveal_type(Identity()[0]) # revealed: int
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -35,18 +32,15 @@ reveal_type(Identity()[0]) # revealed: int
|
||||||
```py
|
```py
|
||||||
flag = True
|
flag = True
|
||||||
|
|
||||||
|
|
||||||
class Identity:
|
class Identity:
|
||||||
if flag:
|
if flag:
|
||||||
|
|
||||||
def __getitem__(self, index: int) -> int:
|
def __getitem__(self, index: int) -> int:
|
||||||
return index
|
return index
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
def __getitem__(self, index: int) -> str:
|
def __getitem__(self, index: int) -> str:
|
||||||
return str(index)
|
return str(index)
|
||||||
|
|
||||||
|
|
||||||
reveal_type(Identity()[0]) # revealed: int | str
|
reveal_type(Identity()[0]) # revealed: int | str
|
||||||
```
|
```
|
||||||
|
|
|
@ -25,7 +25,6 @@ reveal_type(b) # revealed: Unknown
|
||||||
```py
|
```py
|
||||||
def int_instance() -> int: ...
|
def int_instance() -> int: ...
|
||||||
|
|
||||||
|
|
||||||
a = "abcde"[int_instance()]
|
a = "abcde"[int_instance()]
|
||||||
# TODO: Support overloads... Should be `str`
|
# TODO: Support overloads... Should be `str`
|
||||||
reveal_type(a) # revealed: @Todo
|
reveal_type(a) # revealed: @Todo
|
||||||
|
|
|
@ -14,17 +14,14 @@ class Number:
|
||||||
def __invert__(self) -> Literal[True]:
|
def __invert__(self) -> Literal[True]:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
a = Number()
|
a = Number()
|
||||||
|
|
||||||
reveal_type(+a) # revealed: int
|
reveal_type(+a) # revealed: int
|
||||||
reveal_type(-a) # revealed: int
|
reveal_type(-a) # revealed: int
|
||||||
reveal_type(~a) # revealed: @Todo
|
reveal_type(~a) # revealed: @Todo
|
||||||
|
|
||||||
|
|
||||||
class NoDunder: ...
|
class NoDunder: ...
|
||||||
|
|
||||||
|
|
||||||
b = 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`"
|
||||||
-b # error: [unsupported-operator] "Unary operator `-` is unsupported for type `NoDunder`"
|
-b # error: [unsupported-operator] "Unary operator `-` is unsupported for type `NoDunder`"
|
||||||
|
|
|
@ -12,11 +12,9 @@ reveal_type(not not None) # revealed: Literal[False]
|
||||||
```py
|
```py
|
||||||
from typing import reveal_type
|
from typing import reveal_type
|
||||||
|
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
reveal_type(not f) # revealed: Literal[False]
|
reveal_type(not f) # revealed: Literal[False]
|
||||||
# TODO Unknown should not be part of the type of typing.reveal_type
|
# TODO Unknown should not be part of the type of typing.reveal_type
|
||||||
# reveal_type(not reveal_type) revealed: Literal[False]
|
# reveal_type(not reveal_type) revealed: Literal[False]
|
||||||
|
@ -28,7 +26,6 @@ reveal_type(not f) # revealed: Literal[False]
|
||||||
import b
|
import b
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
reveal_type(not b) # revealed: Literal[False]
|
reveal_type(not b) # revealed: Literal[False]
|
||||||
reveal_type(not warnings) # revealed: Literal[False]
|
reveal_type(not warnings) # revealed: Literal[False]
|
||||||
```
|
```
|
||||||
|
|
|
@ -155,12 +155,10 @@ class Iterator:
|
||||||
def __next__(self) -> int:
|
def __next__(self) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class Iterable:
|
class Iterable:
|
||||||
def __iter__(self) -> Iterator:
|
def __iter__(self) -> Iterator:
|
||||||
return Iterator()
|
return Iterator()
|
||||||
|
|
||||||
|
|
||||||
(a, b) = Iterable()
|
(a, b) = Iterable()
|
||||||
reveal_type(a) # revealed: int
|
reveal_type(a) # revealed: int
|
||||||
reveal_type(b) # revealed: int
|
reveal_type(b) # revealed: int
|
||||||
|
@ -173,12 +171,10 @@ class Iterator:
|
||||||
def __next__(self) -> int:
|
def __next__(self) -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
||||||
class Iterable:
|
class Iterable:
|
||||||
def __iter__(self) -> Iterator:
|
def __iter__(self) -> Iterator:
|
||||||
return Iterator()
|
return Iterator()
|
||||||
|
|
||||||
|
|
||||||
(a, (b, c), d) = (1, Iterable(), 2)
|
(a, (b, c), d) = (1, Iterable(), 2)
|
||||||
reveal_type(a) # revealed: Literal[1]
|
reveal_type(a) # revealed: Literal[1]
|
||||||
reveal_type(b) # revealed: int
|
reveal_type(b) # revealed: int
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue