Add TypedDict closed and extra_items support (PEP 728)#2922
Conversation
|
Warning Rate limit exceeded@koxudaxi has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 19 minutes and 5 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (12)
📝 WalkthroughWalkthroughThis PR implements PEP 728 TypedDict support and backport handling: TypedDict declarations are made closed/extra_items-aware, PythonVersion gains a feature flag, JSON Schema parsing propagates typed-dict kwargs and base-class markers, and model rendering includes conditional typing_extensions backport usage. Changes
Sequence Diagram(s)sequenceDiagram
participant Schema as JSON Schema
participant Parser as Parser.jsonschema
participant PV as PythonVersion
participant TD as TypedDict Model
participant Gen as Code Generator
Schema->>Parser: parse schema (includes additionalProperties / $ref / x-is-base-class)
Parser->>Parser: set_schema_extensions / set_additional_properties
Parser->>PV: query has_typed_dict_closed
alt additionalProperties == false
Parser->>TD: set typed_dict_kwargs {closed=True}
else additionalProperties is schema
Parser->>TD: derive additionalPropertiesType
Parser->>TD: set typed_dict_kwargs {extra_items=Type}
end
alt PV lacks native support
Parser->>TD: set use_typeddict_backport=True
end
Note over TD,Gen: Rendering phase
TD->>TD: _has_typed_dict_kwargs?
alt backport required
TD->>Gen: include IMPORT_TYPED_DICT_BACKPORT
Gen->>Gen: emit class X(TypedDict, closed=True / extra_items=...)
else native support
TD->>Gen: include TypedDict import
Gen->>Gen: emit class X(TypedDict, closed=True / extra_items=...)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
CodSpeed Performance ReportMerging #2922 will not alter performanceComparing
|
There was a problem hiding this comment.
Actionable comments posted: 2
Fix all issues with AI Agents 🤖
In @src/datamodel_code_generator/_types/generate_config_dict.py:
- Around line 6-8: Remove the unused TypedDict import from the stdlib typing
import: keep "from typing import TYPE_CHECKING, Any" (remove TypedDict) and rely
on the backport "from typing_extensions import NotRequired, TypedDict" already
present; update the import line(s) accordingly so only typing_extensions
provides TypedDict (needed for closed=True) and avoid the shadowed stdlib
symbol.
In @src/datamodel_code_generator/_types/parser_config_dicts.py:
- Around line 6-8: Remove the redundant TypedDict import from the typing import
list in parser_config_dicts.py: update the line that currently reads "from
typing import TYPE_CHECKING, Any, TypeAlias, TypedDict" to drop TypedDict so
only TYPE_CHECKING, Any, and TypeAlias remain, relying on the TypedDict imported
from typing_extensions; this removes the shadowed/unused symbol and keeps
NotRequired/TypedDict usage from typing_extensions intact.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/data/expected/main/input_model/config_class.py (1)
9-13: Remove redundantTypedDictimport fromtyping.Line 9 imports
TypedDictfromtyping, but line 13 re-imports it fromtyping_extensions. Sincetyping_extensions.TypedDictis required for theclosed=Trueparameter (PEP 728 backport), the import fromtypingon line 9 is unused and should be removed.🔎 Proposed fix
-from typing import Any, Literal, TypeAlias, TypedDict +from typing import Any, Literal, TypeAlias
🧹 Nitpick comments (2)
src/datamodel_code_generator/model/typed_dict.py (1)
128-139: Minor duplication of kwargs string computation.The
kwargs_stris computed in both_setup_closed_extra_items(stored astyped_dict_kwargs_suffix) and again inbase_class. Consider reusing the pre-computed suffix:🔎 Proposed simplification
@property def base_class(self) -> str: """Get base class string with kwargs if needed. For PEP 728 support, includes closed=True or extra_items=X in the base class. """ base = super().base_class - typed_dict_kwargs = self.extra_template_data.get("typed_dict_kwargs") - if typed_dict_kwargs: - kwargs_str = ", ".join(f"{k}={v}" for k, v in typed_dict_kwargs.items()) - return f"{base}, {kwargs_str}" + kwargs_suffix = self.extra_template_data.get("typed_dict_kwargs_suffix") + if kwargs_suffix: + return f"{base}{kwargs_suffix}" return basetests/main/jsonschema/test_main_jsonschema.py (1)
4262-4316: TypedDict closed/extra_items tests align with PEP 728; consider minor coverage + skip refinementsThe three new tests correctly exercise the intended mapping:
typed_dict_closed.json→TypedDict(..., closed=True)foradditionalProperties: false(with both native 3.13 and 3.10 backport via different golden files).typed_dict_extra_items.json→TypedDict(..., extra_items=...)for schema-valuedadditionalPropertieson a 3.13 target.Two small, non-blocking suggestions:
Backport coverage for
extra_itemsas well
If the implementation also backportsextra_itemsviatyping_extensionsfor< 3.13(as it does forclosed), a companion test would harden that path against regressions, mirroringtest_main_typed_dict_closed_backport.Unify Black compatibility gating for the backport test (Lines 4280–4283)
Instead of hard-codingblack.__version__.split(".")[0] == "22", you can lean on the existing helper for consistency and future-proofing:Suggested tweak to the skip condition
-@pytest.mark.skipif( - black.__version__.split(".")[0] == "22", - reason="Installed black doesn't support Python version 3.10", -) +@pytest.mark.skipif( + not is_supported_in_black(PythonVersion.PY_310), + reason="Installed black doesn't support Python 3.10 formatting", +) def test_main_typed_dict_closed_backport(output_file: Path) -> None: ...And, if you do want explicit
extra_itemsbackport coverage, something along these lines would stay consistent with the existing pattern:Optional extra_items backport test sketch
+@pytest.mark.skipif( + not is_supported_in_black(PythonVersion.PY_310), + reason="Installed black doesn't support Python 3.10 formatting", +) +def test_main_typed_dict_extra_items_backport(output_file: Path) -> None: + """Test TypedDict extra_items uses typing_extensions on Python < 3.13.""" + run_main_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "typed_dict_extra_items.json", + output_path=output_file, + input_file_type=None, + assert_func=assert_file_content, + expected_file="typed_dict_extra_items_py310.py", + extra_args=[ + "--output-model-type", + "typing.TypedDict", + "--target-python-version", + "3.10", + ], + )
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
src/datamodel_code_generator/model/template/TypedDictFunction.jinja2is excluded by none and included by nonetests/data/jsonschema/typed_dict_closed.jsonis excluded by!tests/data/**/*.jsonand included by nonetests/data/jsonschema/typed_dict_extra_items.jsonis excluded by!tests/data/**/*.jsonand included by none
📒 Files selected for processing (12)
src/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dicts.pysrc/datamodel_code_generator/format.pysrc/datamodel_code_generator/model/typed_dict.pysrc/datamodel_code_generator/parser/jsonschema.pytests/data/expected/main/input_model/config_class.pytests/data/expected/main/jsonschema/typed_dict_closed.pytests/data/expected/main/jsonschema/typed_dict_closed_py310.pytests/data/expected/main/jsonschema/typed_dict_extra_items.pytests/main/jsonschema/test_main_jsonschema.pytests/model/test_typed_dict.py
🧰 Additional context used
🧬 Code graph analysis (8)
tests/data/expected/main/jsonschema/typed_dict_extra_items.py (1)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(50-175)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(50-175)
tests/data/expected/main/jsonschema/typed_dict_closed.py (2)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(50-175)tests/data/expected/main/jsonschema/typed_dict_closed_py310.py (1)
ClosedModel(10-12)
tests/model/test_typed_dict.py (1)
src/datamodel_code_generator/model/typed_dict.py (6)
imports(142-151)imports(225-231)DataModelField(178-231)TypedDict(50-175)_has_typed_dict_kwargs(119-121)base_class(129-139)
src/datamodel_code_generator/parser/jsonschema.py (1)
src/datamodel_code_generator/format.py (1)
has_typed_dict_closed(132-134)
tests/data/expected/main/input_model/config_class.py (2)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(50-175)src/datamodel_code_generator/enums.py (1)
DataclassArguments(15-27)
src/datamodel_code_generator/model/typed_dict.py (3)
src/datamodel_code_generator/model/base.py (3)
base_class(849-851)imports(326-351)imports(823-828)src/datamodel_code_generator/types.py (1)
imports(620-674)src/datamodel_code_generator/imports.py (2)
Import(20-38)append(74-89)
tests/main/jsonschema/test_main_jsonschema.py (1)
tests/main/conftest.py (2)
output_file(99-101)run_main_and_assert(245-409)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/_types/generate_config_dict.py
8-8: Redefinition of unused TypedDict from line 6
(F811)
src/datamodel_code_generator/_types/parser_config_dicts.py
8-8: Redefinition of unused TypedDict from line 6
(F811)
tests/data/expected/main/input_model/config_class.py
13-13: Redefinition of unused TypedDict from line 9
(F811)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.13 on macOS
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (16)
tests/data/expected/main/jsonschema/typed_dict_extra_items.py (1)
1-12: LGTM!The test expectation file correctly represents the expected output for Python 3.13+ where
extra_itemsis natively supported intyping.TypedDict. The imports fromtypingand the class syntax are correct for PEP 728 semantics.src/datamodel_code_generator/format.py (1)
131-135: LGTM!The
has_typed_dict_closedproperty correctly gates the PEP 728 feature (closed/extra_items) to Python 3.13+, following the established pattern for version-specific feature detection.src/datamodel_code_generator/_types/parse_config_dict.py (1)
6-16: LGTM!The use of
typing_extensions.TypedDictwithclosed=Trueis correct for maintaining Python < 3.13 compatibility. This is a good example of dogfooding the PEP 728 support being implemented.src/datamodel_code_generator/model/typed_dict.py (2)
92-116: LGTM - Clean PEP 728 setup logic.The implementation correctly maps JSON Schema
additionalPropertiessemantics to PEP 728 TypedDict parameters. The identity checkadditional_props is Falseis appropriate here since JSON Schema explicitly usesfalsefor closed semantics.
141-151: LGTM - Correct backport import handling.The logic correctly replaces
typing.TypedDictwithtyping_extensions.TypedDictonly when both conditions are met: the backport is required (Python < 3.13) and the TypedDict uses closed/extra_items kwargs.src/datamodel_code_generator/_types/generate_config_dict.py (1)
41-41: LGTM - Closed TypedDict for config validation.Using
closed=Trueon configuration TypedDicts is a good practice as it helps catch typos in config keys at type-check time.tests/data/expected/main/jsonschema/typed_dict_closed.py (1)
1-12: LGTM!The test expectation correctly represents the generated output for Python 3.13+ where
typing.TypedDictnatively supports theclosedparameter. The import fromtyping(nottyping_extensions) is correct for this target version.src/datamodel_code_generator/_types/parser_config_dicts.py (1)
43-43: LGTM - Consistent closed TypedDict hierarchy.All parser config TypedDicts are now closed, which provides type-safety benefits by catching invalid config keys. The inheritance chain correctly declares
closed=Trueat each level, and the newopenapi_include_pathsfield is properly added toOpenAPIParserConfigDict.Also applies to: 163-163, 169-170, 173-177
tests/data/expected/main/jsonschema/typed_dict_closed_py310.py (1)
1-12: LGTM!This test fixture correctly demonstrates the expected output for a closed TypedDict on Python 3.10. The use of
typing_extensions.TypedDictfor theclosed=Trueparameter is appropriate since PEP 728 features require a backport for Python versions before 3.13.tests/data/expected/main/input_model/config_class.py (2)
45-56: LGTM!The
DataclassArgumentsTypedDict is correctly marked asclosed=True, which aligns with the PEP 728 implementation for restricting additional keys in configuration dictionaries.
117-248: LGTM!The
GenerateConfigTypedDict withclosed=Trueis appropriate for a configuration type that should not accept arbitrary extra keys.src/datamodel_code_generator/parser/jsonschema.py (2)
1138-1157: LGTM! Clean implementation of PEP 728 TypedDict support.The logic correctly maps JSON Schema
additionalPropertiessemantics to TypedDict parameters:
additionalProperties: false→ sets backport flag forclosed=TrueadditionalProperties: { type: X }→ extracts type hint forextra_itemsThe backport flag is appropriately set based on
target_python_version.has_typed_dict_closed.
1150-1157: Verify behavior when_build_lightweight_typereturnsNone.When
additionalPropertiesis a complex schema that_build_lightweight_typecannot resolve, neitheradditionalPropertiesTypenoruse_typeddict_backportis set. This means the TypedDict won't have anextra_itemsconstraint in such cases.This appears to be intentional graceful degradation, but please confirm this is the expected behavior for complex
additionalPropertiesschemas that can't be resolved to a simple type hint.tests/model/test_typed_dict.py (3)
5-9: LGTM! Imports support new PEP 728 test functionality.The new imports are all necessary for testing TypedDict's closed and extra_items features:
defaultdictfor test helper constructionIMPORT_TYPED_DICTandIMPORT_TYPED_DICT_BACKPORTconstants for verifying import selectionTypedDictandReferencefor creating test instances
40-48: LGTM! Well-designed test helper function.The
_create_typed_dicthelper effectively reduces duplication across tests and clearly encapsulates the setup logic. The defaultdict structure correctly mirrors the TypedDict constructor's expectations for extra_template_data.
51-122: LGTM! Comprehensive test coverage for PEP 728 TypedDict features.The test suite thoroughly validates the TypedDict implementation:
- ✅ Closed and extra_items kwargs generation from schema properties
- ✅ Base class composition with and without kwargs
- ✅ Import selection (standard typing vs typing_extensions backport)
- ✅ Edge case:
additionalProperties: truecorrectly excluded from kwargsThe tests correctly verify string values in
typed_dict_kwargs(e.g.,"True","bool") for template rendering and code-formattedtyped_dict_kwargs_suffixvalues.Note: Tests access private method
_has_typed_dict_kwargs. While acceptable in unit tests, this coupling could make tests fragile if the implementation's internal structure changes.
e9f2419 to
3c39200
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Fix all issues with AI Agents 🤖
In @tests/model/test_typed_dict.py:
- Around line 51-122: Add tests to cover the is_base_class=True path so that
TypedDict kwargs are not applied when the typed dict is a base class: create two
tests using _create_typed_dict with {"additionalProperties": False,
"is_base_class": True} and {"additionalPropertiesType": "str", "is_base_class":
True} respectively, and assert in both that td._has_typed_dict_kwargs is False,
td.extra_template_data.get("typed_dict_kwargs") is None, and td.base_class ==
"TypedDict"; this verifies the logic in
src/datamodel_code_generator/model/typed_dict.py (the branches around
is_base_class handling that skip setting closed=True or extra_items).
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/data/expected/main/input_model/config_class.py (1)
9-13: Remove unusedTypedDictimport fromtypingin generated output.This generated file has a redundant
TypedDictimport on line 9 that is shadowed by line 13. This indicates the code generator may be producing unnecessary imports when generating closed TypedDicts.🔎 Expected fix in generated output
-from typing import Any, Literal, TypeAlias, TypedDict +from typing import Any, Literal, TypeAlias
♻️ Duplicate comments (2)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
6-8: Remove unusedTypedDictimport fromtyping.The
TypedDictimport on line 6 is shadowed by the import on line 8 fromtyping_extensions. Sinceclosed=Truerequires the typing_extensions backport, only that import is needed.🔎 Proposed fix
-from typing import TYPE_CHECKING, Any, TypedDict +from typing import TYPE_CHECKING, Any from typing_extensions import NotRequired, TypedDictsrc/datamodel_code_generator/_types/parser_config_dicts.py (1)
6-8: Remove unusedTypedDictimport fromtyping.The
TypedDictimport on line 6 is shadowed by line 8's import fromtyping_extensions. Sinceclosed=Truerequires the typing_extensions backport, only that import is needed.🔎 Proposed fix
-from typing import TYPE_CHECKING, Any, TypeAlias, TypedDict +from typing import TYPE_CHECKING, Any, TypeAlias from typing_extensions import NotRequired, TypedDict
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
src/datamodel_code_generator/model/template/TypedDictFunction.jinja2is excluded by none and included by nonetests/data/jsonschema/typed_dict_closed.jsonis excluded by!tests/data/**/*.jsonand included by nonetests/data/jsonschema/typed_dict_extra_items.jsonis excluded by!tests/data/**/*.jsonand included by none
📒 Files selected for processing (13)
src/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dicts.pysrc/datamodel_code_generator/format.pysrc/datamodel_code_generator/input_model.pysrc/datamodel_code_generator/model/typed_dict.pysrc/datamodel_code_generator/parser/jsonschema.pytests/data/expected/main/input_model/config_class.pytests/data/expected/main/jsonschema/typed_dict_closed.pytests/data/expected/main/jsonschema/typed_dict_closed_py310.pytests/data/expected/main/jsonschema/typed_dict_extra_items.pytests/main/jsonschema/test_main_jsonschema.pytests/model/test_typed_dict.py
🚧 Files skipped from review as they are similar to previous changes (6)
- src/datamodel_code_generator/format.py
- src/datamodel_code_generator/parser/jsonschema.py
- tests/data/expected/main/jsonschema/typed_dict_closed.py
- tests/main/jsonschema/test_main_jsonschema.py
- tests/data/expected/main/jsonschema/typed_dict_closed_py310.py
- tests/data/expected/main/jsonschema/typed_dict_extra_items.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-01-02T08:25:19.839Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2890
File: tests/data/expected/main/jsonschema/ref_nullable_with_constraint.py:14-15
Timestamp: 2026-01-02T08:25:19.839Z
Learning: The datamodel-code-generator currently generates RootModel subclasses with an explicit `root` field annotation (e.g., `class StringType(RootModel[str]): root: str`). This is existing behavior of the code generator and should not be flagged as an issue introduced by new changes.
Applied to files:
src/datamodel_code_generator/input_model.py
📚 Learning: 2025-12-25T09:22:22.481Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43
Timestamp: 2025-12-25T09:22:22.481Z
Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dicts.pysrc/datamodel_code_generator/_types/generate_config_dict.py
🧬 Code graph analysis (2)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(50-181)
tests/data/expected/main/input_model/config_class.py (2)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(50-181)src/datamodel_code_generator/enums.py (1)
DataclassArguments(15-27)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/_types/parser_config_dicts.py
8-8: Redefinition of unused TypedDict from line 6
(F811)
src/datamodel_code_generator/_types/generate_config_dict.py
8-8: Redefinition of unused TypedDict from line 6
(F811)
tests/data/expected/main/input_model/config_class.py
13-13: Redefinition of unused TypedDict from line 9
(F811)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.14 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (15)
src/datamodel_code_generator/input_model.py (2)
656-657: LGTM: Base class marker for PEP 728 compatibility.The
x-is-base-classmarker correctly preventsclosed=Truefrom being applied to TypedDict base classes, which is necessary because PEP 728 doesn't allow child TypedDicts to extend closed parents.
806-811: LGTM: Correct prioritization of base-class schemas.The merging logic properly prioritizes schemas marked with
x-is-base-class, ensuring that base-class variants are retained over non-base-class variants. This supports correct TypedDict inheritance resolution.src/datamodel_code_generator/_types/parse_config_dict.py (2)
6-8: LGTM: Clean imports for closed TypedDict.The imports are correctly structured, using
typing_extensions.TypedDictto support theclosed=Trueparameter from PEP 728.
16-16: LGTM: Properly closed TypedDict.The
closed=Trueparameter correctly restricts the TypedDict to only the declared fields, implementing PEP 728 semantics.src/datamodel_code_generator/_types/generate_config_dict.py (1)
41-41: LGTM: Properly closed TypedDict.The
closed=Trueparameter correctly implements PEP 728 semantics for GenerateConfigDict.tests/data/expected/main/input_model/config_class.py (1)
45-45: LGTM: Closed TypedDicts in test expectations.Both
DataclassArgumentsandGenerateConfigcorrectly useclosed=True, demonstrating proper PEP 728 implementation in the expected test output.Also applies to: 117-117
src/datamodel_code_generator/_types/parser_config_dicts.py (1)
163-163: LGTM: Properly closed TypedDicts with new field.Both
GraphQLParserConfigDictandOpenAPIParserConfigDictcorrectly useclosed=Trueto implement PEP 728 semantics. The addition ofopenapi_include_pathsfield toOpenAPIParserConfigDictis appropriate.Also applies to: 173-177
tests/model/test_typed_dict.py (2)
5-9: LGTM!The new imports are appropriate and used throughout the test file for the PEP 728 TypedDict features.
40-48: LGTM!The helper function is well-designed and provides a clean way to create TypedDict instances for testing with optional extra_template_data.
src/datamodel_code_generator/model/typed_dict.py (6)
19-19: LGTM!The backport import addition is necessary for PEP 728 support on Python < 3.13.
92-93: LGTM!The placement of
_setup_closed_extra_items()aftersuper().__init__()is correct, ensuringextra_template_datais available.
95-123: LGTM - Correct implementation of PEP 728 semantics.The method correctly implements the mapping:
additionalProperties: false→closed=TrueadditionalProperties: { type: X }→extra_items=XThe exclusion of base classes (lines 113, 115) is correct per PEP 728, as child TypedDicts cannot extend a closed parent. The use of
elifensuresclosedandextra_itemsare mutually exclusive, which aligns with JSON Schema semantics whereadditionalPropertiesis eitherfalseor a schema object.
124-132: LGTM!Both properties provide clean boolean checks for TypedDict kwargs presence and backport usage.
134-145: LGTM!The
base_classoverride correctly formats PEP 728 kwargs into the base class string (e.g.,TypedDict, closed=True).
147-157: LGTM - Correct backport import logic.The condition on line 152 correctly requires both
_use_typeddict_backportand_has_typed_dict_kwargsto be true, ensuring the backport is only used for PEP 728 features on Python < 3.13.The import replacement (lines 154-155) correctly filters out
IMPORT_TYPED_DICTand addsIMPORT_TYPED_DICT_BACKPORT.
3c39200 to
afb4178
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2922 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 93 92 -1
Lines 16913 16957 +44
Branches 1966 1976 +10
=========================================
+ Hits 16913 16957 +44
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
🎉 Released in 0.52.2 This PR is now available in the latest release. See the release notes for details. |
Fixes: #2921
Summary by CodeRabbit
New Features
Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.