mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-17 13:57:25 +00:00
[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
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:
parent
dc64c08633
commit
7064c38e53
47 changed files with 849 additions and 1900 deletions
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
## Invalid syntax
|
||||
|
||||
```py
|
||||
from typing_extensions import reveal_type
|
||||
|
||||
try:
|
||||
print
|
||||
except as e: # error: [invalid-syntax]
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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'>]
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]]`
|
||||
|
|
||||
|
||||
```
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'>]`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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 | )
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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]`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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"]]`
|
||||
|
|
||||
|
||||
```
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue