[ty] Filter out revealed-type and undefined-reveal diagnostics from mdtest snapshots (#20820)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / ty completion evaluation (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / cargo test (linux) (push) Blocked by required conditions
CI / benchmarks walltime (medium|multithreaded) (push) Blocked by required conditions
CI / benchmarks walltime (small|large) (push) Blocked by required conditions
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run

This commit is contained in:
Alex Waygood 2025-10-12 19:39:32 +01:00 committed by GitHub
parent dc64c08633
commit 7064c38e53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 849 additions and 1900 deletions

View file

@ -99,8 +99,6 @@ If the arity check only matches a single overload, it should be evaluated as a r
call should be reported directly and not as a `no-matching-overload` error.
```py
from typing_extensions import reveal_type
from overloaded import f
reveal_type(f()) # revealed: None

View file

@ -1010,7 +1010,6 @@ python-version = "3.10"
```py
from dataclasses import dataclass, field, KW_ONLY
from typing_extensions import reveal_type
@dataclass
class C:

View file

@ -3,8 +3,6 @@
## Invalid syntax
```py
from typing_extensions import reveal_type
try:
print
except as e: # error: [invalid-syntax]

View file

@ -181,7 +181,6 @@ reveal_type(takes_homogeneous_tuple((42, 43))) # revealed: Literal[42, 43]
```py
from typing import TypeVar
from typing_extensions import reveal_type
T = TypeVar("T", bound=int)
@ -200,7 +199,6 @@ reveal_type(f("string")) # revealed: Unknown
```py
from typing import TypeVar
from typing_extensions import reveal_type
T = TypeVar("T", int, None)

View file

@ -5,8 +5,6 @@ all members available on a given type. This routine is used for autocomplete sug
## Basic functionality
<!-- snapshot-diagnostics -->
The `ty_extensions.all_members` and `ty_extensions.has_member` functions expose a Python-level API
that can be used to query which attributes `ide_support::all_members` understands as being available
on a given object. For example, all member functions of `str` are available on `"a"`. The Python API
@ -45,10 +43,10 @@ The full list of all members is relatively long, but `reveal_type` can be used i
`all_members` to see them all:
```py
from typing_extensions import reveal_type
from ty_extensions import all_members
reveal_type(all_members("a")) # error: [revealed-type]
# revealed: tuple[Literal["__add__"], Literal["__annotations__"], Literal["__class__"], Literal["__contains__"], Literal["__delattr__"], Literal["__dict__"], Literal["__dir__"], Literal["__doc__"], Literal["__eq__"], Literal["__format__"], Literal["__ge__"], Literal["__getattribute__"], Literal["__getitem__"], Literal["__getnewargs__"], Literal["__gt__"], Literal["__hash__"], Literal["__init__"], Literal["__init_subclass__"], Literal["__iter__"], Literal["__le__"], Literal["__len__"], Literal["__lt__"], Literal["__mod__"], Literal["__module__"], Literal["__mul__"], Literal["__ne__"], Literal["__new__"], Literal["__reduce__"], Literal["__reduce_ex__"], Literal["__repr__"], Literal["__reversed__"], Literal["__rmul__"], Literal["__setattr__"], Literal["__sizeof__"], Literal["__str__"], Literal["__subclasshook__"], Literal["capitalize"], Literal["casefold"], Literal["center"], Literal["count"], Literal["encode"], Literal["endswith"], Literal["expandtabs"], Literal["find"], Literal["format"], Literal["format_map"], Literal["index"], Literal["isalnum"], Literal["isalpha"], Literal["isascii"], Literal["isdecimal"], Literal["isdigit"], Literal["isidentifier"], Literal["islower"], Literal["isnumeric"], Literal["isprintable"], Literal["isspace"], Literal["istitle"], Literal["isupper"], Literal["join"], Literal["ljust"], Literal["lower"], Literal["lstrip"], Literal["maketrans"], Literal["partition"], Literal["removeprefix"], Literal["removesuffix"], Literal["replace"], Literal["rfind"], Literal["rindex"], Literal["rjust"], Literal["rpartition"], Literal["rsplit"], Literal["rstrip"], Literal["split"], Literal["splitlines"], Literal["startswith"], Literal["strip"], Literal["swapcase"], Literal["title"], Literal["translate"], Literal["upper"], Literal["zfill"]]
reveal_type(all_members("a"))
```
## Kinds of types

View file

@ -42,8 +42,6 @@ async def foo():
### No `__aiter__` method
```py
from typing_extensions import reveal_type
class NotAsyncIterable: ...
async def foo():
@ -55,8 +53,6 @@ async def foo():
### Synchronously iterable, but not asynchronously iterable
```py
from typing_extensions import reveal_type
async def foo():
class Iterator:
def __next__(self) -> int:
@ -74,8 +70,6 @@ async def foo():
### No `__anext__` method
```py
from typing_extensions import reveal_type
class NoAnext: ...
class AsyncIterable:
@ -91,8 +85,6 @@ async def foo():
### Possibly missing `__anext__` method
```py
from typing_extensions import reveal_type
async def foo(flag: bool):
class PossiblyUnboundAnext:
if flag:
@ -111,8 +103,6 @@ async def foo(flag: bool):
### Possibly missing `__aiter__` method
```py
from typing_extensions import reveal_type
async def foo(flag: bool):
class AsyncIterable:
async def __anext__(self) -> int:
@ -131,8 +121,6 @@ async def foo(flag: bool):
### Wrong signature for `__aiter__`
```py
from typing_extensions import reveal_type
class AsyncIterator:
async def __anext__(self) -> int:
return 42
@ -150,8 +138,6 @@ async def foo():
### Wrong signature for `__anext__`
```py
from typing_extensions import reveal_type
class AsyncIterator:
async def __anext__(self, arg: int) -> int: # wrong
return 42

View file

@ -108,8 +108,6 @@ reveal_type(x)
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
def _(flag: bool):
class NotIterable:
if flag:
@ -271,8 +269,6 @@ def g(
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class TestIter:
def __next__(self) -> int:
return 42
@ -292,8 +288,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class TestIter:
def __next__(self) -> int:
return 42
@ -370,8 +364,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Iterator:
def __next__(self) -> int:
return 42
@ -390,8 +382,6 @@ for x in Iterable():
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Bad:
def __iter__(self) -> int:
return 42
@ -424,8 +414,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Iterator1:
def __next__(self, extra_arg) -> int:
return 42
@ -455,8 +443,6 @@ for y in Iterable2():
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
def _(flag: bool):
class Iterator:
def __next__(self) -> int:
@ -509,8 +495,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Iterator:
def __next__(self) -> int:
return 42
@ -534,8 +518,6 @@ def _(flag1: bool, flag2: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Bad:
__getitem__: None = None
@ -549,8 +531,6 @@ for x in Bad():
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
def _(flag: bool):
class CustomCallable:
if flag:
@ -585,8 +565,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Iterable:
# invalid because it will implicitly be passed an `int`
# by the interpreter
@ -626,8 +604,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Iterator:
def __next__(self) -> int:
return 42
@ -663,8 +639,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
def _(flag: bool):
class Iterator1:
if flag:
@ -704,8 +678,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
def _(flag: bool):
class Iterable1:
if flag:
@ -737,8 +709,6 @@ def _(flag: bool):
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Iterator:
def __next__(self) -> bytes:
return b"foo"

View file

@ -241,8 +241,6 @@ find a union type in a class's bases, we infer the class's `__mro__` as being
`[<class>, Unknown, object]`, the same as for MROs that cause errors at runtime.
```py
from typing_extensions import reveal_type
def returns_bool() -> bool:
return True
@ -391,8 +389,6 @@ class BadSub2(Bad2()): ... # error: [invalid-base]
<!-- snapshot-diagnostics -->
```py
from typing_extensions import reveal_type
class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]

View file

@ -281,7 +281,7 @@ def _(x: Foo | Bar, flag: bool) -> None:
The `TypeIs` type remains effective across generic boundaries:
```py
from typing_extensions import TypeVar, reveal_type
from typing_extensions import TypeVar
T = TypeVar("T")

View file

@ -347,7 +347,7 @@ python-version = "3.12"
```
```py
from typing_extensions import Protocol, reveal_type
from typing_extensions import Protocol
# error: [call-non-callable]
reveal_type(Protocol()) # revealed: Unknown
@ -381,9 +381,7 @@ And as a corollary, `type[MyProtocol]` can also be called:
```py
def f(x: type[MyProtocol]):
# TODO: add a `reveal_type` call here once it's no longer a `Todo` type
# (which doesn't work well with snapshots)
x()
reveal_type(x()) # revealed: @Todo(type[T] for protocols)
```
## Members of a protocol
@ -534,7 +532,7 @@ python-version = "3.9"
```py
import sys
from typing_extensions import Protocol, get_protocol_members, reveal_type
from typing_extensions import Protocol, get_protocol_members
class Foo(Protocol):
if sys.version_info >= (3, 10):
@ -2393,7 +2391,7 @@ By default, a protocol class cannot be used as the second argument to `isinstanc
type inside these branches (this matches the behavior of other type checkers):
```py
from typing_extensions import Protocol, reveal_type
from typing_extensions import Protocol
class HasX(Protocol):
x: int

View file

@ -1,43 +0,0 @@
---
source: crates/ty_test/src/lib.rs
expression: snapshot
---
---
mdtest name: all_members.md - List all members - Basic functionality
mdtest path: crates/ty_python_semantic/resources/mdtest/ide_support/all_members.md
---
# Python source files
## mdtest_snippet.py
```
1 | from ty_extensions import static_assert, has_member
2 |
3 | static_assert(has_member("a", "replace"))
4 | static_assert(has_member("a", "startswith"))
5 | static_assert(has_member("a", "isupper"))
6 | static_assert(has_member("a", "__add__"))
7 | static_assert(has_member("a", "__gt__"))
8 | static_assert(has_member("a", "__doc__"))
9 | static_assert(has_member("a", "__repr__"))
10 | static_assert(not has_member("a", "non_existent"))
11 | from typing_extensions import reveal_type
12 | from ty_extensions import all_members
13 |
14 | reveal_type(all_members("a")) # error: [revealed-type]
```
# Diagnostics
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:14:13
|
12 | from ty_extensions import all_members
13 |
14 | reveal_type(all_members("a")) # error: [revealed-type]
| ^^^^^^^^^^^^^^^^ `tuple[Literal["__add__"], Literal["__annotations__"], Literal["__class__"], Literal["__contains__"], Literal["__delattr__"], Literal["__dict__"], Literal["__dir__"], Literal["__doc__"], Literal["__eq__"], Literal["__format__"], Literal["__ge__"], Literal["__getattribute__"], Literal["__getitem__"], Literal["__getnewargs__"], Literal["__gt__"], Literal["__hash__"], Literal["__init__"], Literal["__init_subclass__"], Literal["__iter__"], Literal["__le__"], Literal["__len__"], Literal["__lt__"], Literal["__mod__"], Literal["__module__"], Literal["__mul__"], Literal["__ne__"], Literal["__new__"], Literal["__reduce__"], Literal["__reduce_ex__"], Literal["__repr__"], Literal["__reversed__"], Literal["__rmul__"], Literal["__setattr__"], Literal["__sizeof__"], Literal["__str__"], Literal["__subclasshook__"], Literal["capitalize"], Literal["casefold"], Literal["center"], Literal["count"], Literal["encode"], Literal["endswith"], Literal["expandtabs"], Literal["find"], Literal["format"], Literal["format_map"], Literal["index"], Literal["isalnum"], Literal["isalpha"], Literal["isascii"], Literal["isdecimal"], Literal["isdigit"], Literal["isidentifier"], Literal["islower"], Literal["isnumeric"], Literal["isprintable"], Literal["isspace"], Literal["istitle"], Literal["isupper"], Literal["join"], Literal["ljust"], Literal["lower"], Literal["lstrip"], Literal["maketrans"], Literal["partition"], Literal["removeprefix"], Literal["removesuffix"], Literal["replace"], Literal["rfind"], Literal["rindex"], Literal["rjust"], Literal["rpartition"], Literal["rsplit"], Literal["rstrip"], Literal["split"], Literal["splitlines"], Literal["startswith"], Literal["strip"], Literal["swapcase"], Literal["title"], Literal["translate"], Literal["upper"], Literal["zfill"]]`
|
```

View file

@ -12,41 +12,27 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/async_for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
1 | class NotAsyncIterable: ...
2 |
3 | class NotAsyncIterable: ...
4 |
5 | async def foo():
6 | # error: [not-iterable] "Object of type `NotAsyncIterable` is not async-iterable"
7 | async for x in NotAsyncIterable():
8 | reveal_type(x) # revealed: Unknown
3 | async def foo():
4 | # error: [not-iterable] "Object of type `NotAsyncIterable` is not async-iterable"
5 | async for x in NotAsyncIterable():
6 | reveal_type(x) # revealed: Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `NotAsyncIterable` is not async-iterable
--> src/mdtest_snippet.py:7:20
--> src/mdtest_snippet.py:5:20
|
5 | async def foo():
6 | # error: [not-iterable] "Object of type `NotAsyncIterable` is not async-iterable"
7 | async for x in NotAsyncIterable():
3 | async def foo():
4 | # error: [not-iterable] "Object of type `NotAsyncIterable` is not async-iterable"
5 | async for x in NotAsyncIterable():
| ^^^^^^^^^^^^^^^^^^
8 | reveal_type(x) # revealed: Unknown
6 | reveal_type(x) # revealed: Unknown
|
info: It has no `__aiter__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:8:21
|
6 | # error: [not-iterable] "Object of type `NotAsyncIterable` is not async-iterable"
7 | async for x in NotAsyncIterable():
8 | reveal_type(x) # revealed: Unknown
| ^ `Unknown`
|
```

View file

@ -12,45 +12,31 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/async_for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
1 | class NoAnext: ...
2 |
3 | class NoAnext: ...
4 |
5 | class AsyncIterable:
6 | def __aiter__(self) -> NoAnext:
7 | return NoAnext()
8 |
9 | async def foo():
10 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
11 | async for x in AsyncIterable():
12 | reveal_type(x) # revealed: Unknown
3 | class AsyncIterable:
4 | def __aiter__(self) -> NoAnext:
5 | return NoAnext()
6 |
7 | async def foo():
8 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
9 | async for x in AsyncIterable():
10 | reveal_type(x) # revealed: Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `AsyncIterable` is not async-iterable
--> src/mdtest_snippet.py:11:20
--> src/mdtest_snippet.py:9:20
|
9 | async def foo():
10 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
11 | async for x in AsyncIterable():
7 | async def foo():
8 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
9 | async for x in AsyncIterable():
| ^^^^^^^^^^^^^^^
12 | reveal_type(x) # revealed: Unknown
10 | reveal_type(x) # revealed: Unknown
|
info: Its `__aiter__` method returns an object of type `NoAnext`, which has no `__anext__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:12:21
|
10 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
11 | async for x in AsyncIterable():
12 | reveal_type(x) # revealed: Unknown
| ^ `Unknown`
|
```

View file

@ -12,47 +12,33 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/async_for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | async def foo(flag: bool):
4 | class AsyncIterable:
5 | async def __anext__(self) -> int:
6 | return 42
7 |
8 | class PossiblyUnboundAiter:
9 | if flag:
10 | def __aiter__(self) -> AsyncIterable:
11 | return AsyncIterable()
12 |
13 | # error: "Object of type `PossiblyUnboundAiter` may not be async-iterable"
14 | async for x in PossiblyUnboundAiter():
15 | reveal_type(x) # revealed: int
1 | async def foo(flag: bool):
2 | class AsyncIterable:
3 | async def __anext__(self) -> int:
4 | return 42
5 |
6 | class PossiblyUnboundAiter:
7 | if flag:
8 | def __aiter__(self) -> AsyncIterable:
9 | return AsyncIterable()
10 |
11 | # error: "Object of type `PossiblyUnboundAiter` may not be async-iterable"
12 | async for x in PossiblyUnboundAiter():
13 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `PossiblyUnboundAiter` may not be async-iterable
--> src/mdtest_snippet.py:14:20
--> src/mdtest_snippet.py:12:20
|
13 | # error: "Object of type `PossiblyUnboundAiter` may not be async-iterable"
14 | async for x in PossiblyUnboundAiter():
11 | # error: "Object of type `PossiblyUnboundAiter` may not be async-iterable"
12 | async for x in PossiblyUnboundAiter():
| ^^^^^^^^^^^^^^^^^^^^^^
15 | reveal_type(x) # revealed: int
13 | reveal_type(x) # revealed: int
|
info: Its `__aiter__` attribute (with type `bound method PossiblyUnboundAiter.__aiter__() -> AsyncIterable`) may not be callable
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:15:21
|
13 | # error: "Object of type `PossiblyUnboundAiter` may not be async-iterable"
14 | async for x in PossiblyUnboundAiter():
15 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -12,47 +12,33 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/async_for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | async def foo(flag: bool):
4 | class PossiblyUnboundAnext:
5 | if flag:
6 | async def __anext__(self) -> int:
7 | return 42
8 |
9 | class AsyncIterable:
10 | def __aiter__(self) -> PossiblyUnboundAnext:
11 | return PossiblyUnboundAnext()
12 |
13 | # error: [not-iterable] "Object of type `AsyncIterable` may not be async-iterable"
14 | async for x in AsyncIterable():
15 | reveal_type(x) # revealed: int
1 | async def foo(flag: bool):
2 | class PossiblyUnboundAnext:
3 | if flag:
4 | async def __anext__(self) -> int:
5 | return 42
6 |
7 | class AsyncIterable:
8 | def __aiter__(self) -> PossiblyUnboundAnext:
9 | return PossiblyUnboundAnext()
10 |
11 | # error: [not-iterable] "Object of type `AsyncIterable` may not be async-iterable"
12 | async for x in AsyncIterable():
13 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `AsyncIterable` may not be async-iterable
--> src/mdtest_snippet.py:14:20
--> src/mdtest_snippet.py:12:20
|
13 | # error: [not-iterable] "Object of type `AsyncIterable` may not be async-iterable"
14 | async for x in AsyncIterable():
11 | # error: [not-iterable] "Object of type `AsyncIterable` may not be async-iterable"
12 | async for x in AsyncIterable():
| ^^^^^^^^^^^^^^^
15 | reveal_type(x) # revealed: int
13 | reveal_type(x) # revealed: int
|
info: Its `__aiter__` method returns an object of type `PossiblyUnboundAnext`, which may not have a `__anext__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:15:21
|
13 | # error: [not-iterable] "Object of type `AsyncIterable` may not be async-iterable"
14 | async for x in AsyncIterable():
15 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -12,46 +12,32 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/async_for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | async def foo():
4 | class Iterator:
5 | def __next__(self) -> int:
6 | return 42
7 |
8 | class Iterable:
9 | def __iter__(self) -> Iterator:
10 | return Iterator()
11 |
12 | # error: [not-iterable] "Object of type `Iterator` is not async-iterable"
13 | async for x in Iterator():
14 | reveal_type(x) # revealed: Unknown
1 | async def foo():
2 | class Iterator:
3 | def __next__(self) -> int:
4 | return 42
5 |
6 | class Iterable:
7 | def __iter__(self) -> Iterator:
8 | return Iterator()
9 |
10 | # error: [not-iterable] "Object of type `Iterator` is not async-iterable"
11 | async for x in Iterator():
12 | reveal_type(x) # revealed: Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterator` is not async-iterable
--> src/mdtest_snippet.py:13:20
--> src/mdtest_snippet.py:11:20
|
12 | # error: [not-iterable] "Object of type `Iterator` is not async-iterable"
13 | async for x in Iterator():
10 | # error: [not-iterable] "Object of type `Iterator` is not async-iterable"
11 | async for x in Iterator():
| ^^^^^^^^^^
14 | reveal_type(x) # revealed: Unknown
12 | reveal_type(x) # revealed: Unknown
|
info: It has no `__aiter__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:14:21
|
12 | # error: [not-iterable] "Object of type `Iterator` is not async-iterable"
13 | async for x in Iterator():
14 | reveal_type(x) # revealed: Unknown
| ^ `Unknown`
|
```

View file

@ -12,48 +12,34 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/async_for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class AsyncIterator:
4 | async def __anext__(self, arg: int) -> int: # wrong
5 | return 42
6 |
7 | class AsyncIterable:
8 | def __aiter__(self) -> AsyncIterator:
9 | return AsyncIterator()
10 |
11 | async def foo():
12 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
13 | async for x in AsyncIterable():
14 | reveal_type(x) # revealed: int
1 | class AsyncIterator:
2 | async def __anext__(self, arg: int) -> int: # wrong
3 | return 42
4 |
5 | class AsyncIterable:
6 | def __aiter__(self) -> AsyncIterator:
7 | return AsyncIterator()
8 |
9 | async def foo():
10 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
11 | async for x in AsyncIterable():
12 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `AsyncIterable` is not async-iterable
--> src/mdtest_snippet.py:13:20
--> src/mdtest_snippet.py:11:20
|
11 | async def foo():
12 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
13 | async for x in AsyncIterable():
9 | async def foo():
10 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
11 | async for x in AsyncIterable():
| ^^^^^^^^^^^^^^^
14 | reveal_type(x) # revealed: int
12 | reveal_type(x) # revealed: int
|
info: Its `__aiter__` method returns an object of type `AsyncIterator`, which has an invalid `__anext__` method
info: Expected signature for `__anext__` is `def __anext__(self): ...`
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:14:21
|
12 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
13 | async for x in AsyncIterable():
14 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -12,48 +12,34 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/async_for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class AsyncIterator:
4 | async def __anext__(self) -> int:
5 | return 42
6 |
7 | class AsyncIterable:
8 | def __aiter__(self, arg: int) -> AsyncIterator: # wrong
9 | return AsyncIterator()
10 |
11 | async def foo():
12 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
13 | async for x in AsyncIterable():
14 | reveal_type(x) # revealed: int
1 | class AsyncIterator:
2 | async def __anext__(self) -> int:
3 | return 42
4 |
5 | class AsyncIterable:
6 | def __aiter__(self, arg: int) -> AsyncIterator: # wrong
7 | return AsyncIterator()
8 |
9 | async def foo():
10 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
11 | async for x in AsyncIterable():
12 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `AsyncIterable` is not async-iterable
--> src/mdtest_snippet.py:13:20
--> src/mdtest_snippet.py:11:20
|
11 | async def foo():
12 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
13 | async for x in AsyncIterable():
9 | async def foo():
10 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
11 | async for x in AsyncIterable():
| ^^^^^^^^^^^^^^^
14 | reveal_type(x) # revealed: int
12 | reveal_type(x) # revealed: int
|
info: Its `__aiter__` method has an invalid signature
info: Expected signature `def __aiter__(self): ...`
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:14:21
|
12 | # error: [not-iterable] "Object of type `AsyncIterable` is not async-iterable"
13 | async for x in AsyncIterable():
14 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -13,86 +13,71 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.
```
1 | from dataclasses import dataclass, field, KW_ONLY
2 | from typing_extensions import reveal_type
3 |
4 | @dataclass
5 | class C:
6 | x: int
7 | _: KW_ONLY
8 | y: str
9 |
10 | reveal_type(C.__init__) # revealed: (self: C, x: int, *, y: str) -> None
11 |
12 | # error: [missing-argument]
13 | # error: [too-many-positional-arguments]
14 | C(3, "")
15 |
16 | C(3, y="")
17 | @dataclass
18 | class Fails: # error: [duplicate-kw-only]
19 | a: int
20 | b: KW_ONLY
21 | c: str
22 | d: KW_ONLY
23 | e: bytes
24 |
25 | reveal_type(Fails.__init__) # revealed: (self: Fails, a: int, *, c: str, e: bytes) -> None
26 | def flag() -> bool:
27 | return True
28 |
29 | @dataclass
30 | class D: # error: [duplicate-kw-only]
31 | x: int
32 | _1: KW_ONLY
33 |
34 | if flag():
35 | y: str
36 | _2: KW_ONLY
37 | z: float
38 | from dataclasses import dataclass, KW_ONLY
39 |
40 | @dataclass
41 | class D:
42 | x: int
43 | _: KW_ONLY
44 | y: str
45 |
46 | @dataclass
47 | class E(D):
48 | z: bytes
49 |
50 | # This should work: x=1 (positional), z=b"foo" (positional), y="foo" (keyword-only)
51 | E(1, b"foo", y="foo")
52 |
53 | reveal_type(E.__init__) # revealed: (self: E, x: int, z: bytes, *, y: str) -> None
2 |
3 | @dataclass
4 | class C:
5 | x: int
6 | _: KW_ONLY
7 | y: str
8 |
9 | reveal_type(C.__init__) # revealed: (self: C, x: int, *, y: str) -> None
10 |
11 | # error: [missing-argument]
12 | # error: [too-many-positional-arguments]
13 | C(3, "")
14 |
15 | C(3, y="")
16 | @dataclass
17 | class Fails: # error: [duplicate-kw-only]
18 | a: int
19 | b: KW_ONLY
20 | c: str
21 | d: KW_ONLY
22 | e: bytes
23 |
24 | reveal_type(Fails.__init__) # revealed: (self: Fails, a: int, *, c: str, e: bytes) -> None
25 | def flag() -> bool:
26 | return True
27 |
28 | @dataclass
29 | class D: # error: [duplicate-kw-only]
30 | x: int
31 | _1: KW_ONLY
32 |
33 | if flag():
34 | y: str
35 | _2: KW_ONLY
36 | z: float
37 | from dataclasses import dataclass, KW_ONLY
38 |
39 | @dataclass
40 | class D:
41 | x: int
42 | _: KW_ONLY
43 | y: str
44 |
45 | @dataclass
46 | class E(D):
47 | z: bytes
48 |
49 | # This should work: x=1 (positional), z=b"foo" (positional), y="foo" (keyword-only)
50 | E(1, b"foo", y="foo")
51 |
52 | reveal_type(E.__init__) # revealed: (self: E, x: int, z: bytes, *, y: str) -> None
```
# Diagnostics
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:10:13
|
8 | y: str
9 |
10 | reveal_type(C.__init__) # revealed: (self: C, x: int, *, y: str) -> None
| ^^^^^^^^^^ `(self: C, x: int, *, y: str) -> None`
11 |
12 | # error: [missing-argument]
|
```
```
error[missing-argument]: No argument provided for required parameter `y`
--> src/mdtest_snippet.py:14:1
--> src/mdtest_snippet.py:13:1
|
12 | # error: [missing-argument]
13 | # error: [too-many-positional-arguments]
14 | C(3, "")
11 | # error: [missing-argument]
12 | # error: [too-many-positional-arguments]
13 | C(3, "")
| ^^^^^^^^
15 |
16 | C(3, y="")
14 |
15 | C(3, y="")
|
info: rule `missing-argument` is enabled by default
@ -100,14 +85,14 @@ info: rule `missing-argument` is enabled by default
```
error[too-many-positional-arguments]: Too many positional arguments: expected 1, got 2
--> src/mdtest_snippet.py:14:6
--> src/mdtest_snippet.py:13:6
|
12 | # error: [missing-argument]
13 | # error: [too-many-positional-arguments]
14 | C(3, "")
11 | # error: [missing-argument]
12 | # error: [too-many-positional-arguments]
13 | C(3, "")
| ^^
15 |
16 | C(3, y="")
14 |
15 | C(3, y="")
|
info: rule `too-many-positional-arguments` is enabled by default
@ -115,57 +100,31 @@ info: rule `too-many-positional-arguments` is enabled by default
```
error[duplicate-kw-only]: Dataclass has more than one field annotated with `KW_ONLY`
--> src/mdtest_snippet.py:18:7
--> src/mdtest_snippet.py:17:7
|
16 | C(3, y="")
17 | @dataclass
18 | class Fails: # error: [duplicate-kw-only]
15 | C(3, y="")
16 | @dataclass
17 | class Fails: # error: [duplicate-kw-only]
| ^^^^^
19 | a: int
20 | b: KW_ONLY
18 | a: int
19 | b: KW_ONLY
|
info: `KW_ONLY` fields: `b`, `d`
info: rule `duplicate-kw-only` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:25:13
|
23 | e: bytes
24 |
25 | reveal_type(Fails.__init__) # revealed: (self: Fails, a: int, *, c: str, e: bytes) -> None
| ^^^^^^^^^^^^^^ `(self: Fails, a: int, *, c: str, e: bytes) -> None`
26 | def flag() -> bool:
27 | return True
|
```
```
error[duplicate-kw-only]: Dataclass has more than one field annotated with `KW_ONLY`
--> src/mdtest_snippet.py:30:7
--> src/mdtest_snippet.py:29:7
|
29 | @dataclass
30 | class D: # error: [duplicate-kw-only]
28 | @dataclass
29 | class D: # error: [duplicate-kw-only]
| ^
31 | x: int
32 | _1: KW_ONLY
30 | x: int
31 | _1: KW_ONLY
|
info: `KW_ONLY` fields: `_1`, `_2`
info: rule `duplicate-kw-only` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:53:13
|
51 | E(1, b"foo", y="foo")
52 |
53 | reveal_type(E.__init__) # revealed: (self: E, x: int, z: bytes, *, y: str) -> None
| ^^^^^^^^^^ `(self: E, x: int, z: bytes, *, y: str) -> None`
|
```

View file

@ -12,44 +12,30 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Iterable:
4 | # invalid because it will implicitly be passed an `int`
5 | # by the interpreter
6 | def __getitem__(self, key: str) -> int:
7 | return 42
8 |
9 | # error: [not-iterable]
10 | for x in Iterable():
11 | reveal_type(x) # revealed: int
1 | class Iterable:
2 | # invalid because it will implicitly be passed an `int`
3 | # by the interpreter
4 | def __getitem__(self, key: str) -> int:
5 | return 42
6 |
7 | # error: [not-iterable]
8 | for x in Iterable():
9 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable` is not iterable
--> src/mdtest_snippet.py:10:10
|
9 | # error: [not-iterable]
10 | for x in Iterable():
| ^^^^^^^^^^
11 | reveal_type(x) # revealed: int
|
--> src/mdtest_snippet.py:8:10
|
7 | # error: [not-iterable]
8 | for x in Iterable():
| ^^^^^^^^^^
9 | reveal_type(x) # revealed: int
|
info: It has no `__iter__` method and its `__getitem__` method has an incorrect signature for the old-style iteration protocol
info: `__getitem__` must be at least as permissive as `def __getitem__(self, key: int): ...` to satisfy the old-style iteration protocol
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:11:17
|
9 | # error: [not-iterable]
10 | for x in Iterable():
11 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -12,40 +12,26 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Bad:
4 | __getitem__: None = None
5 |
6 | # error: [not-iterable]
7 | for x in Bad():
8 | reveal_type(x) # revealed: Unknown
1 | class Bad:
2 | __getitem__: None = None
3 |
4 | # error: [not-iterable]
5 | for x in Bad():
6 | reveal_type(x) # revealed: Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `Bad` is not iterable
--> src/mdtest_snippet.py:7:10
--> src/mdtest_snippet.py:5:10
|
6 | # error: [not-iterable]
7 | for x in Bad():
4 | # error: [not-iterable]
5 | for x in Bad():
| ^^^^^
8 | reveal_type(x) # revealed: Unknown
6 | reveal_type(x) # revealed: Unknown
|
info: It has no `__iter__` method and its `__getitem__` attribute has type `None`, which is not callable
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:8:17
|
6 | # error: [not-iterable]
7 | for x in Bad():
8 | reveal_type(x) # revealed: Unknown
| ^ `Unknown`
|
```

View file

@ -12,48 +12,46 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | def _(flag: bool):
4 | class CustomCallable:
5 | if flag:
6 | def __call__(self, *args, **kwargs) -> int:
7 | return 42
8 | else:
9 | __call__: None = None
10 |
11 | class Iterable1:
12 | __getitem__: CustomCallable = CustomCallable()
13 |
14 | class Iterable2:
15 | if flag:
16 | def __getitem__(self, key: int) -> int:
17 | return 42
18 | else:
19 | __getitem__: None = None
20 |
21 | # error: [not-iterable]
22 | for x in Iterable1():
23 | # TODO... `int` might be ideal here?
24 | reveal_type(x) # revealed: int | Unknown
25 |
26 | # error: [not-iterable]
27 | for y in Iterable2():
28 | # TODO... `int` might be ideal here?
29 | reveal_type(y) # revealed: int | Unknown
1 | def _(flag: bool):
2 | class CustomCallable:
3 | if flag:
4 | def __call__(self, *args, **kwargs) -> int:
5 | return 42
6 | else:
7 | __call__: None = None
8 |
9 | class Iterable1:
10 | __getitem__: CustomCallable = CustomCallable()
11 |
12 | class Iterable2:
13 | if flag:
14 | def __getitem__(self, key: int) -> int:
15 | return 42
16 | else:
17 | __getitem__: None = None
18 |
19 | # error: [not-iterable]
20 | for x in Iterable1():
21 | # TODO... `int` might be ideal here?
22 | reveal_type(x) # revealed: int | Unknown
23 |
24 | # error: [not-iterable]
25 | for y in Iterable2():
26 | # TODO... `int` might be ideal here?
27 | reveal_type(y) # revealed: int | Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable1` may not be iterable
--> src/mdtest_snippet.py:22:14
--> src/mdtest_snippet.py:20:14
|
21 | # error: [not-iterable]
22 | for x in Iterable1():
19 | # error: [not-iterable]
20 | for x in Iterable1():
| ^^^^^^^^^^^
23 | # TODO... `int` might be ideal here?
24 | reveal_type(x) # revealed: int | Unknown
21 | # TODO... `int` might be ideal here?
22 | reveal_type(x) # revealed: int | Unknown
|
info: It has no `__iter__` method and its `__getitem__` attribute is invalid
info: `__getitem__` has type `CustomCallable`, which is not callable
@ -61,44 +59,18 @@ info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:24:21
|
22 | for x in Iterable1():
23 | # TODO... `int` might be ideal here?
24 | reveal_type(x) # revealed: int | Unknown
| ^ `int | Unknown`
25 |
26 | # error: [not-iterable]
|
```
```
error[not-iterable]: Object of type `Iterable2` may not be iterable
--> src/mdtest_snippet.py:27:14
--> src/mdtest_snippet.py:25:14
|
26 | # error: [not-iterable]
27 | for y in Iterable2():
24 | # error: [not-iterable]
25 | for y in Iterable2():
| ^^^^^^^^^^^
28 | # TODO... `int` might be ideal here?
29 | reveal_type(y) # revealed: int | Unknown
26 | # TODO... `int` might be ideal here?
27 | reveal_type(y) # revealed: int | Unknown
|
info: It has no `__iter__` method and its `__getitem__` attribute is invalid
info: `__getitem__` has type `(bound method Iterable2.__getitem__(key: int) -> int) | None`, which is not callable
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:29:21
|
27 | for y in Iterable2():
28 | # TODO... `int` might be ideal here?
29 | reveal_type(y) # revealed: int | Unknown
| ^ `int | Unknown`
|
```

View file

@ -12,48 +12,46 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Iterator:
4 | def __next__(self) -> int:
5 | return 42
6 |
7 | def _(flag: bool):
8 | class Iterable1:
9 | if flag:
10 | def __iter__(self) -> Iterator:
11 | return Iterator()
12 | else:
13 | def __iter__(self, invalid_extra_arg) -> Iterator:
14 | return Iterator()
15 |
16 | # error: [not-iterable]
17 | for x in Iterable1():
18 | reveal_type(x) # revealed: int
19 |
20 | class Iterable2:
21 | if flag:
22 | def __iter__(self) -> Iterator:
23 | return Iterator()
24 | else:
25 | __iter__: None = None
26 |
27 | # error: [not-iterable]
28 | for x in Iterable2():
29 | # TODO: `int` would probably be better here:
30 | reveal_type(x) # revealed: int | Unknown
1 | class Iterator:
2 | def __next__(self) -> int:
3 | return 42
4 |
5 | def _(flag: bool):
6 | class Iterable1:
7 | if flag:
8 | def __iter__(self) -> Iterator:
9 | return Iterator()
10 | else:
11 | def __iter__(self, invalid_extra_arg) -> Iterator:
12 | return Iterator()
13 |
14 | # error: [not-iterable]
15 | for x in Iterable1():
16 | reveal_type(x) # revealed: int
17 |
18 | class Iterable2:
19 | if flag:
20 | def __iter__(self) -> Iterator:
21 | return Iterator()
22 | else:
23 | __iter__: None = None
24 |
25 | # error: [not-iterable]
26 | for x in Iterable2():
27 | # TODO: `int` would probably be better here:
28 | reveal_type(x) # revealed: int | Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable1` may not be iterable
--> src/mdtest_snippet.py:17:14
--> src/mdtest_snippet.py:15:14
|
16 | # error: [not-iterable]
17 | for x in Iterable1():
14 | # error: [not-iterable]
15 | for x in Iterable1():
| ^^^^^^^^^^^
18 | reveal_type(x) # revealed: int
16 | reveal_type(x) # revealed: int
|
info: Its `__iter__` method may have an invalid signature
info: Type of `__iter__` is `(bound method Iterable1.__iter__() -> Iterator) | (bound method Iterable1.__iter__(invalid_extra_arg) -> Iterator)`
@ -62,43 +60,17 @@ info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:18:21
|
16 | # error: [not-iterable]
17 | for x in Iterable1():
18 | reveal_type(x) # revealed: int
| ^ `int`
19 |
20 | class Iterable2:
|
```
```
error[not-iterable]: Object of type `Iterable2` may not be iterable
--> src/mdtest_snippet.py:28:14
--> src/mdtest_snippet.py:26:14
|
27 | # error: [not-iterable]
28 | for x in Iterable2():
25 | # error: [not-iterable]
26 | for x in Iterable2():
| ^^^^^^^^^^^
29 | # TODO: `int` would probably be better here:
30 | reveal_type(x) # revealed: int | Unknown
27 | # TODO: `int` would probably be better here:
28 | reveal_type(x) # revealed: int | Unknown
|
info: Its `__iter__` attribute (with type `(bound method Iterable2.__iter__() -> Iterator) | None`) may not be callable
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:30:21
|
28 | for x in Iterable2():
29 | # TODO: `int` would probably be better here:
30 | reveal_type(x) # revealed: int | Unknown
| ^ `int | Unknown`
|
```

View file

@ -12,45 +12,43 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | def _(flag: bool):
4 | class Iterable1:
5 | if flag:
6 | def __getitem__(self, item: int) -> str:
7 | return "foo"
8 | else:
9 | __getitem__: None = None
10 |
11 | class Iterable2:
12 | if flag:
13 | def __getitem__(self, item: int) -> str:
14 | return "foo"
15 | else:
16 | def __getitem__(self, item: str) -> int:
17 | return 42
18 |
19 | # error: [not-iterable]
20 | for x in Iterable1():
21 | # TODO: `str` might be better
22 | reveal_type(x) # revealed: str | Unknown
23 |
24 | # error: [not-iterable]
25 | for y in Iterable2():
26 | reveal_type(y) # revealed: str | int
1 | def _(flag: bool):
2 | class Iterable1:
3 | if flag:
4 | def __getitem__(self, item: int) -> str:
5 | return "foo"
6 | else:
7 | __getitem__: None = None
8 |
9 | class Iterable2:
10 | if flag:
11 | def __getitem__(self, item: int) -> str:
12 | return "foo"
13 | else:
14 | def __getitem__(self, item: str) -> int:
15 | return 42
16 |
17 | # error: [not-iterable]
18 | for x in Iterable1():
19 | # TODO: `str` might be better
20 | reveal_type(x) # revealed: str | Unknown
21 |
22 | # error: [not-iterable]
23 | for y in Iterable2():
24 | reveal_type(y) # revealed: str | int
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable1` may not be iterable
--> src/mdtest_snippet.py:20:14
--> src/mdtest_snippet.py:18:14
|
19 | # error: [not-iterable]
20 | for x in Iterable1():
17 | # error: [not-iterable]
18 | for x in Iterable1():
| ^^^^^^^^^^^
21 | # TODO: `str` might be better
22 | reveal_type(x) # revealed: str | Unknown
19 | # TODO: `str` might be better
20 | reveal_type(x) # revealed: str | Unknown
|
info: It has no `__iter__` method and its `__getitem__` attribute is invalid
info: `__getitem__` has type `(bound method Iterable1.__getitem__(item: int) -> str) | None`, which is not callable
@ -58,43 +56,17 @@ info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:22:21
|
20 | for x in Iterable1():
21 | # TODO: `str` might be better
22 | reveal_type(x) # revealed: str | Unknown
| ^ `str | Unknown`
23 |
24 | # error: [not-iterable]
|
```
```
error[not-iterable]: Object of type `Iterable2` may not be iterable
--> src/mdtest_snippet.py:25:14
--> src/mdtest_snippet.py:23:14
|
24 | # error: [not-iterable]
25 | for y in Iterable2():
22 | # error: [not-iterable]
23 | for y in Iterable2():
| ^^^^^^^^^^^
26 | reveal_type(y) # revealed: str | int
24 | reveal_type(y) # revealed: str | int
|
info: It has no `__iter__` method and its `__getitem__` method (with type `(bound method Iterable2.__getitem__(item: int) -> str) | (bound method Iterable2.__getitem__(item: str) -> int)`) may have an incorrect signature for the old-style iteration protocol
info: `__getitem__` must be at least as permissive as `def __getitem__(self, key: int): ...` to satisfy the old-style iteration protocol
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:26:21
|
24 | # error: [not-iterable]
25 | for y in Iterable2():
26 | reveal_type(y) # revealed: str | int
| ^ `str | int`
|
```

View file

@ -12,52 +12,50 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | def _(flag: bool):
4 | class Iterator1:
5 | if flag:
6 | def __next__(self) -> int:
7 | return 42
8 | else:
9 | def __next__(self, invalid_extra_arg) -> str:
10 | return "foo"
11 |
12 | class Iterator2:
13 | if flag:
14 | def __next__(self) -> int:
15 | return 42
16 | else:
17 | __next__: None = None
18 |
19 | class Iterable1:
20 | def __iter__(self) -> Iterator1:
21 | return Iterator1()
22 |
23 | class Iterable2:
24 | def __iter__(self) -> Iterator2:
25 | return Iterator2()
26 |
27 | # error: [not-iterable]
28 | for x in Iterable1():
29 | reveal_type(x) # revealed: int | str
30 |
31 | # error: [not-iterable]
32 | for y in Iterable2():
33 | # TODO: `int` would probably be better here:
34 | reveal_type(y) # revealed: int | Unknown
1 | def _(flag: bool):
2 | class Iterator1:
3 | if flag:
4 | def __next__(self) -> int:
5 | return 42
6 | else:
7 | def __next__(self, invalid_extra_arg) -> str:
8 | return "foo"
9 |
10 | class Iterator2:
11 | if flag:
12 | def __next__(self) -> int:
13 | return 42
14 | else:
15 | __next__: None = None
16 |
17 | class Iterable1:
18 | def __iter__(self) -> Iterator1:
19 | return Iterator1()
20 |
21 | class Iterable2:
22 | def __iter__(self) -> Iterator2:
23 | return Iterator2()
24 |
25 | # error: [not-iterable]
26 | for x in Iterable1():
27 | reveal_type(x) # revealed: int | str
28 |
29 | # error: [not-iterable]
30 | for y in Iterable2():
31 | # TODO: `int` would probably be better here:
32 | reveal_type(y) # revealed: int | Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable1` may not be iterable
--> src/mdtest_snippet.py:28:14
--> src/mdtest_snippet.py:26:14
|
27 | # error: [not-iterable]
28 | for x in Iterable1():
25 | # error: [not-iterable]
26 | for x in Iterable1():
| ^^^^^^^^^^^
29 | reveal_type(x) # revealed: int | str
27 | reveal_type(x) # revealed: int | str
|
info: Its `__iter__` method returns an object of type `Iterator1`, which may have an invalid `__next__` method
info: Expected signature for `__next__` is `def __next__(self): ...`
@ -65,43 +63,17 @@ info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:29:21
|
27 | # error: [not-iterable]
28 | for x in Iterable1():
29 | reveal_type(x) # revealed: int | str
| ^ `int | str`
30 |
31 | # error: [not-iterable]
|
```
```
error[not-iterable]: Object of type `Iterable2` may not be iterable
--> src/mdtest_snippet.py:32:14
--> src/mdtest_snippet.py:30:14
|
31 | # error: [not-iterable]
32 | for y in Iterable2():
29 | # error: [not-iterable]
30 | for y in Iterable2():
| ^^^^^^^^^^^
33 | # TODO: `int` would probably be better here:
34 | reveal_type(y) # revealed: int | Unknown
31 | # TODO: `int` would probably be better here:
32 | reveal_type(y) # revealed: int | Unknown
|
info: Its `__iter__` method returns an object of type `Iterator2`, which has a `__next__` attribute that may not be callable
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:34:21
|
32 | for y in Iterable2():
33 | # TODO: `int` would probably be better here:
34 | reveal_type(y) # revealed: int | Unknown
| ^ `int | Unknown`
|
```

View file

@ -12,99 +12,71 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Iterator:
4 | def __next__(self) -> bytes:
5 | return b"foo"
6 |
7 | def _(flag: bool, flag2: bool):
8 | class Iterable1:
9 | if flag:
10 | def __getitem__(self, item: int) -> str:
11 | return "foo"
12 | else:
13 | __getitem__: None = None
14 |
15 | if flag2:
16 | def __iter__(self) -> Iterator:
17 | return Iterator()
18 |
19 | class Iterable2:
20 | if flag:
21 | def __getitem__(self, item: int) -> str:
22 | return "foo"
23 | else:
24 | def __getitem__(self, item: str) -> int:
25 | return 42
26 | if flag2:
27 | def __iter__(self) -> Iterator:
28 | return Iterator()
29 |
30 | # error: [not-iterable]
31 | for x in Iterable1():
32 | # TODO: `bytes | str` might be better
33 | reveal_type(x) # revealed: bytes | str | Unknown
34 |
35 | # error: [not-iterable]
36 | for y in Iterable2():
37 | reveal_type(y) # revealed: bytes | str | int
1 | class Iterator:
2 | def __next__(self) -> bytes:
3 | return b"foo"
4 |
5 | def _(flag: bool, flag2: bool):
6 | class Iterable1:
7 | if flag:
8 | def __getitem__(self, item: int) -> str:
9 | return "foo"
10 | else:
11 | __getitem__: None = None
12 |
13 | if flag2:
14 | def __iter__(self) -> Iterator:
15 | return Iterator()
16 |
17 | class Iterable2:
18 | if flag:
19 | def __getitem__(self, item: int) -> str:
20 | return "foo"
21 | else:
22 | def __getitem__(self, item: str) -> int:
23 | return 42
24 | if flag2:
25 | def __iter__(self) -> Iterator:
26 | return Iterator()
27 |
28 | # error: [not-iterable]
29 | for x in Iterable1():
30 | # TODO: `bytes | str` might be better
31 | reveal_type(x) # revealed: bytes | str | Unknown
32 |
33 | # error: [not-iterable]
34 | for y in Iterable2():
35 | reveal_type(y) # revealed: bytes | str | int
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable1` may not be iterable
--> src/mdtest_snippet.py:31:14
--> src/mdtest_snippet.py:29:14
|
30 | # error: [not-iterable]
31 | for x in Iterable1():
28 | # error: [not-iterable]
29 | for x in Iterable1():
| ^^^^^^^^^^^
32 | # TODO: `bytes | str` might be better
33 | reveal_type(x) # revealed: bytes | str | Unknown
30 | # TODO: `bytes | str` might be better
31 | reveal_type(x) # revealed: bytes | str | Unknown
|
info: It may not have an `__iter__` method and its `__getitem__` attribute (with type `(bound method Iterable1.__getitem__(item: int) -> str) | None`) may not be callable
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:33:21
|
31 | for x in Iterable1():
32 | # TODO: `bytes | str` might be better
33 | reveal_type(x) # revealed: bytes | str | Unknown
| ^ `bytes | str | Unknown`
34 |
35 | # error: [not-iterable]
|
```
```
error[not-iterable]: Object of type `Iterable2` may not be iterable
--> src/mdtest_snippet.py:36:14
--> src/mdtest_snippet.py:34:14
|
35 | # error: [not-iterable]
36 | for y in Iterable2():
33 | # error: [not-iterable]
34 | for y in Iterable2():
| ^^^^^^^^^^^
37 | reveal_type(y) # revealed: bytes | str | int
35 | reveal_type(y) # revealed: bytes | str | int
|
info: It may not have an `__iter__` method and its `__getitem__` method (with type `(bound method Iterable2.__getitem__(item: int) -> str) | (bound method Iterable2.__getitem__(item: str) -> int)`) may have an incorrect signature for the old-style iteration protocol
info: `__getitem__` must be at least as permissive as `def __getitem__(self, key: int): ...` to satisfy the old-style iteration protocol
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:37:21
|
35 | # error: [not-iterable]
36 | for y in Iterable2():
37 | reveal_type(y) # revealed: bytes | str | int
| ^ `bytes | str | int`
|
```

View file

@ -12,52 +12,38 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | def _(flag: bool):
4 | class Iterator:
5 | def __next__(self) -> int:
6 | return 42
7 |
8 | class Iterable:
9 | if flag:
10 | def __iter__(self) -> Iterator:
11 | return Iterator()
12 | # invalid signature because it only accepts a `str`,
13 | # but the old-style iteration protocol will pass it an `int`
14 | def __getitem__(self, key: str) -> bytes:
15 | return bytes()
16 |
17 | # error: [not-iterable]
18 | for x in Iterable():
19 | reveal_type(x) # revealed: int | bytes
1 | def _(flag: bool):
2 | class Iterator:
3 | def __next__(self) -> int:
4 | return 42
5 |
6 | class Iterable:
7 | if flag:
8 | def __iter__(self) -> Iterator:
9 | return Iterator()
10 | # invalid signature because it only accepts a `str`,
11 | # but the old-style iteration protocol will pass it an `int`
12 | def __getitem__(self, key: str) -> bytes:
13 | return bytes()
14 |
15 | # error: [not-iterable]
16 | for x in Iterable():
17 | reveal_type(x) # revealed: int | bytes
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable` may not be iterable
--> src/mdtest_snippet.py:18:14
--> src/mdtest_snippet.py:16:14
|
17 | # error: [not-iterable]
18 | for x in Iterable():
15 | # error: [not-iterable]
16 | for x in Iterable():
| ^^^^^^^^^^
19 | reveal_type(x) # revealed: int | bytes
17 | reveal_type(x) # revealed: int | bytes
|
info: It may not have an `__iter__` method and its `__getitem__` method has an incorrect signature for the old-style iteration protocol
info: `__getitem__` must be at least as permissive as `def __getitem__(self, key: int): ...` to satisfy the old-style iteration protocol
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:19:21
|
17 | # error: [not-iterable]
18 | for x in Iterable():
19 | reveal_type(x) # revealed: int | bytes
| ^ `int | bytes`
|
```

View file

@ -12,50 +12,36 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Iterator:
4 | def __next__(self) -> int:
5 | return 42
6 |
7 | def _(flag1: bool, flag2: bool):
8 | class Iterable:
9 | if flag1:
10 | def __iter__(self) -> Iterator:
11 | return Iterator()
12 | if flag2:
13 | def __getitem__(self, key: int) -> bytes:
14 | return bytes()
15 |
16 | # error: [not-iterable]
17 | for x in Iterable():
18 | reveal_type(x) # revealed: int | bytes
1 | class Iterator:
2 | def __next__(self) -> int:
3 | return 42
4 |
5 | def _(flag1: bool, flag2: bool):
6 | class Iterable:
7 | if flag1:
8 | def __iter__(self) -> Iterator:
9 | return Iterator()
10 | if flag2:
11 | def __getitem__(self, key: int) -> bytes:
12 | return bytes()
13 |
14 | # error: [not-iterable]
15 | for x in Iterable():
16 | reveal_type(x) # revealed: int | bytes
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable` may not be iterable
--> src/mdtest_snippet.py:17:14
--> src/mdtest_snippet.py:15:14
|
16 | # error: [not-iterable]
17 | for x in Iterable():
14 | # error: [not-iterable]
15 | for x in Iterable():
| ^^^^^^^^^^
18 | reveal_type(x) # revealed: int | bytes
16 | reveal_type(x) # revealed: int | bytes
|
info: It may not have an `__iter__` method or a `__getitem__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:18:21
|
16 | # error: [not-iterable]
17 | for x in Iterable():
18 | reveal_type(x) # revealed: int | bytes
| ^ `int | bytes`
|
```

View file

@ -12,52 +12,38 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class TestIter:
4 | def __next__(self) -> int:
5 | return 42
6 |
7 | class Test:
8 | def __iter__(self) -> TestIter:
9 | return TestIter()
10 |
11 | class Test2:
12 | def __iter__(self) -> int:
13 | return 42
14 |
15 | def _(flag: bool):
16 | # TODO: Improve error message to state which union variant isn't iterable (https://github.com/astral-sh/ruff/issues/13989)
17 | # error: [not-iterable]
18 | for x in Test() if flag else Test2():
19 | reveal_type(x) # revealed: int
1 | class TestIter:
2 | def __next__(self) -> int:
3 | return 42
4 |
5 | class Test:
6 | def __iter__(self) -> TestIter:
7 | return TestIter()
8 |
9 | class Test2:
10 | def __iter__(self) -> int:
11 | return 42
12 |
13 | def _(flag: bool):
14 | # TODO: Improve error message to state which union variant isn't iterable (https://github.com/astral-sh/ruff/issues/13989)
15 | # error: [not-iterable]
16 | for x in Test() if flag else Test2():
17 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `Test | Test2` may not be iterable
--> src/mdtest_snippet.py:18:14
--> src/mdtest_snippet.py:16:14
|
16 | # TODO: Improve error message to state which union variant isn't iterable (https://github.com/astral-sh/ruff/issues/13989)
17 | # error: [not-iterable]
18 | for x in Test() if flag else Test2():
14 | # TODO: Improve error message to state which union variant isn't iterable (https://github.com/astral-sh/ruff/issues/13989)
15 | # error: [not-iterable]
16 | for x in Test() if flag else Test2():
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
19 | reveal_type(x) # revealed: int
17 | reveal_type(x) # revealed: int
|
info: Its `__iter__` method returns an object of type `TestIter | int`, which may not have a `__next__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:19:21
|
17 | # error: [not-iterable]
18 | for x in Test() if flag else Test2():
19 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -12,47 +12,33 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class TestIter:
4 | def __next__(self) -> int:
5 | return 42
6 |
7 | class Test:
8 | def __iter__(self) -> TestIter:
9 | return TestIter()
10 |
11 | def _(flag: bool):
12 | # error: [not-iterable]
13 | for x in Test() if flag else 42:
14 | reveal_type(x) # revealed: int
1 | class TestIter:
2 | def __next__(self) -> int:
3 | return 42
4 |
5 | class Test:
6 | def __iter__(self) -> TestIter:
7 | return TestIter()
8 |
9 | def _(flag: bool):
10 | # error: [not-iterable]
11 | for x in Test() if flag else 42:
12 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `Test | Literal[42]` may not be iterable
--> src/mdtest_snippet.py:13:14
--> src/mdtest_snippet.py:11:14
|
11 | def _(flag: bool):
12 | # error: [not-iterable]
13 | for x in Test() if flag else 42:
9 | def _(flag: bool):
10 | # error: [not-iterable]
11 | for x in Test() if flag else 42:
| ^^^^^^^^^^^^^^^^^^^^^^
14 | reveal_type(x) # revealed: int
12 | reveal_type(x) # revealed: int
|
info: It may not have an `__iter__` method and it doesn't have a `__getitem__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:14:21
|
12 | # error: [not-iterable]
13 | for x in Test() if flag else 42:
14 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -12,34 +12,32 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | def _(flag: bool):
4 | class NotIterable:
5 | if flag:
6 | __iter__: int = 1
7 | else:
8 | __iter__: None = None
9 |
10 | # error: [not-iterable]
11 | for x in NotIterable():
12 | pass
13 |
14 | # revealed: Unknown
15 | # error: [possibly-unresolved-reference]
16 | reveal_type(x)
1 | def _(flag: bool):
2 | class NotIterable:
3 | if flag:
4 | __iter__: int = 1
5 | else:
6 | __iter__: None = None
7 |
8 | # error: [not-iterable]
9 | for x in NotIterable():
10 | pass
11 |
12 | # revealed: Unknown
13 | # error: [possibly-unresolved-reference]
14 | reveal_type(x)
```
# Diagnostics
```
error[not-iterable]: Object of type `NotIterable` is not iterable
--> src/mdtest_snippet.py:11:14
--> src/mdtest_snippet.py:9:14
|
10 | # error: [not-iterable]
11 | for x in NotIterable():
8 | # error: [not-iterable]
9 | for x in NotIterable():
| ^^^^^^^^^^^^^
12 | pass
10 | pass
|
info: Its `__iter__` attribute has type `int | None`, which is not callable
info: rule `not-iterable` is enabled by default
@ -48,25 +46,13 @@ info: rule `not-iterable` is enabled by default
```
info[possibly-unresolved-reference]: Name `x` used when possibly not defined
--> src/mdtest_snippet.py:16:17
--> src/mdtest_snippet.py:14:17
|
14 | # revealed: Unknown
15 | # error: [possibly-unresolved-reference]
16 | reveal_type(x)
12 | # revealed: Unknown
13 | # error: [possibly-unresolved-reference]
14 | reveal_type(x)
| ^
|
info: rule `possibly-unresolved-reference` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:16:17
|
14 | # revealed: Unknown
15 | # error: [possibly-unresolved-reference]
16 | reveal_type(x)
| ^ `Unknown`
|
```

View file

@ -12,41 +12,27 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Bad:
4 | def __iter__(self) -> int:
5 | return 42
6 |
7 | # error: [not-iterable]
8 | for x in Bad():
9 | reveal_type(x) # revealed: Unknown
1 | class Bad:
2 | def __iter__(self) -> int:
3 | return 42
4 |
5 | # error: [not-iterable]
6 | for x in Bad():
7 | reveal_type(x) # revealed: Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `Bad` is not iterable
--> src/mdtest_snippet.py:8:10
--> src/mdtest_snippet.py:6:10
|
7 | # error: [not-iterable]
8 | for x in Bad():
5 | # error: [not-iterable]
6 | for x in Bad():
| ^^^^^
9 | reveal_type(x) # revealed: Unknown
7 | reveal_type(x) # revealed: Unknown
|
info: Its `__iter__` method returns an object of type `int`, which has no `__next__` method
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:9:17
|
7 | # error: [not-iterable]
8 | for x in Bad():
9 | reveal_type(x) # revealed: Unknown
| ^ `Unknown`
|
```

View file

@ -12,46 +12,32 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Iterator:
4 | def __next__(self) -> int:
5 | return 42
6 |
7 | class Iterable:
8 | def __iter__(self, extra_arg) -> Iterator:
9 | return Iterator()
10 |
11 | # error: [not-iterable]
12 | for x in Iterable():
13 | reveal_type(x) # revealed: int
1 | class Iterator:
2 | def __next__(self) -> int:
3 | return 42
4 |
5 | class Iterable:
6 | def __iter__(self, extra_arg) -> Iterator:
7 | return Iterator()
8 |
9 | # error: [not-iterable]
10 | for x in Iterable():
11 | reveal_type(x) # revealed: int
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable` is not iterable
--> src/mdtest_snippet.py:12:10
--> src/mdtest_snippet.py:10:10
|
11 | # error: [not-iterable]
12 | for x in Iterable():
9 | # error: [not-iterable]
10 | for x in Iterable():
| ^^^^^^^^^^
13 | reveal_type(x) # revealed: int
11 | reveal_type(x) # revealed: int
|
info: Its `__iter__` method has an invalid signature
info: Expected signature `def __iter__(self): ...`
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:13:17
|
11 | # error: [not-iterable]
12 | for x in Iterable():
13 | reveal_type(x) # revealed: int
| ^ `int`
|
```

View file

@ -12,42 +12,40 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/loops/for.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | class Iterator1:
4 | def __next__(self, extra_arg) -> int:
5 | return 42
6 |
7 | class Iterator2:
8 | __next__: None = None
9 |
10 | class Iterable1:
11 | def __iter__(self) -> Iterator1:
12 | return Iterator1()
13 |
14 | class Iterable2:
15 | def __iter__(self) -> Iterator2:
16 | return Iterator2()
17 |
18 | # error: [not-iterable]
19 | for x in Iterable1():
20 | reveal_type(x) # revealed: int
21 |
22 | # error: [not-iterable]
23 | for y in Iterable2():
24 | reveal_type(y) # revealed: Unknown
1 | class Iterator1:
2 | def __next__(self, extra_arg) -> int:
3 | return 42
4 |
5 | class Iterator2:
6 | __next__: None = None
7 |
8 | class Iterable1:
9 | def __iter__(self) -> Iterator1:
10 | return Iterator1()
11 |
12 | class Iterable2:
13 | def __iter__(self) -> Iterator2:
14 | return Iterator2()
15 |
16 | # error: [not-iterable]
17 | for x in Iterable1():
18 | reveal_type(x) # revealed: int
19 |
20 | # error: [not-iterable]
21 | for y in Iterable2():
22 | reveal_type(y) # revealed: Unknown
```
# Diagnostics
```
error[not-iterable]: Object of type `Iterable1` is not iterable
--> src/mdtest_snippet.py:19:10
--> src/mdtest_snippet.py:17:10
|
18 | # error: [not-iterable]
19 | for x in Iterable1():
16 | # error: [not-iterable]
17 | for x in Iterable1():
| ^^^^^^^^^^^
20 | reveal_type(x) # revealed: int
18 | reveal_type(x) # revealed: int
|
info: Its `__iter__` method returns an object of type `Iterator1`, which has an invalid `__next__` method
info: Expected signature for `__next__` is `def __next__(self): ...`
@ -55,42 +53,16 @@ info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:20:17
|
18 | # error: [not-iterable]
19 | for x in Iterable1():
20 | reveal_type(x) # revealed: int
| ^ `int`
21 |
22 | # error: [not-iterable]
|
```
```
error[not-iterable]: Object of type `Iterable2` is not iterable
--> src/mdtest_snippet.py:23:10
--> src/mdtest_snippet.py:21:10
|
22 | # error: [not-iterable]
23 | for y in Iterable2():
20 | # error: [not-iterable]
21 | for y in Iterable2():
| ^^^^^^^^^^^
24 | reveal_type(y) # revealed: Unknown
22 | reveal_type(y) # revealed: Unknown
|
info: Its `__iter__` method returns an object of type `Iterator2`, which has a `__next__` attribute that is not callable
info: rule `not-iterable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:24:17
|
22 | # error: [not-iterable]
23 | for y in Iterable2():
24 | reveal_type(y) # revealed: Unknown
| ^ `Unknown`
|
```

View file

@ -13,78 +13,38 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/generics/legacy/function
```
1 | from typing import TypeVar
2 | from typing_extensions import reveal_type
3 |
4 | T = TypeVar("T", bound=int)
5 |
6 | def f(x: T) -> T:
7 | return x
8 |
9 | reveal_type(f(1)) # revealed: Literal[1]
10 | reveal_type(f(True)) # revealed: Literal[True]
11 | # error: [invalid-argument-type]
12 | reveal_type(f("string")) # revealed: Unknown
2 |
3 | T = TypeVar("T", bound=int)
4 |
5 | def f(x: T) -> T:
6 | return x
7 |
8 | reveal_type(f(1)) # revealed: Literal[1]
9 | reveal_type(f(True)) # revealed: Literal[True]
10 | # error: [invalid-argument-type]
11 | reveal_type(f("string")) # revealed: Unknown
```
# Diagnostics
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:9:13
|
7 | return x
8 |
9 | reveal_type(f(1)) # revealed: Literal[1]
| ^^^^ `Literal[1]`
10 | reveal_type(f(True)) # revealed: Literal[True]
11 | # error: [invalid-argument-type]
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:10:13
|
9 | reveal_type(f(1)) # revealed: Literal[1]
10 | reveal_type(f(True)) # revealed: Literal[True]
| ^^^^^^^ `Literal[True]`
11 | # error: [invalid-argument-type]
12 | reveal_type(f("string")) # revealed: Unknown
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:12:13
|
10 | reveal_type(f(True)) # revealed: Literal[True]
11 | # error: [invalid-argument-type]
12 | reveal_type(f("string")) # revealed: Unknown
| ^^^^^^^^^^^ `Unknown`
|
```
```
error[invalid-argument-type]: Argument to function `f` is incorrect
--> src/mdtest_snippet.py:12:15
--> src/mdtest_snippet.py:11:15
|
10 | reveal_type(f(True)) # revealed: Literal[True]
11 | # error: [invalid-argument-type]
12 | reveal_type(f("string")) # revealed: Unknown
9 | reveal_type(f(True)) # revealed: Literal[True]
10 | # error: [invalid-argument-type]
11 | reveal_type(f("string")) # revealed: Unknown
| ^^^^^^^^ Argument type `Literal["string"]` does not satisfy upper bound `int` of type variable `T`
|
info: Type variable defined here
--> src/mdtest_snippet.py:4:1
--> src/mdtest_snippet.py:3:1
|
2 | from typing_extensions import reveal_type
3 |
4 | T = TypeVar("T", bound=int)
1 | from typing import TypeVar
2 |
3 | T = TypeVar("T", bound=int)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 |
6 | def f(x: T) -> T:
4 |
5 | def f(x: T) -> T:
|
info: rule `invalid-argument-type` is enabled by default

View file

@ -13,93 +13,39 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/generics/legacy/function
```
1 | from typing import TypeVar
2 | from typing_extensions import reveal_type
3 |
4 | T = TypeVar("T", int, None)
5 |
6 | def f(x: T) -> T:
7 | return x
8 |
9 | reveal_type(f(1)) # revealed: int
10 | reveal_type(f(True)) # revealed: int
11 | reveal_type(f(None)) # revealed: None
12 | # error: [invalid-argument-type]
13 | reveal_type(f("string")) # revealed: Unknown
2 |
3 | T = TypeVar("T", int, None)
4 |
5 | def f(x: T) -> T:
6 | return x
7 |
8 | reveal_type(f(1)) # revealed: int
9 | reveal_type(f(True)) # revealed: int
10 | reveal_type(f(None)) # revealed: None
11 | # error: [invalid-argument-type]
12 | reveal_type(f("string")) # revealed: Unknown
```
# Diagnostics
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:9:13
|
7 | return x
8 |
9 | reveal_type(f(1)) # revealed: int
| ^^^^ `int`
10 | reveal_type(f(True)) # revealed: int
11 | reveal_type(f(None)) # revealed: None
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:10:13
|
9 | reveal_type(f(1)) # revealed: int
10 | reveal_type(f(True)) # revealed: int
| ^^^^^^^ `int`
11 | reveal_type(f(None)) # revealed: None
12 | # error: [invalid-argument-type]
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:11:13
|
9 | reveal_type(f(1)) # revealed: int
10 | reveal_type(f(True)) # revealed: int
11 | reveal_type(f(None)) # revealed: None
| ^^^^^^^ `None`
12 | # error: [invalid-argument-type]
13 | reveal_type(f("string")) # revealed: Unknown
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:13:13
|
11 | reveal_type(f(None)) # revealed: None
12 | # error: [invalid-argument-type]
13 | reveal_type(f("string")) # revealed: Unknown
| ^^^^^^^^^^^ `Unknown`
|
```
```
error[invalid-argument-type]: Argument to function `f` is incorrect
--> src/mdtest_snippet.py:13:15
--> src/mdtest_snippet.py:12:15
|
11 | reveal_type(f(None)) # revealed: None
12 | # error: [invalid-argument-type]
13 | reveal_type(f("string")) # revealed: Unknown
10 | reveal_type(f(None)) # revealed: None
11 | # error: [invalid-argument-type]
12 | reveal_type(f("string")) # revealed: Unknown
| ^^^^^^^^ Argument type `Literal["string"]` does not satisfy constraints (`int`, `None`) of type variable `T`
|
info: Type variable defined here
--> src/mdtest_snippet.py:4:1
--> src/mdtest_snippet.py:3:1
|
2 | from typing_extensions import reveal_type
3 |
4 | T = TypeVar("T", int, None)
1 | from typing import TypeVar
2 |
3 | T = TypeVar("T", int, None)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 |
6 | def f(x: T) -> T:
4 |
5 | def f(x: T) -> T:
|
info: rule `invalid-argument-type` is enabled by default

View file

@ -25,45 +25,6 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/generics/pep695/function
# Diagnostics
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:6:13
|
4 | return x
5 |
6 | reveal_type(f(1)) # revealed: Literal[1]
| ^^^^ `Literal[1]`
7 | reveal_type(f(True)) # revealed: Literal[True]
8 | # error: [invalid-argument-type]
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:7:13
|
6 | reveal_type(f(1)) # revealed: Literal[1]
7 | reveal_type(f(True)) # revealed: Literal[True]
| ^^^^^^^ `Literal[True]`
8 | # error: [invalid-argument-type]
9 | reveal_type(f("string")) # revealed: Unknown
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:9:13
|
7 | reveal_type(f(True)) # revealed: Literal[True]
8 | # error: [invalid-argument-type]
9 | reveal_type(f("string")) # revealed: Unknown
| ^^^^^^^^^^^ `Unknown`
|
```
```
error[invalid-argument-type]: Argument to function `f` is incorrect
--> src/mdtest_snippet.py:9:15

View file

@ -26,59 +26,6 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/generics/pep695/function
# Diagnostics
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:6:13
|
4 | return x
5 |
6 | reveal_type(f(1)) # revealed: int
| ^^^^ `int`
7 | reveal_type(f(True)) # revealed: int
8 | reveal_type(f(None)) # revealed: None
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:7:13
|
6 | reveal_type(f(1)) # revealed: int
7 | reveal_type(f(True)) # revealed: int
| ^^^^^^^ `int`
8 | reveal_type(f(None)) # revealed: None
9 | # error: [invalid-argument-type]
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:8:13
|
6 | reveal_type(f(1)) # revealed: int
7 | reveal_type(f(True)) # revealed: int
8 | reveal_type(f(None)) # revealed: None
| ^^^^^^^ `None`
9 | # error: [invalid-argument-type]
10 | reveal_type(f("string")) # revealed: Unknown
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:10:13
|
8 | reveal_type(f(None)) # revealed: None
9 | # error: [invalid-argument-type]
10 | reveal_type(f("string")) # revealed: Unknown
| ^^^^^^^^^^^ `Unknown`
|
```
```
error[invalid-argument-type]: Argument to function `f` is incorrect
--> src/mdtest_snippet.py:10:15

View file

@ -12,67 +12,39 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/mro.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
2 |
3 | def returns_bool() -> bool:
4 | return True
5 |
6 | class A: ...
7 | class B: ...
8 |
9 | if returns_bool():
10 | x = A
11 | else:
12 | x = B
1 | def returns_bool() -> bool:
2 | return True
3 |
4 | class A: ...
5 | class B: ...
6 |
7 | if returns_bool():
8 | x = A
9 | else:
10 | x = B
11 |
12 | reveal_type(x) # revealed: <class 'A'> | <class 'B'>
13 |
14 | reveal_type(x) # revealed: <class 'A'> | <class 'B'>
15 |
16 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
17 | class Foo(x): ...
18 |
19 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
14 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
15 | class Foo(x): ...
16 |
17 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
```
# Diagnostics
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:14:13
|
12 | x = B
13 |
14 | reveal_type(x) # revealed: <class 'A'> | <class 'B'>
| ^ `<class 'A'> | <class 'B'>`
15 |
16 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
|
```
```
warning[unsupported-base]: Unsupported class base with type `<class 'A'> | <class 'B'>`
--> src/mdtest_snippet.py:17:11
--> src/mdtest_snippet.py:15:11
|
16 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
17 | class Foo(x): ...
14 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
15 | class Foo(x): ...
| ^
18 |
19 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
16 |
17 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
info: ty cannot resolve a consistent MRO for class `Foo` due to this base
info: Only class objects or `Any` are supported as class bases
info: rule `unsupported-base` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:19:13
|
17 | class Foo(x): ...
18 |
19 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
| ^^^^^^^^^^^ `tuple[<class 'Foo'>, Unknown, <class 'object'>]`
|
```

View file

@ -12,167 +12,147 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/mro.md
## mdtest_snippet.py
```
1 | from typing_extensions import reveal_type
1 | class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
2 |
3 | class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
3 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
4 |
5 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
6 |
7 | class Spam: ...
8 | class Eggs: ...
9 | class Bar: ...
10 | class Baz: ...
5 | class Spam: ...
6 | class Eggs: ...
7 | class Bar: ...
8 | class Baz: ...
9 |
10 | # fmt: off
11 |
12 | # fmt: off
13 |
14 | # error: [duplicate-base] "Duplicate base class `Spam`"
15 | # error: [duplicate-base] "Duplicate base class `Eggs`"
16 | class Ham(
17 | Spam,
18 | Eggs,
19 | Bar,
20 | Baz,
21 | Spam,
22 | Eggs,
23 | ): ...
12 | # error: [duplicate-base] "Duplicate base class `Spam`"
13 | # error: [duplicate-base] "Duplicate base class `Eggs`"
14 | class Ham(
15 | Spam,
16 | Eggs,
17 | Bar,
18 | Baz,
19 | Spam,
20 | Eggs,
21 | ): ...
22 |
23 | # fmt: on
24 |
25 | # fmt: on
25 | reveal_type(Ham.__mro__) # revealed: tuple[<class 'Ham'>, Unknown, <class 'object'>]
26 |
27 | reveal_type(Ham.__mro__) # revealed: tuple[<class 'Ham'>, Unknown, <class 'object'>]
28 |
29 | class Mushrooms: ...
30 | class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
27 | class Mushrooms: ...
28 | class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
29 |
30 | reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
31 |
32 | reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
32 | # fmt: off
33 |
34 | # fmt: off
35 |
36 | # error: [duplicate-base] "Duplicate base class `Eggs`"
37 | class VeryEggyOmelette(
38 | Eggs,
39 | Ham,
40 | Spam,
41 | Eggs,
42 | Mushrooms,
43 | Bar,
34 | # error: [duplicate-base] "Duplicate base class `Eggs`"
35 | class VeryEggyOmelette(
36 | Eggs,
37 | Ham,
38 | Spam,
39 | Eggs,
40 | Mushrooms,
41 | Bar,
42 | Eggs,
43 | Baz,
44 | Eggs,
45 | Baz,
46 | Eggs,
47 | ): ...
48 |
49 | # fmt: off
50 | # fmt: off
45 | ): ...
46 |
47 | # fmt: off
48 | # fmt: off
49 |
50 | class A: ...
51 |
52 | class A: ...
53 |
54 | class B( # type: ignore[duplicate-base]
55 | A,
56 | A,
57 | ): ...
58 |
59 | class C(
60 | A,
61 | A
62 | ): # type: ignore[duplicate-base]
63 | x: int
64 |
65 | # fmt: on
66 | # fmt: off
67 |
68 | # error: [duplicate-base]
69 | class D(
70 | A,
71 | # error: [unused-ignore-comment]
72 | A, # type: ignore[duplicate-base]
73 | ): ...
74 |
75 | # error: [duplicate-base]
76 | class E(
77 | A,
78 | A
79 | ):
80 | # error: [unused-ignore-comment]
81 | x: int # type: ignore[duplicate-base]
82 |
83 | # fmt: on
52 | class B( # type: ignore[duplicate-base]
53 | A,
54 | A,
55 | ): ...
56 |
57 | class C(
58 | A,
59 | A
60 | ): # type: ignore[duplicate-base]
61 | x: int
62 |
63 | # fmt: on
64 | # fmt: off
65 |
66 | # error: [duplicate-base]
67 | class D(
68 | A,
69 | # error: [unused-ignore-comment]
70 | A, # type: ignore[duplicate-base]
71 | ): ...
72 |
73 | # error: [duplicate-base]
74 | class E(
75 | A,
76 | A
77 | ):
78 | # error: [unused-ignore-comment]
79 | x: int # type: ignore[duplicate-base]
80 |
81 | # fmt: on
```
# Diagnostics
```
error[duplicate-base]: Duplicate base class `str`
--> src/mdtest_snippet.py:3:7
--> src/mdtest_snippet.py:1:7
|
1 | from typing_extensions import reveal_type
2 |
3 | class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
1 | class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
| ^^^^^^^^^^^^^
4 |
5 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
2 |
3 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
info: The definition of class `Foo` will raise `TypeError` at runtime
--> src/mdtest_snippet.py:3:11
--> src/mdtest_snippet.py:1:11
|
1 | from typing_extensions import reveal_type
2 |
3 | class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
1 | class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
| --- ^^^ Class `str` later repeated here
| |
| Class `str` first included in bases list here
4 |
5 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
2 |
3 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
info: rule `duplicate-base` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:5:13
|
3 | class Foo(str, str): ... # error: [duplicate-base] "Duplicate base class `str`"
4 |
5 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
| ^^^^^^^^^^^ `tuple[<class 'Foo'>, Unknown, <class 'object'>]`
6 |
7 | class Spam: ...
|
```
```
error[duplicate-base]: Duplicate base class `Spam`
--> src/mdtest_snippet.py:16:7
--> src/mdtest_snippet.py:14:7
|
14 | # error: [duplicate-base] "Duplicate base class `Spam`"
15 | # error: [duplicate-base] "Duplicate base class `Eggs`"
16 | class Ham(
12 | # error: [duplicate-base] "Duplicate base class `Spam`"
13 | # error: [duplicate-base] "Duplicate base class `Eggs`"
14 | class Ham(
| _______^
17 | | Spam,
18 | | Eggs,
19 | | Bar,
20 | | Baz,
21 | | Spam,
22 | | Eggs,
23 | | ): ...
15 | | Spam,
16 | | Eggs,
17 | | Bar,
18 | | Baz,
19 | | Spam,
20 | | Eggs,
21 | | ): ...
| |_^
24 |
25 | # fmt: on
22 |
23 | # fmt: on
|
info: The definition of class `Ham` will raise `TypeError` at runtime
--> src/mdtest_snippet.py:17:5
--> src/mdtest_snippet.py:15:5
|
15 | # error: [duplicate-base] "Duplicate base class `Eggs`"
16 | class Ham(
17 | Spam,
13 | # error: [duplicate-base] "Duplicate base class `Eggs`"
14 | class Ham(
15 | Spam,
| ---- Class `Spam` first included in bases list here
18 | Eggs,
19 | Bar,
20 | Baz,
21 | Spam,
16 | Eggs,
17 | Bar,
18 | Baz,
19 | Spam,
| ^^^^ Class `Spam` later repeated here
22 | Eggs,
23 | ): ...
20 | Eggs,
21 | ): ...
|
info: rule `duplicate-base` is enabled by default
@ -180,134 +160,106 @@ info: rule `duplicate-base` is enabled by default
```
error[duplicate-base]: Duplicate base class `Eggs`
--> src/mdtest_snippet.py:16:7
--> src/mdtest_snippet.py:14:7
|
14 | # error: [duplicate-base] "Duplicate base class `Spam`"
15 | # error: [duplicate-base] "Duplicate base class `Eggs`"
16 | class Ham(
12 | # error: [duplicate-base] "Duplicate base class `Spam`"
13 | # error: [duplicate-base] "Duplicate base class `Eggs`"
14 | class Ham(
| _______^
17 | | Spam,
18 | | Eggs,
19 | | Bar,
20 | | Baz,
21 | | Spam,
22 | | Eggs,
23 | | ): ...
15 | | Spam,
16 | | Eggs,
17 | | Bar,
18 | | Baz,
19 | | Spam,
20 | | Eggs,
21 | | ): ...
| |_^
24 |
25 | # fmt: on
22 |
23 | # fmt: on
|
info: The definition of class `Ham` will raise `TypeError` at runtime
--> src/mdtest_snippet.py:18:5
--> src/mdtest_snippet.py:16:5
|
16 | class Ham(
17 | Spam,
18 | Eggs,
14 | class Ham(
15 | Spam,
16 | Eggs,
| ---- Class `Eggs` first included in bases list here
19 | Bar,
20 | Baz,
21 | Spam,
22 | Eggs,
17 | Bar,
18 | Baz,
19 | Spam,
20 | Eggs,
| ^^^^ Class `Eggs` later repeated here
23 | ): ...
21 | ): ...
|
info: rule `duplicate-base` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:27:13
|
25 | # fmt: on
26 |
27 | reveal_type(Ham.__mro__) # revealed: tuple[<class 'Ham'>, Unknown, <class 'object'>]
| ^^^^^^^^^^^ `tuple[<class 'Ham'>, Unknown, <class 'object'>]`
28 |
29 | class Mushrooms: ...
|
```
```
error[duplicate-base]: Duplicate base class `Mushrooms`
--> src/mdtest_snippet.py:30:7
--> src/mdtest_snippet.py:28:7
|
29 | class Mushrooms: ...
30 | class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
27 | class Mushrooms: ...
28 | class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31 |
32 | reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
29 |
30 | reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
|
info: The definition of class `Omelette` will raise `TypeError` at runtime
--> src/mdtest_snippet.py:30:28
--> src/mdtest_snippet.py:28:28
|
29 | class Mushrooms: ...
30 | class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
27 | class Mushrooms: ...
28 | class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
| --------- ^^^^^^^^^ Class `Mushrooms` later repeated here
| |
| Class `Mushrooms` first included in bases list here
31 |
32 | reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
29 |
30 | reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
|
info: rule `duplicate-base` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:32:13
|
30 | class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
31 |
32 | reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
| ^^^^^^^^^^^^^^^^ `tuple[<class 'Omelette'>, Unknown, <class 'object'>]`
33 |
34 | # fmt: off
|
```
```
error[duplicate-base]: Duplicate base class `Eggs`
--> src/mdtest_snippet.py:37:7
--> src/mdtest_snippet.py:35:7
|
36 | # error: [duplicate-base] "Duplicate base class `Eggs`"
37 | class VeryEggyOmelette(
34 | # error: [duplicate-base] "Duplicate base class `Eggs`"
35 | class VeryEggyOmelette(
| _______^
38 | | Eggs,
39 | | Ham,
40 | | Spam,
41 | | Eggs,
42 | | Mushrooms,
43 | | Bar,
36 | | Eggs,
37 | | Ham,
38 | | Spam,
39 | | Eggs,
40 | | Mushrooms,
41 | | Bar,
42 | | Eggs,
43 | | Baz,
44 | | Eggs,
45 | | Baz,
46 | | Eggs,
47 | | ): ...
45 | | ): ...
| |_^
48 |
49 | # fmt: off
46 |
47 | # fmt: off
|
info: The definition of class `VeryEggyOmelette` will raise `TypeError` at runtime
--> src/mdtest_snippet.py:38:5
--> src/mdtest_snippet.py:36:5
|
36 | # error: [duplicate-base] "Duplicate base class `Eggs`"
37 | class VeryEggyOmelette(
38 | Eggs,
34 | # error: [duplicate-base] "Duplicate base class `Eggs`"
35 | class VeryEggyOmelette(
36 | Eggs,
| ---- Class `Eggs` first included in bases list here
39 | Ham,
40 | Spam,
41 | Eggs,
37 | Ham,
38 | Spam,
39 | Eggs,
| ^^^^ Class `Eggs` later repeated here
42 | Mushrooms,
43 | Bar,
40 | Mushrooms,
41 | Bar,
42 | Eggs,
| ^^^^ Class `Eggs` later repeated here
43 | Baz,
44 | Eggs,
| ^^^^ Class `Eggs` later repeated here
45 | Baz,
46 | Eggs,
| ^^^^ Class `Eggs` later repeated here
47 | ): ...
45 | ): ...
|
info: rule `duplicate-base` is enabled by default
@ -315,30 +267,30 @@ info: rule `duplicate-base` is enabled by default
```
error[duplicate-base]: Duplicate base class `A`
--> src/mdtest_snippet.py:69:7
--> src/mdtest_snippet.py:67:7
|
68 | # error: [duplicate-base]
69 | class D(
66 | # error: [duplicate-base]
67 | class D(
| _______^
70 | | A,
71 | | # error: [unused-ignore-comment]
72 | | A, # type: ignore[duplicate-base]
73 | | ): ...
68 | | A,
69 | | # error: [unused-ignore-comment]
70 | | A, # type: ignore[duplicate-base]
71 | | ): ...
| |_^
74 |
75 | # error: [duplicate-base]
72 |
73 | # error: [duplicate-base]
|
info: The definition of class `D` will raise `TypeError` at runtime
--> src/mdtest_snippet.py:70:5
--> src/mdtest_snippet.py:68:5
|
68 | # error: [duplicate-base]
69 | class D(
70 | A,
66 | # error: [duplicate-base]
67 | class D(
68 | A,
| - Class `A` first included in bases list here
71 | # error: [unused-ignore-comment]
72 | A, # type: ignore[duplicate-base]
69 | # error: [unused-ignore-comment]
70 | A, # type: ignore[duplicate-base]
| ^ Class `A` later repeated here
73 | ): ...
71 | ): ...
|
info: rule `duplicate-base` is enabled by default
@ -346,42 +298,42 @@ info: rule `duplicate-base` is enabled by default
```
info[unused-ignore-comment]
--> src/mdtest_snippet.py:72:9
--> src/mdtest_snippet.py:70:9
|
70 | A,
71 | # error: [unused-ignore-comment]
72 | A, # type: ignore[duplicate-base]
68 | A,
69 | # error: [unused-ignore-comment]
70 | A, # type: ignore[duplicate-base]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unused blanket `type: ignore` directive
73 | ): ...
71 | ): ...
|
```
```
error[duplicate-base]: Duplicate base class `A`
--> src/mdtest_snippet.py:76:7
--> src/mdtest_snippet.py:74:7
|
75 | # error: [duplicate-base]
76 | class E(
73 | # error: [duplicate-base]
74 | class E(
| _______^
77 | | A,
78 | | A
79 | | ):
75 | | A,
76 | | A
77 | | ):
| |_^
80 | # error: [unused-ignore-comment]
81 | x: int # type: ignore[duplicate-base]
78 | # error: [unused-ignore-comment]
79 | x: int # type: ignore[duplicate-base]
|
info: The definition of class `E` will raise `TypeError` at runtime
--> src/mdtest_snippet.py:77:5
--> src/mdtest_snippet.py:75:5
|
75 | # error: [duplicate-base]
76 | class E(
77 | A,
73 | # error: [duplicate-base]
74 | class E(
75 | A,
| - Class `A` first included in bases list here
78 | A
76 | A
| ^ Class `A` later repeated here
79 | ):
80 | # error: [unused-ignore-comment]
77 | ):
78 | # error: [unused-ignore-comment]
|
info: rule `duplicate-base` is enabled by default
@ -389,14 +341,14 @@ info: rule `duplicate-base` is enabled by default
```
info[unused-ignore-comment]
--> src/mdtest_snippet.py:81:13
--> src/mdtest_snippet.py:79:13
|
79 | ):
80 | # error: [unused-ignore-comment]
81 | x: int # type: ignore[duplicate-base]
77 | ):
78 | # error: [unused-ignore-comment]
79 | x: int # type: ignore[duplicate-base]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unused blanket `type: ignore` directive
82 |
83 | # fmt: on
80 |
81 | # fmt: on
|
```

View file

@ -136,48 +136,3 @@ info: (x: B, /, **kwargs: int) -> B
info: rule `no-matching-overload` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:8:9
|
6 | # error: [no-matching-overload]
7 | # revealed: Unknown
8 | / f(
9 | | A(),
10 | | a1=a,
11 | | a2=a,
12 | | a3=a,
13 | | a4=a,
14 | | a5=a,
15 | | a6=a,
16 | | a7=a,
17 | | a8=a,
18 | | a9=a,
19 | | a10=a,
20 | | a11=a,
21 | | a12=a,
22 | | a13=a,
23 | | a14=a,
24 | | a15=a,
25 | | a16=a,
26 | | a17=a,
27 | | a18=a,
28 | | a19=a,
29 | | a20=a,
30 | | a21=a,
31 | | a22=a,
32 | | a23=a,
33 | | a24=a,
34 | | a25=a,
35 | | a26=a,
36 | | a27=a,
37 | | a28=a,
38 | | a29=a,
39 | | a30=a,
40 | | )
| |_________^ `Unknown`
41 | )
|
```

