mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 22:55:08 +00:00

## Summary This is a small, tentative step towards the bigger goal of understanding instance attributes. - Adds partial support for pure instance variables declared in the class body, i.e. this case: ```py class C: variable1: str = "a" variable2 = "b" reveal_type(C().variable1) # str reveal_type(C().variable2) # Unknown | Literal["b"] ``` - Adds `property` as a known class to query for `@property` decorators - Splits up various `@Todo(instance attributes)` cases into sub-categories. ## Test Plan Modified existing MD tests.
1.9 KiB
1.9 KiB
PEP 695 Generics
Class Declarations
Basic PEP 695 generics
class MyBox[T]:
data: T
box_model_number = 695
def __init__(self, data: T):
self.data = data
box: MyBox[int] = MyBox(5)
# TODO should emit a diagnostic here (str is not assignable to int)
wrong_innards: MyBox[int] = MyBox("five")
# TODO reveal int, do not leak the typevar
reveal_type(box.data) # revealed: T
reveal_type(MyBox.box_model_number) # revealed: Literal[695]
Subclassing
class MyBox[T]:
data: T
def __init__(self, data: T):
self.data = data
# TODO not error on the subscripting
# error: [non-subscriptable]
class MySecureBox[T](MyBox[T]): ...
secure_box: MySecureBox[int] = MySecureBox(5)
reveal_type(secure_box) # revealed: MySecureBox
# TODO reveal int
# The @Todo(…) is misleading here. We currently treat `MyBox[T]` as a dynamic base class because we
# don't understand generics and therefore infer `Unknown` for the `MyBox[T]` base of `MySecureBox[T]`.
reveal_type(secure_box.data) # revealed: @Todo(instance attribute on class with dynamic base)
Cyclical class definition
In type stubs, classes can reference themselves in their base class definitions. For example, in
typeshed
, we have class str(Sequence[str]): ...
.
This should hold true even with generics at play.
class Seq[T]: ...
# TODO not error on the subscripting
class S[T](Seq[S]): ... # error: [non-subscriptable]
reveal_type(S) # revealed: Literal[S]
Type params
A PEP695 type variable defines a value of type typing.TypeVar
.
def f[T]():
reveal_type(T) # revealed: T
reveal_type(T.__name__) # revealed: Literal["T"]
Minimum two constraints
A typevar with less than two constraints emits a diagnostic:
# error: [invalid-type-variable-constraints] "TypeVar must have at least two constrained types"
def f[T: (int,)]():
pass