mirror of https://github.com/astral-sh/ruff
support dictionary literal `TypedDict` constructors
This commit is contained in:
parent
b753851379
commit
2949f76b47
|
|
@ -315,6 +315,8 @@ Person(name="Alice", age=30, extra=True) # type: ignore
|
||||||
The positional dictionary constructor pattern (used by libraries like strawberry) should work
|
The positional dictionary constructor pattern (used by libraries like strawberry) should work
|
||||||
correctly:
|
correctly:
|
||||||
|
|
||||||
|
`class.py`:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import TypedDict
|
from typing import TypedDict
|
||||||
|
|
||||||
|
|
@ -335,6 +337,26 @@ user3 = User({"name": None, "age": 25})
|
||||||
user4 = User({"name": "Charlie", "age": 30, "extra": True})
|
user4 = User({"name": "Charlie", "age": 30, "extra": True})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`functional.py`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from typing import TypedDict
|
||||||
|
|
||||||
|
User = TypedDict("User", {"name": str, "age": int})
|
||||||
|
|
||||||
|
# Valid usage - all required fields provided
|
||||||
|
user1 = User({"name": "Alice", "age": 30})
|
||||||
|
|
||||||
|
# error: [missing-typed-dict-key] "Missing required key 'age' in TypedDict `User` constructor"
|
||||||
|
user2 = User({"name": "Bob"})
|
||||||
|
|
||||||
|
# error: [invalid-argument-type] "Invalid argument to key "name" with declared type `str` on TypedDict `User`: value of type `None`"
|
||||||
|
user3 = User({"name": None, "age": 25})
|
||||||
|
|
||||||
|
# error: [invalid-key] "Invalid key access on TypedDict `User`: Unknown key "extra""
|
||||||
|
user4 = User({"name": "Charlie", "age": 30, "extra": True})
|
||||||
|
```
|
||||||
|
|
||||||
## Optional fields with `total=False`
|
## Optional fields with `total=False`
|
||||||
|
|
||||||
By default, all fields in a `TypedDict` are required (`total=True`). You can make all fields
|
By default, all fields in a `TypedDict` are required (`total=True`). You can make all fields
|
||||||
|
|
|
||||||
|
|
@ -4865,16 +4865,21 @@ impl<'db> Type<'db> {
|
||||||
|
|
||||||
Type::EnumLiteral(enum_literal) => enum_literal.enum_class_instance(db).bindings(db),
|
Type::EnumLiteral(enum_literal) => enum_literal.enum_class_instance(db).bindings(db),
|
||||||
|
|
||||||
Type::KnownInstance(KnownInstanceType::TypedDictType(typed_dict)) => Binding::single(
|
Type::KnownInstance(KnownInstanceType::TypedDictType(typed_dict)) => {
|
||||||
self,
|
CallableBinding::from_overloads(
|
||||||
Signature::new(
|
self,
|
||||||
// TODO: List more specific parameter types here for better code completion.
|
[Signature::new(
|
||||||
Parameters::new([Parameter::keyword_variadic(Name::new_static("kwargs"))
|
// TODO: List more specific parameter types here for better code completion.
|
||||||
.with_annotated_type(Type::any())]),
|
Parameters::new([
|
||||||
Some(Type::TypedDict(TypedDictType::Synthesized(typed_dict))),
|
Parameter::variadic(Name::new_static("args")),
|
||||||
),
|
Parameter::keyword_variadic(Name::new_static("kwargs"))
|
||||||
)
|
.with_annotated_type(Type::any()),
|
||||||
.into(),
|
]),
|
||||||
|
Some(Type::TypedDict(TypedDictType::Synthesized(typed_dict))),
|
||||||
|
)],
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
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