mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +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]:
|
def __len__(self, v: int) -> Literal[1]:
|
||||||
return 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]
|
reveal_type(len(SecondOptionalArgument())) # revealed: Literal[0]
|
||||||
|
|
||||||
# TODO: Emit a diagnostic
|
# TODO: Emit a diagnostic
|
||||||
|
|
|
@ -77,7 +77,7 @@ from typing import Protocol, TypeVar
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
class CanIndex(Protocol[T]):
|
class CanIndex(Protocol[T]):
|
||||||
def __getitem__(self, index: int) -> T: ...
|
def __getitem__(self, index: int, /) -> T: ...
|
||||||
|
|
||||||
class ExplicitlyImplements(CanIndex[T]): ...
|
class ExplicitlyImplements(CanIndex[T]): ...
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ from typing import Protocol, TypeVar
|
||||||
S = TypeVar("S")
|
S = TypeVar("S")
|
||||||
|
|
||||||
class CanIndex(Protocol[S]):
|
class CanIndex(Protocol[S]):
|
||||||
def __getitem__(self, index: int) -> S: ...
|
def __getitem__(self, index: int, /) -> S: ...
|
||||||
|
|
||||||
class ExplicitlyImplements[T](CanIndex[T]): ...
|
class ExplicitlyImplements[T](CanIndex[T]): ...
|
||||||
|
|
||||||
|
|
|
@ -1813,9 +1813,28 @@ class Foo:
|
||||||
static_assert(not is_assignable_to(Foo, Iterable[Any]))
|
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
|
Because method members are always looked up on the meta-type of an object when testing assignability
|
||||||
`type[P]`, where `P` is a protocol class, just like it is generally safe to access a method on
|
and subtyping, we understand that `IterableClass` here is a subtype of `Iterable[int]` even though
|
||||||
`type[C]` where `C` is a nominal class:
|
`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
|
```py
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue