mirror of https://github.com/astral-sh/ruff
Merge ab736b22d0 into d755f3b522
This commit is contained in:
commit
1ded830fde
|
|
@ -11,17 +11,36 @@ valid type for use in a type expression:
|
||||||
```py
|
```py
|
||||||
MyInt = int
|
MyInt = int
|
||||||
|
|
||||||
|
reveal_type(MyInt) # revealed: <class 'int'>
|
||||||
|
reveal_type(MyInt(1)) # revealed: int
|
||||||
|
|
||||||
def f(x: MyInt):
|
def f(x: MyInt):
|
||||||
reveal_type(x) # revealed: int
|
reveal_type(x) # revealed: int
|
||||||
|
|
||||||
f(1)
|
f(1)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This also works for generic aliases:
|
||||||
|
|
||||||
|
```py
|
||||||
|
ListOfStr = list[str]
|
||||||
|
|
||||||
|
reveal_type(ListOfStr) # revealed: <class 'list[str]'>
|
||||||
|
reveal_type(ListOfStr(["a", "b"])) # revealed: list[str]
|
||||||
|
|
||||||
|
def g(x: ListOfStr):
|
||||||
|
reveal_type(x) # revealed: list[str]
|
||||||
|
|
||||||
|
g(["a", "b"])
|
||||||
|
```
|
||||||
|
|
||||||
## None
|
## None
|
||||||
|
|
||||||
```py
|
```py
|
||||||
MyNone = None
|
MyNone = None
|
||||||
|
|
||||||
|
reveal_type(MyNone) # revealed: None
|
||||||
|
|
||||||
def g(x: MyNone):
|
def g(x: MyNone):
|
||||||
reveal_type(x) # revealed: None
|
reveal_type(x) # revealed: None
|
||||||
|
|
||||||
|
|
@ -211,6 +230,13 @@ def _(int_or_int: IntOrInt, list_of_int_or_list_of_int: ListOfIntOrListOfInt):
|
||||||
reveal_type(list_of_int_or_list_of_int) # revealed: list[int]
|
reveal_type(list_of_int_or_list_of_int) # revealed: list[int]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`types.UnionType` instances can not be instantiated:
|
||||||
|
|
||||||
|
```py
|
||||||
|
# error: [call-non-callable] "Object of type `UnionType` is not callable"
|
||||||
|
IntOrStr()
|
||||||
|
```
|
||||||
|
|
||||||
`NoneType` has no special or-operator behavior, so this is an error:
|
`NoneType` has no special or-operator behavior, so this is an error:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
|
@ -926,7 +952,7 @@ def _(weird: IntLiteral1[int]):
|
||||||
|
|
||||||
## `Annotated`
|
## `Annotated`
|
||||||
|
|
||||||
Basic usage:
|
### Basic usage
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
@ -952,10 +978,61 @@ class C:
|
||||||
reveal_type(C().old) # revealed: int
|
reveal_type(C().old) # revealed: int
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Special members
|
||||||
|
|
||||||
|
The `__origin__` attribute on an instance of `Annotated` can be used to access the underlying type.
|
||||||
|
We currently do not model this precisely:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
StrWithMetadata = Annotated[str, "metadata", 1, 2, 3]
|
||||||
|
|
||||||
|
reveal_type(StrWithMetadata.__origin__) # revealed: type | TypeAliasType
|
||||||
|
```
|
||||||
|
|
||||||
|
At runtime, the `__metadata__` attribute contains the metadata elements `('metadata', 1, 2, 3)`, but
|
||||||
|
we do not model the type of this attribute precisely:
|
||||||
|
|
||||||
|
```py
|
||||||
|
reveal_type(StrWithMetadata.__metadata__) # revealed: Any
|
||||||
|
```
|
||||||
|
|
||||||
|
### Attribute access and instantiation
|
||||||
|
|
||||||
|
A class can be instantiated through an `Annotated` alias, and attributes can be accessed on the
|
||||||
|
created instance:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Annotated, Union
|
||||||
|
|
||||||
|
class Foo:
|
||||||
|
attribute: int = 1
|
||||||
|
|
||||||
|
FooWithMetadata = Annotated[Foo, "metadata"]
|
||||||
|
|
||||||
|
c = FooWithMetadata()
|
||||||
|
|
||||||
|
reveal_type(c) # revealed: Foo
|
||||||
|
reveal_type(c.attribute) # revealed: int
|
||||||
|
```
|
||||||
|
|
||||||
|
However, accessing attributes on the alias itself currently yields `Any`, instead of the attribute's
|
||||||
|
type:
|
||||||
|
|
||||||
|
```py
|
||||||
|
reveal_type(FooWithMetadata.attribute) # revealed: Any
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error cases
|
||||||
|
|
||||||
If the metadata argument is missing, we emit an error (because this code fails at runtime), but
|
If the metadata argument is missing, we emit an error (because this code fails at runtime), but
|
||||||
still use the first element as the type, when used in annotations:
|
still use the first element as the type, when used in annotations:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
# error: [invalid-type-form] "Special form `typing.Annotated` expected at least 2 arguments (one type and at least one metadata element)"
|
# error: [invalid-type-form] "Special form `typing.Annotated` expected at least 2 arguments (one type and at least one metadata element)"
|
||||||
WronglyAnnotatedInt = Annotated[int]
|
WronglyAnnotatedInt = Annotated[int]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6433,6 +6433,10 @@ impl<'db> Type<'db> {
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
|
|
||||||
|
Type::KnownInstance(KnownInstanceType::Annotated(ty)) => {
|
||||||
|
ty.inner(db).to_meta_type(db).bindings(db)
|
||||||
|
}
|
||||||
|
|
||||||
Type::KnownInstance(known_instance) => {
|
Type::KnownInstance(known_instance) => {
|
||||||
known_instance.instance_fallback(db).bindings(db)
|
known_instance.instance_fallback(db).bindings(db)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue