mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:24:57 +00:00
[ty] Minor fixes to Protocol
tests (#20347)
This commit is contained in:
parent
ffd4340dce
commit
0e3697a643
4 changed files with 25 additions and 6 deletions
|
@ -260,7 +260,7 @@ class SecondRequiredArgument:
|
|||
def __len__(self, v: int) -> Literal[1]:
|
||||
return 1
|
||||
|
||||
# TODO: Emit a diagnostic
|
||||
# this is fine: the call succeeds at runtime since the second argument is optional
|
||||
reveal_type(len(SecondOptionalArgument())) # revealed: Literal[0]
|
||||
|
||||
# TODO: Emit a diagnostic
|
||||
|
|
|
@ -77,7 +77,7 @@ from typing import Protocol, TypeVar
|
|||
T = TypeVar("T")
|
||||
|
||||
class CanIndex(Protocol[T]):
|
||||
def __getitem__(self, index: int) -> T: ...
|
||||
def __getitem__(self, index: int, /) -> T: ...
|
||||
|
||||
class ExplicitlyImplements(CanIndex[T]): ...
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ from typing import Protocol, TypeVar
|
|||
S = TypeVar("S")
|
||||
|
||||
class CanIndex(Protocol[S]):
|
||||
def __getitem__(self, index: int) -> S: ...
|
||||
def __getitem__(self, index: int, /) -> S: ...
|
||||
|
||||
class ExplicitlyImplements[T](CanIndex[T]): ...
|
||||
|
||||
|
|
|
@ -1813,9 +1813,28 @@ class Foo:
|
|||
static_assert(not is_assignable_to(Foo, Iterable[Any]))
|
||||
```
|
||||
|
||||
Because method members must always be available on the class, it is safe to access a method on
|
||||
`type[P]`, where `P` is a protocol class, just like it is generally safe to access a method on
|
||||
`type[C]` where `C` is a nominal class:
|
||||
Because method members are always looked up on the meta-type of an object when testing assignability
|
||||
and subtyping, we understand that `IterableClass` here is a subtype of `Iterable[int]` even though
|
||||
`IterableClass.__iter__` has the wrong signature:
|
||||
|
||||
```py
|
||||
from typing import Iterator, Iterable
|
||||
from ty_extensions import static_assert, is_subtype_of, TypeOf
|
||||
|
||||
class Meta(type):
|
||||
def __iter__(self) -> Iterator[int]:
|
||||
yield from range(42)
|
||||
|
||||
class IterableClass(metaclass=Meta):
|
||||
def __iter__(self) -> Iterator[str]:
|
||||
yield from "abc"
|
||||
|
||||
static_assert(is_subtype_of(TypeOf[IterableClass], Iterable[int]))
|
||||
```
|
||||
|
||||
Enforcing that members must always be available on the class also means that it is safe to access a
|
||||
method on `type[P]`, where `P` is a protocol class, just like it is generally safe to access a
|
||||
method on `type[C]` where `C` is a nominal class:
|
||||
|
||||
```py
|
||||
from typing import Protocol
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue