[ty] Add support for functional TypedDict#24174
Conversation
dbb3a6d to
6953c16
Compare
Typing conformance results improved 🎉The percentage of diagnostics emitted that were expected errors increased from 86.59% to 86.60%. The percentage of expected errors that received a diagnostic increased from 80.96% to 81.47%. The number of fully passing files improved from 68/132 to 69/132. SummaryHow are test cases classified?Each test case represents one expected error annotation or a group of annotations sharing a tag. Counts are per test case, not per diagnostic — multiple diagnostics on the same line count as one. Required annotations (
Test file breakdown4 files altered
True positives added (5)5 diagnostics
False positives added (1)1 diagnostic
Optional Diagnostics Added (3)3 diagnostics
Optional Diagnostics Removed (1)1 diagnostic
|
Memory usage reportSummary
Significant changesClick to expand detailed breakdownprefect
sphinx
trio
flake8
|
6953c16 to
c64acf6
Compare
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
36 | 3 | 3 |
invalid-await |
40 | 0 | 0 |
missing-typed-dict-key |
12 | 1 | 0 |
unused-type-ignore-comment |
0 | 13 | 0 |
invalid-key |
7 | 3 | 0 |
unresolved-attribute |
0 | 7 | 0 |
invalid-assignment |
5 | 0 | 0 |
invalid-method-override |
5 | 0 | 0 |
invalid-return-type |
2 | 2 | 0 |
no-matching-overload |
1 | 0 | 0 |
| Total | 108 | 29 | 3 |
Changes in flaky projects detected. Raw diff output excludes flaky projects; see the HTML report for details.
Raw diff (98 changes)
artigraph (https://github.com/artigraph/artigraph)
+ src/arti/types/python.py:258:13 error[invalid-argument-type] Expected a dict literal for parameter `fields` of `TypedDict()`
dragonchain (https://github.com/dragonchain/dragonchain)
+ dragonchain/lib/dto/api_key_model.py:175:9 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `permissions_doc`, found `permissions_doc | dict[str, str | bool | dict[Unknown, Unknown]]`
+ dragonchain/lib/dto/api_key_model.py:209:9 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `permissions_doc`, found `permissions_doc | dict[str, str | bool | dict[Unknown, Unknown]]`
+ dragonchain/transaction_processor/level_3_actions_utest.py:247:86 error[invalid-argument-type] Argument to function `verify_blocks` is incorrect: Expected `L1Headers`, found `dict[str, str]`
+ dragonchain/webserver/helpers_utest.py:169:47 error[invalid-argument-type] Argument to function `verify_custom_indexes_options` is incorrect: Expected `Iterable[custom_index]`, found `list[dict[str, str]]`
+ dragonchain/webserver/helpers_utest.py:169:48 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/webserver/helpers_utest.py:172:47 error[invalid-argument-type] Argument to function `verify_custom_indexes_options` is incorrect: Expected `Iterable[custom_index]`, found `list[dict[str, str]]`
+ dragonchain/webserver/helpers_utest.py:172:48 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/webserver/helpers_utest.py:175:47 error[invalid-argument-type] Argument to function `verify_custom_indexes_options` is incorrect: Expected `Iterable[custom_index]`, found `list[dict[str, str]]`
+ dragonchain/webserver/helpers_utest.py:175:48 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:66 error[invalid-argument-type] Argument to function `create_api_key_v1` is incorrect: Expected `permissions_doc | None`, found `dict[str, str]`
+ dragonchain/webserver/lib/api_keys_utest.py:48:87 error[missing-typed-dict-key] Missing required key 'default_allow' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:87 error[missing-typed-dict-key] Missing required key 'permissions' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:87 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:88 error[invalid-key] Unknown key "wind" for TypedDict `permissions_doc`
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[invalid-argument-type] Argument to function `update_api_key_v1` is incorrect: Expected `permissions_doc | None`, found `dict[str, str]`
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[missing-typed-dict-key] Missing required key 'default_allow' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[missing-typed-dict-key] Missing required key 'permissions' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:91:60 error[invalid-key] Unknown key "definitely" for TypedDict `permissions_doc`
+ dragonchain/lib/database/redisearch_utest.py:71:55 error[invalid-argument-type] Argument to function `create_transaction_index` is incorrect: Expected `Iterable[custom_index] | None`, found `list[dict[str, str]]`
+ dragonchain/lib/database/redisearch_utest.py:71:56 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/transaction_processor/level_4_actions_utest.py:73:63 error[invalid-argument-type] Argument to function `verify_blocks` is incorrect: Expected `L1Headers`, found `dict[str, int | str]`
+ dragonchain/transaction_processor/level_4_actions_utest.py:73:73 error[invalid-argument-type] Invalid argument to key "dc_id" with declared type `str` on TypedDict `L1Headers`: value of type `Literal[123]`
+ dragonchain/transaction_processor/level_4_actions_utest.py:73:90 error[invalid-argument-type] Invalid argument to key "block_id" with declared type `str` on TypedDict `L1Headers`: value of type `Literal[124]`
graphql-core (https://github.com/graphql-python/graphql-core)
- tests/utilities/test_build_client_schema.py:90:53 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:498:54 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:673:44 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:682:42 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:987:60 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:1002:55 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
- src/hydra_zen/wrapper/_implementations.py:1572:89 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
isort (https://github.com/pycqa/isort)
- isort/output.py:587:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `@Todo(Functional TypedDicts) | None | list[Unknown]`
+ isort/output.py:587:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `Any | None | list[Unknown]`
- isort/output.py:597:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `@Todo(Functional TypedDicts) | None | list[Unknown]`
+ isort/output.py:597:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `Any | None | list[Unknown]`
- isort/output.py:605:29 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `@Todo(Functional TypedDicts) | None | list[Unknown]`
+ isort/output.py:605:29 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `Any | None | list[Unknown]`
meson (https://github.com/mesonbuild/meson)
- mesonbuild/cargo/manifest.py:330:16 error[missing-typed-dict-key] Missing required key 'workspace' in TypedDict `FromWorkspace` constructor
- mesonbuild/cargo/manifest.py:330:17 error[invalid-key] Unknown key "version" for TypedDict `FromWorkspace`
- mesonbuild/cargo/manifest.py:542:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `LibTarget`, found `dict[Unknown, Unknown]`
- mesonbuild/cargo/manifest.py:557:54 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `BuildTarget`, found `dict[str, str]`
- mesonbuild/cargo/manifest.py:563:54 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `BuildTarget`, found `dict[str, str]`
+ mesonbuild/cargo/manifest.py:336:22 error[no-matching-overload] No overload of function `_depv_to_dep` matches arguments
+ unittests/cargotests.py:332:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:333:33 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, dict[str, str] | FromWorkspace]`
+ unittests/cargotests.py:333:45 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `Package` constructor
+ unittests/cargotests.py:340:33 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, dict[str, str]]`
+ unittests/cargotests.py:340:45 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `Package` constructor
+ unittests/cargotests.py:350:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:364:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:400:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:417:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:441:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:457:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:497:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:504:38 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:515:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:549:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:569:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
- unittests/cargotests.py:379:68 error[invalid-key] Unknown key "optional" for TypedDict `FromWorkspace`
+ unittests/cargotests.py:379:48 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `FromWorkspace | Dependency | str`, found `dict[str, bool]`
- unittests/cargotests.py:387:62 error[invalid-key] Unknown key "features" for TypedDict `FromWorkspace`
+ unittests/cargotests.py:387:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `FromWorkspace | Dependency | str`, found `dict[str, bool | list[str]]`
operator (https://github.com/canonical/operator)
+ ops/_private/harness.py:1640:9 error[invalid-assignment] Invalid subscript assignment with key of type `tuple[str | None, int | None]` and value of type `dict[str, list[dict[str, str | list[dict[str, str]]]] | list[str]]` on object of type `dict[tuple[str | None, int | None], _NetworkDict]`
+ ops/_private/harness.py:3355:38 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `str | LayerDict | None`, found `str | (LayerDict & Top[dict[Unknown, Unknown]]) | (Layer & Top[dict[Unknown, Unknown]])`
+ ops/model.py:3738:16 error[invalid-return-type] Return type does not match returned value: expected `_StatusDict`, found `dict[str, str]`
+ ops/model.py:3739:23 error[invalid-argument-type] Invalid argument to key "status" with declared type `Literal["active", "blocked", "maintenance", "waiting", "error", "unknown"]` on TypedDict `_StatusDict`: value of type `str`
- ops/pebble.py:630:58 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:720:58 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:789:58 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:1170:40 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:1188:40 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ ops/pebble.py:884:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:946:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:963:28 error[invalid-assignment] Object of type `(ServiceDict & ~AlwaysFalsy) | dict[Unknown, Unknown]` is not assignable to `ServiceDict`
+ ops/pebble.py:1033:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:1101:26 error[invalid-assignment] Object of type `(CheckDict & ~AlwaysFalsy) | dict[Unknown, Unknown]` is not assignable to `CheckDict`
+ ops/pebble.py:1148:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:1171:27 error[invalid-key] TypedDict `ExecDict` can only be subscripted with a string literal key, got key of type `str`.
+ ops/pebble.py:1173:27 error[invalid-key] TypedDict `ExecDict` can only be subscripted with a string literal key, got key of type `str & ~Literal["environment"]`.
+ ops/pebble.py:1189:27 error[invalid-key] TypedDict `HttpDict` can only be subscripted with a string literal key, got key of type `str`.
+ ops/pebble.py:1191:27 error[invalid-key] TypedDict `HttpDict` can only be subscripted with a string literal key, got key of type `str & ~Literal["headers"]`.
+ ops/pebble.py:1204:22 error[invalid-key] TypedDict `TcpDict` can only be subscripted with a string literal key, got key of type `str`.
+ ops/pebble.py:1262:30 error[invalid-assignment] Object of type `(LogTargetDict & ~AlwaysFalsy) | dict[Unknown, Unknown]` is not assignable to `LogTargetDict`
+ ops/pebble.py:1286:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:2103:23 error[invalid-argument-type] Invalid argument to key "access" with declared type `Literal["untrusted", "metrics", "read", "admin"]` on TypedDict `IdentityDict`: value of type `str`
+ ops/pebble.py:2556:36 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `str | LayerDict | None`, found `(LayerDict & Top[dict[Unknown, Unknown]]) | (Layer & Top[dict[Unknown, Unknown]])`
pandera (https://github.com/pandera-dev/pandera)
- pandera/engines/pandas_engine.py:1420:76 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
ppb-vector (https://github.com/ppb/ppb-vector)
- tests/test_length.py:41:20 error[unresolved-attribute] Object of type `int | float` has no attribute `length`
- tests/test_project.py:50:8 error[unresolved-attribute] Object of type `int | float` has no attribute `isclose`
- tests/test_scalar_multiplication.py:10:28 error[unresolved-attribute] Object of type `int | float` has no attribute `x`
- tests/test_scalar_multiplication.py:11:28 error[unresolved-attribute] Object of type `int | float` has no attribute `y`
- tests/test_scalar_multiplication.py:19:12 error[unresolved-attribute] Object of type `int | float` has no attribute `isclose`
- tests/test_scalar_multiplication.py:24:12 error[unresolved-attribute] Object of type `int | float` has no attribute `isclose`
- tests/test_scalar_multiplication.py:32:20 error[unresolved-attribute] Object of type `int | float` has no attribute `length`
- ppb_vector/__init__.py:567:16 error[invalid-return-type] Return type does not match returned value: expected `Vector`, found `int | float`
- ppb_vector/__init__.py:588:16 error[invalid-return-type] Return type does not match returned value: expected `tuple[Vector, Vector]`, found `tuple[int | float, Vector]`
scipy-stubs (https://github.com/scipy/scipy-stubs)
+ scipy-stubs/integrate/_quadpack_py.pyi:77:43 error[invalid-argument-type] Expected a string-literal key in the `fields` dict of `TypedDict()`: Found `Literal[0]`
static-frame (https://github.com/static-frame/static-frame)
+ static_frame/test/unit/test_type_clinic.py:198:39 error[invalid-argument-type] Expected a dict literal for parameter `fields` of `TypedDict()`
+ static_frame/test/unit/test_type_clinic.py:199:39 error[invalid-argument-type] Expected a dict literal for parameter `fields` of `TypedDict()`|
For the ecosystem changes...
|
c64acf6 to
abe5844
Compare
abe5844 to
ff459cb
Compare
AlexWaygood
left a comment
There was a problem hiding this comment.
Thank you! I haven't looked in depth at the code yet, just at the tests so far.
crates/ty_python_semantic/src/types/infer/builder/typed_dict.rs
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/src/types/infer/builder/typed_dict.rs
Outdated
Show resolved
Hide resolved
42d26d8 to
f7f0130
Compare
crates/ty_python_semantic/src/types/infer/builder/typed_dict.rs
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/src/types/infer/builder/typed_dict.rs
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/src/types/infer/builder/typed_dict.rs
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/src/types/infer/builder/typed_dict.rs
Outdated
Show resolved
Hide resolved
|
It looks like we should be able to get rid of the Detailsdiff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs
index 0656296c08..e5566f2ccf 100644
--- a/crates/ty_python_semantic/src/types.rs
+++ b/crates/ty_python_semantic/src/types.rs
@@ -929,7 +929,6 @@ impl<'db> Type<'db> {
DynamicType::Todo(_)
| DynamicType::TodoStarredExpression
| DynamicType::TodoUnpack
- | DynamicType::TodoFunctionalTypedDict
| DynamicType::TodoTypeVarTuple => true,
})
}
@@ -3759,32 +3758,6 @@ impl<'db> Type<'db> {
}
},
- Type::SpecialForm(SpecialFormType::TypedDict) => {
- Binding::single(
- self,
- Signature::new(
- Parameters::new(
- db,
- [
- Parameter::positional_only(Some(Name::new_static("typename")))
- .with_annotated_type(KnownClass::Str.to_instance(db)),
- Parameter::positional_only(Some(Name::new_static("fields")))
- .with_annotated_type(KnownClass::Dict.to_instance(db))
- .with_default_type(Type::any()),
- Parameter::keyword_only(Name::new_static("total"))
- .with_annotated_type(KnownClass::Bool.to_instance(db))
- .with_default_type(Type::bool_literal(true)),
- // Future compatibility, in case new keyword arguments will be added:
- Parameter::keyword_variadic(Name::new_static("kwargs"))
- .with_annotated_type(Type::any()),
- ],
- ),
- Type::Dynamic(DynamicType::TodoFunctionalTypedDict),
- ),
- )
- .into()
- }
-
Type::NominalInstance(_) | Type::ProtocolInstance(_) | Type::NewTypeInstance(_) => {
// Note that for objects that have a (possibly not callable!) `__call__` attribute,
// we will get the signature of the `__call__` attribute, but will pass in the type
@@ -6011,7 +5984,6 @@ impl<'db> Type<'db> {
| DynamicType::TodoStarredExpression
| DynamicType::TodoTypeVarTuple
| DynamicType::UnspecializedTypeVar
- | DynamicType::TodoFunctionalTypedDict
)
| Self::Callable(_)
| Self::TypeIs(_)
@@ -6495,8 +6467,6 @@ pub enum DynamicType<'db> {
TodoStarredExpression,
/// A special Todo-variant for `TypeVarTuple` instances encountered in type expressions
TodoTypeVarTuple,
- /// A special Todo-variant for functional `TypedDict`s.
- TodoFunctionalTypedDict,
/// A type that is determined to be divergent during recursive type inference.
Divergent(DivergentType),
}
@@ -6523,7 +6493,6 @@ impl std::fmt::Display for DynamicType<'_> {
DynamicType::TodoUnpack => f.write_str("@Todo(typing.Unpack)"),
DynamicType::TodoStarredExpression => f.write_str("@Todo(StarredExpression)"),
DynamicType::TodoTypeVarTuple => f.write_str("@Todo(TypeVarTuple)"),
- DynamicType::TodoFunctionalTypedDict => f.write_str("@Todo(Functional TypedDicts)"),
DynamicType::Divergent(_) => f.write_str("Divergent"),
}
}
diff --git a/crates/ty_python_semantic/src/types/call/bind.rs b/crates/ty_python_semantic/src/types/call/bind.rs
index f120dfb33c..735b3d64d2 100644
--- a/crates/ty_python_semantic/src/types/call/bind.rs
+++ b/crates/ty_python_semantic/src/types/call/bind.rs
@@ -2067,12 +2067,6 @@ impl<'db> Bindings<'db> {
_ => {}
},
- Type::SpecialForm(SpecialFormType::TypedDict) => {
- overload.set_return_type(Type::Dynamic(
- crate::types::DynamicType::TodoFunctionalTypedDict,
- ));
- }
-
// Not a special case
_ => {}
}
diff --git a/crates/ty_python_semantic/src/types/class_base.rs b/crates/ty_python_semantic/src/types/class_base.rs
index 22a730a33e..5138f51ebc 100644
--- a/crates/ty_python_semantic/src/types/class_base.rs
+++ b/crates/ty_python_semantic/src/types/class_base.rs
@@ -59,7 +59,6 @@ impl<'db> ClassBase<'db> {
ClassBase::Dynamic(DynamicType::UnspecializedTypeVar) => "UnspecializedTypeVar",
ClassBase::Dynamic(
DynamicType::Todo(_)
- | DynamicType::TodoFunctionalTypedDict
| DynamicType::TodoUnpack
| DynamicType::TodoStarredExpression
| DynamicType::TodoTypeVarTuple,
diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs
index 43cf155ae5..f98e5dab39 100644
--- a/crates/ty_python_semantic/src/types/infer/builder.rs
+++ b/crates/ty_python_semantic/src/types/infer/builder.rs
@@ -4077,13 +4077,9 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
let in_typed_dict = current_scope.kind() == ScopeKind::Class
&& nearest_enclosing_class(self.db(), self.index, self.scope()).is_some_and(
|class| {
- class.iter_mro(self.db(), None).any(|base| {
- matches!(
- base,
- ClassBase::TypedDict
- | ClassBase::Dynamic(DynamicType::TodoFunctionalTypedDict)
- )
- })
+ class
+ .iter_mro(self.db(), None)
+ .contains(&ClassBase::TypedDict)
},
);
if !in_typed_dict {
@@ -5870,13 +5866,6 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
}
}
- // Avoid false positives for the functional `TypedDict` form, which is currently
- // unsupported.
- if let Some(Type::Dynamic(DynamicType::TodoFunctionalTypedDict)) = tcx.annotation {
- return KnownClass::Dict
- .to_specialized_instance(self.db(), &[Type::unknown(), Type::unknown()]);
- }
-
let items = items
.iter()
.map(|item| [item.key.as_ref(), Some(&item.value)])
diff --git a/crates/ty_python_semantic/src/types/infer/builder/binary_expressions.rs b/crates/ty_python_semantic/src/types/infer/builder/binary_expressions.rs
index bd36a0649d..b230d1dfa2 100644
--- a/crates/ty_python_semantic/src/types/infer/builder/binary_expressions.rs
+++ b/crates/ty_python_semantic/src/types/infer/builder/binary_expressions.rs
@@ -357,9 +357,6 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
(typevar @ Type::Dynamic(DynamicType::UnspecializedTypeVar), _, _)
| (_, typevar @ Type::Dynamic(DynamicType::UnspecializedTypeVar), _) => Some(typevar),
- (todo @ Type::Dynamic(DynamicType::TodoFunctionalTypedDict), _, _)
- | (_, todo @ Type::Dynamic(DynamicType::TodoFunctionalTypedDict), _) => Some(todo),
-
// When both operands are the same constrained TypeVar (e.g., `T: (int, str)`),
// we check if the operation is valid for each constraint paired with itself.
// This is different from treating it as a union, where we'd check all combinations.
diff --git a/crates/ty_python_semantic/src/types/typevar.rs b/crates/ty_python_semantic/src/types/typevar.rs
index e02b52e8e4..6a0c77c0e6 100644
--- a/crates/ty_python_semantic/src/types/typevar.rs
+++ b/crates/ty_python_semantic/src/types/typevar.rs
@@ -541,7 +541,6 @@ impl<'db> TypeVarInstance<'db> {
DynamicType::Todo(_)
| DynamicType::TodoUnpack
| DynamicType::TodoStarredExpression
- | DynamicType::TodoFunctionalTypedDict
| DynamicType::TodoTypeVarTuple => Parameters::todo(),
DynamicType::Any
| DynamicType::UnknownI pushed that as a commit to 592c30c if that's easier for you to apply it! |
|
(Mid-way through addressing locally, just marking as "resolved" once I've addressed on my local branch, recognize they aren't resolved on GH yet...) |
f7f0130 to
12ce19c
Compare
16d6a83 to
001485c
Compare
|
I put this up here so the diff is easy to review: #24253 |
001485c to
9746f58
Compare
|
Okay, having seen #24253, you've persuaded me that the lenient fallback for invalidly defined |
9746f58 to
df581ea
Compare
|
(Applied!) |
|
(I pushed a couple more simplifications/fixes, hope that's okay!) |
AlexWaygood
left a comment
There was a problem hiding this comment.
One more thing I noticed, but otherwise this looks great to me now! (And the other two PRs LGTM too.)
As I mentioned offline, though, it would be great if you could merge the three PRs into one before I do a final approval. I haven't looked at the conformance or ecosystem reports yet -- it's a bit hard to do so while the work is split between three PRs.
|
Sounds good, I will address that last comment then merge the other two PRs in here. |
c67996f to
c196f46
Compare
## Summary This PR adds handling for class-based TypedDicts that inherit from functional TypedDicts. Part of: astral-sh/ty#3095.
## Summary Part of: astral-sh/ty#3095.
|
Okay, all merged, reviewing ecosystem now... |
|
There's a diagnostic for: And then scipy-stubs has: Pyright rejects both of these. |
|
I'm inclined to support |
|
Eh, nevermind. |
6ab8cf8 to
1354606
Compare
|
It looks like there's just one thing we're missing here to get us to be fully passing on the from typing import TypedDict
BadTypedDict3 = TypedDict("WrongName", {"name": str}) # EBecause If you ask me, this is needlessly pedantic and something that should really be the job of a linter rather than a type checker. But it's pretty easy for us to detect this, so we may as well emit a diagnostic for it (but maybe it should just be a warning by default). We could easily add this as a followup, though; it doesn't need to be done in this PR. |
|
Sounds good. Happy to do that as a follow-up! |
## Summary
Given `BadTypedDict = TypedDict("WrongName", {"name": str})`, the
conformance test suite suggests we need to raise a diagnostic due to the
mismatch between `BadTypedDict` and `WrongName`.
See:
#24174 (comment).
---------
Co-authored-by: David Peter <mail@david-peter.de>
Summary
This PR adds basic support for functional TypedDict construction, including recursive TypedDicts. The intent is to follow the patterns we've established for functional NamedTuple and
type(...)calls as closely as we can.There are two follow-up PRs that were carved out to make them easier to review:
(My intent is to merge the stack once all three are approved. E.g., the new false positive in the ecosystem test is fixed in #24176.)
Part of: astral-sh/ty#3095.