View file

@ -12,7 +12,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/protocols.md
## mdtest_snippet.py
```
1 | from typing_extensions import Protocol, reveal_type
1 | from typing_extensions import Protocol
2 |
3 | # error: [call-non-callable]
4 | reveal_type(Protocol()) # revealed: Unknown
@ -36,9 +36,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/protocols.md
22 |
23 | reveal_type(SubclassOfGenericProtocol[int]()) # revealed: SubclassOfGenericProtocol[int]
24 | def f(x: type[MyProtocol]):
25 | # TODO: add a `reveal_type` call here once it's no longer a `Todo` type
26 | # (which doesn't work well with snapshots)
27 | x()
25 | reveal_type(x()) # revealed: @Todo(type[T] for protocols)
```
# Diagnostics
@ -57,19 +55,6 @@ info: rule `call-non-callable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:4:13
|
3 | # error: [call-non-callable]
4 | reveal_type(Protocol()) # revealed: Unknown
| ^^^^^^^^^^ `Unknown`
5 |
6 | class MyProtocol(Protocol):
|
```
```
error[call-non-callable]: Cannot instantiate class `MyProtocol`
--> src/mdtest_snippet.py:10:13
@ -93,19 +78,6 @@ info: rule `call-non-callable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:10:13
|
9 | # error: [call-non-callable] "Cannot instantiate class `MyProtocol`"
10 | reveal_type(MyProtocol()) # revealed: MyProtocol
| ^^^^^^^^^^^^ `MyProtocol`
11 |
12 | class GenericProtocol[T](Protocol):
|
```
```
error[call-non-callable]: Cannot instantiate class `GenericProtocol`
--> src/mdtest_snippet.py:16:13
@ -127,43 +99,3 @@ info: Protocol classes cannot be instantiated
info: rule `call-non-callable` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:16:13
|
15 | # error: [call-non-callable] "Cannot instantiate class `GenericProtocol`"
16 | reveal_type(GenericProtocol[int]()) # revealed: GenericProtocol[int]
| ^^^^^^^^^^^^^^^^^^^^^^ `GenericProtocol[int]`
17 | class SubclassOfMyProtocol(MyProtocol): ...
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:19:13
|
17 | class SubclassOfMyProtocol(MyProtocol): ...
18 |
19 | reveal_type(SubclassOfMyProtocol()) # revealed: SubclassOfMyProtocol
| ^^^^^^^^^^^^^^^^^^^^^^ `SubclassOfMyProtocol`
20 |
21 | class SubclassOfGenericProtocol[T](GenericProtocol[T]): ...
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:23:13
|
21 | class SubclassOfGenericProtocol[T](GenericProtocol[T]): ...
22 |
23 | reveal_type(SubclassOfGenericProtocol[int]()) # revealed: SubclassOfGenericProtocol[int]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SubclassOfGenericProtocol[int]`
24 | def f(x: type[MyProtocol]):
25 | # TODO: add a `reveal_type` call here once it's no longer a `Todo` type
|
```

View file

@ -12,7 +12,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/protocols.md
## mdtest_snippet.py
```
1 | from typing_extensions import Protocol, reveal_type
1 | from typing_extensions import Protocol
2 |
3 | class HasX(Protocol):
4 | x: int
@ -69,7 +69,7 @@ error[invalid-argument-type]: Class `HasX` cannot be used as the second argument
info: `HasX` is declared as a protocol class, but it is not declared as runtime-checkable
--> src/mdtest_snippet.py:3:7
|
1 | from typing_extensions import Protocol, reveal_type
1 | from typing_extensions import Protocol
2 |
3 | class HasX(Protocol):
| ^^^^^^^^^^^^^^ `HasX` declared here
@ -81,34 +81,6 @@ info: rule `invalid-argument-type` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:8:21
|
6 | def f(arg: object, arg2: type):
7 | if isinstance(arg, HasX): # error: [invalid-argument-type]
8 | reveal_type(arg) # revealed: HasX
| ^^^ `HasX`
9 | else:
10 | reveal_type(arg) # revealed: ~HasX
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:10:21
|
8 | reveal_type(arg) # revealed: HasX
9 | else:
10 | reveal_type(arg) # revealed: ~HasX
| ^^^ `~HasX`
11 |
12 | if issubclass(arg2, HasX): # error: [invalid-argument-type]
|
```
```
error[invalid-argument-type]: Class `HasX` cannot be used as the second argument to `issubclass`
--> src/mdtest_snippet.py:12:8
@ -123,7 +95,7 @@ error[invalid-argument-type]: Class `HasX` cannot be used as the second argument
info: `HasX` is declared as a protocol class, but it is not declared as runtime-checkable
--> src/mdtest_snippet.py:3:7
|
1 | from typing_extensions import Protocol, reveal_type
1 | from typing_extensions import Protocol
2 |
3 | class HasX(Protocol):
| ^^^^^^^^^^^^^^ `HasX` declared here
@ -134,110 +106,3 @@ info: See https://docs.python.org/3/library/typing.html#typing.runtime_checkable
info: rule `invalid-argument-type` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:13:21
|
12 | if issubclass(arg2, HasX): # error: [invalid-argument-type]
13 | reveal_type(arg2) # revealed: type[HasX]
| ^^^^ `type[HasX]`
14 | else:
15 | reveal_type(arg2) # revealed: type & ~type[HasX]
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:15:21
|
13 | reveal_type(arg2) # revealed: type[HasX]
14 | else:
15 | reveal_type(arg2) # revealed: type & ~type[HasX]
| ^^^^ `type & ~type[HasX]`
16 | from typing import runtime_checkable
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:24:21
|
22 | def f(arg: object):
23 | if isinstance(arg, RuntimeCheckableHasX): # no error!
24 | reveal_type(arg) # revealed: RuntimeCheckableHasX
| ^^^ `RuntimeCheckableHasX`
25 | else:
26 | reveal_type(arg) # revealed: ~RuntimeCheckableHasX
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:26:21
|
24 | reveal_type(arg) # revealed: RuntimeCheckableHasX
25 | else:
26 | reveal_type(arg) # revealed: ~RuntimeCheckableHasX
| ^^^ `~RuntimeCheckableHasX`
27 | @runtime_checkable
28 | class OnlyMethodMembers(Protocol):
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:33:21
|
31 | def f(arg1: type, arg2: type):
32 | if issubclass(arg1, RuntimeCheckableHasX): # TODO: should emit an error here (has non-method members)
33 | reveal_type(arg1) # revealed: type[RuntimeCheckableHasX]
| ^^^^ `type[RuntimeCheckableHasX]`
34 | else:
35 | reveal_type(arg1) # revealed: type & ~type[RuntimeCheckableHasX]
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:35:21
|
33 | reveal_type(arg1) # revealed: type[RuntimeCheckableHasX]
34 | else:
35 | reveal_type(arg1) # revealed: type & ~type[RuntimeCheckableHasX]
| ^^^^ `type & ~type[RuntimeCheckableHasX]`
36 |
37 | if issubclass(arg2, OnlyMethodMembers): # no error!
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:38:21
|
37 | if issubclass(arg2, OnlyMethodMembers): # no error!
38 | reveal_type(arg2) # revealed: type[OnlyMethodMembers]
| ^^^^ `type[OnlyMethodMembers]`
39 | else:
40 | reveal_type(arg2) # revealed: type & ~type[OnlyMethodMembers]
|
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:40:21
|
38 | reveal_type(arg2) # revealed: type[OnlyMethodMembers]
39 | else:
40 | reveal_type(arg2) # revealed: type & ~type[OnlyMethodMembers]
| ^^^^ `type & ~type[OnlyMethodMembers]`
|
```

View file

@ -13,7 +13,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/protocols.md
```
1 | import sys
2 | from typing_extensions import Protocol, get_protocol_members, reveal_type
2 | from typing_extensions import Protocol, get_protocol_members
3 |
4 | class Foo(Protocol):
5 | if sys.version_info >= (3, 10):
@ -43,7 +43,7 @@ warning[ambiguous-protocol-member]: Cannot assign to undeclared variable in the
info: Assigning to an undeclared variable in a protocol class leads to an ambiguous interface
--> src/mdtest_snippet.py:4:7
|
2 | from typing_extensions import Protocol, get_protocol_members, reveal_type
2 | from typing_extensions import Protocol, get_protocol_members
3 |
4 | class Foo(Protocol):
| ^^^^^^^^^^^^^ `Foo` declared as a protocol here
@ -54,15 +54,3 @@ info: No declarations found for `e` in the body of `Foo` or any of its superclas
info: rule `ambiguous-protocol-member` is enabled by default
```
```
info[revealed-type]: Revealed type
--> src/mdtest_snippet.py:14:13
|
12 | def f(self) -> None: ...
13 |
14 | reveal_type(get_protocol_members(Foo)) # revealed: frozenset[Literal["d", "e", "f"]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `frozenset[Literal["d", "e", "f"]]`
|
```

View file

@ -21,8 +21,8 @@ use type_ordering::union_or_intersection_elements_ordering;
pub(crate) use self::builder::{IntersectionBuilder, UnionBuilder};
pub use self::cyclic::CycleDetector;
pub(crate) use self::cyclic::{PairVisitor, TypeTransformer};
pub use self::diagnostic::TypeCheckDiagnostics;
pub(crate) use self::diagnostic::register_lints;
pub use self::diagnostic::{TypeCheckDiagnostics, UNDEFINED_REVEAL};
pub(crate) use self::infer::{
TypeContext, infer_deferred_types, infer_definition_types, infer_expression_type,
infer_expression_types, infer_isolated_expression, infer_scope_types,

View file

@ -1568,7 +1568,7 @@ declare_lint! {
/// ```python
/// reveal_type(1) # NameError: name 'reveal_type' is not defined
/// ```
pub(crate) static UNDEFINED_REVEAL = {
pub static UNDEFINED_REVEAL = {
summary: "detects usages of `reveal_type` without importing it",
status: LintStatus::preview("1.0.0"),
default_level: Level::Warn,