Add multiple --input-model support with inheritance preservation#2881
Add multiple --input-model support with inheritance preservation#2881
Conversation
|
Warning Rate limit exceeded@koxudaxi has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 32 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 selected for processing (2)
📝 WalkthroughWalkthroughConfig.input_model changed from an optional string to an optional list of MODULE:NAME entries; CLI accepts repeated --input-model. Input-model loading/validation/merging moved into a new public loader load_model_schema (and public Error), and many inline type/schema helpers were removed from main.py and relocated to input_model.py. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant CLI as CLI / ArgParser
participant Main as __main__.py
participant Loader as input_model.load_model_schema
participant Importer as Module/File Importer
participant SchemaGen as model_json_schema
participant Transformer as Inheritance Transformer
participant Merger as Schema Merger
rect rgb(0,128,128,0.06)
CLI->>Main: parse args (repeated --input-model)
end
Main->>Loader: load_model_schema(input_models, input_file_type, ref_strategy, output_model_type)
loop per input_model
Loader->>Importer: import MODULE:NAME or load file path
alt import success
Importer-->>Loader: model class
Loader->>SchemaGen: call model_json_schema / extract schema
SchemaGen-->>Loader: schema fragment (with x-python-* metadata)
alt model has inheritance
Loader->>Transformer: convert inheritance → allOf
Transformer-->>Loader: transformed fragment
end
else import failure
Importer-->>Loader: raise InputModelError
end
end
Loader->>Merger: merge fragments into final schema (anyOf root + aggregated $defs) and apply ref_strategy
Merger-->>Loader: merged_schema
Loader-->>Main: return merged_schema or raise Error
Main->>Main: continue generation using merged_schema
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 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 |
|
📚 Docs Preview: https://pr-2881.datamodel-code-generator.pages.dev |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2881 +/- ##
==========================================
- Coverage 99.38% 99.37% -0.02%
==========================================
Files 91 92 +1
Lines 15643 16040 +397
Branches 1848 1893 +45
==========================================
+ Hits 15547 15939 +392
- Misses 50 52 +2
- Partials 46 49 +3
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:
|
CodSpeed Performance ReportMerging #2881 will not alter performanceComparing
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/datamodel_code_generator/__main__.py (1)
1764-1784:generate_cli_commandand multi‑valuedinput_modeldon’t yet match the new argparse semanticsWith
Config.input_model: Optional[list[str]]and--input-modelnow usingaction="append", a pyproject config like:input-model = ["mod_a:ModelA", "mod_b:ModelB"]will cause
generate_cli_commandto emit:datamodel-codegen --input-model "mod_a:ModelA" "mod_b:ModelB"However, argparse expects one value per
--input-modelflag in this configuration, so the second value will be misparsed as a positional/next option.To make
generate_cli_commandround‑trip correctly with the new multi‑model behavior, you’ll likely need to special‑caseinput_model(and any similar “append” options) so that lists are rendered as repeated flags, e.g.:datamodel-codegen --input-model mod_a:ModelA --input-model mod_b:ModelBrather than a single flag with a space‑separated list.
Also applies to: 465-465
🧹 Nitpick comments (2)
src/datamodel_code_generator/_types/openapi_parser_config_dict.py (1)
34-155: OpenAPI config now cleanly extends the shared JSON Schema parser configHaving
ParserConfig(TypedDict)as the shared base andJSONSchemaParserConfig(ParserConfig)as an intermediate, withOpenAPIParserConfigDict(JSONSchemaParserConfig)adding OpenAPI‑specific options, makes the hierarchy explicit and consistent with the runtimeParserConfigmodel. Only nit is the slight name asymmetry withJSONSchemaParserConfigDictin the JSON schema module, but that’s cosmetic.src/datamodel_code_generator/__main__.py (1)
388-389: Consider cleaning up unused# noqadirectives to satisfy Ruff hintsRuff reports several
RUF100warnings for unused# noqacodes (e.g.,PLC0415,UP007,UP045,PLR0912,PLR0914,PLR0915) on:
- The local
field_validatorimport inside the Pydantic v2 branch.- Some field declarations (
input,input_model, etc.).- Function definitions marked with complexity‑related
noqa.If these codes are no longer enabled in your ruff configuration, dropping the corresponding
# noqafragments (or narrowing them to only active codes you still need) will quiet the linter without changing behavior.Also applies to: 464-465, 1202-1202, 1287-1287, 1304-1305
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/_types/graphql_parser_config_dict.pysrc/datamodel_code_generator/_types/jsonschema_parser_config_dict.pysrc/datamodel_code_generator/_types/openapi_parser_config_dict.pysrc/datamodel_code_generator/arguments.pytests/data/python/input_model/inheritance_models.pytests/test_input_model.py
🧰 Additional context used
🧬 Code graph analysis (3)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/util.py (1)
field_validator(175-191)src/datamodel_code_generator/enums.py (3)
InputFileType(35-45)InputModelRefStrategy(206-217)DataModelType(48-56)
src/datamodel_code_generator/_types/graphql_parser_config_dict.py (2)
src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py (1)
ParserConfig(33-144)src/datamodel_code_generator/_types/openapi_parser_config_dict.py (1)
ParserConfig(34-145)
src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py (3)
src/datamodel_code_generator/_types/graphql_parser_config_dict.py (1)
ParserConfig(33-144)src/datamodel_code_generator/_types/openapi_parser_config_dict.py (1)
ParserConfig(34-145)src/datamodel_code_generator/config.py (1)
ParserConfig(201-324)
🪛 GitHub Actions: Lint
src/datamodel_code_generator/__main__.py
[error] 1276-1276: ruff: PLC0206 Extracting value from dictionary without calling .items()
[error] 1367-1367: ruff: E501 Line too long (123 > 120)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py
388-388: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
464-464: Unused noqa directive (non-enabled: UP007, UP045)
Remove unused noqa directive
(RUF100)
465-465: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
1202-1202: Unused noqa directive (non-enabled: PLR0912)
Remove unused noqa directive
(RUF100)
1287-1287: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
1304-1304: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1305-1305: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (12)
- GitHub Check: benchmarks
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: Analyze (python)
- GitHub Check: 3.13 on Windows
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.11 on Windows
🔇 Additional comments (9)
src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py (1)
33-148: Shared ParserConfig base for JSON Schema looks consistent and backwards‑compatibleDefining
ParserConfig(TypedDict)and havingJSONSchemaParserConfigDict(ParserConfig)as a thin subclass cleanly preserves the old public name while aligning with the new shared config structure used by OpenAPI/GraphQL. No issues from a typing or compatibility standpoint.src/datamodel_code_generator/arguments.py (1)
161-169:--input-modelappend semantics align with new multi‑model supportSwitching
--input-modeltoaction="append"with updated help text is consistent withConfig.input_model: Optional[list[str]]and the new multi‑model loading path. No issues spotted here.src/datamodel_code_generator/_types/graphql_parser_config_dict.py (1)
33-149: GraphQL parser config layering is coherent with JSONSchema/OpenAPIUsing a shared
ParserConfig(TypedDict)and extending it viaGraphQLParserConfigDictfor the scalar/union model types matches the pattern in the other parser config modules and keeps the config surfaces aligned. Looks good.tests/data/python/input_model/inheritance_models.py (1)
1-59: Inheritance fixture models cover key scenarios and look correctThe Pydantic models capture straight, forked, empty‑child, and optional‑only inheritance patterns needed for the new tests, with clean typing and docstrings. No issues.
tests/test_input_model.py (3)
1150-1199: Multi‑model test helpers correctly exercise repeated--input-modelThe new
run_multiple_input_models_and_assert/run_multiple_input_models_error_and_asserthelpers build args via repeated--input-modelflags, assert exit codes, and centralize output/stderr checks. This nicely mirrors the new CLI semantics and keeps the later tests concise.
1202-1382: Inheritance and multi‑model tests provide strong coverage of new behaviorThe added tests around single‑model inheritance, multi‑level chains, forked inheritance, mixed depths, union/TypeAlias generation, and Pydantic/dataclass outputs collectively validate the new inheritance‑aware schema transformation and multi‑model loader. The negative cases for non‑BaseModel, Pydantic v1 runtime, invalid formats, and incompatible
--input-file-typeare also well specified and match the new error messages.
1668-1731: sys.path/CWD and filename‑only tests are a good sanity check on module loadingThe tests for
cwdalready insys.pathand.pyfiles without path separators validate that the new loader neither duplicatescwdentries nor fails on filename‑only imports. This guards against subtle regressions in thesys.pathmanipulation and path vs module detection logic.src/datamodel_code_generator/__main__.py (2)
388-398: Config.input_model list type and coercion validators are appropriateNormalizing
input_modeltoOptional[list[str]]withcoerce_input_model_to_listin both the Pydantic v2 and v1 branches keeps pyproject (string or list) and CLI (action="append") inputs compatible while presenting a single internal shape. This is a clean way to extend behavior without breaking existing configs.If you want extra safety, double‑check Pydantic v1/v2 docs to ensure
mode="before"field validators with@classmethodsignatures are still the recommended pattern for this style of coercion.Also applies to: 456-463, 465-467
2156-2167: main() correctly routes allinput_modelusage through the new multi‑model loaderThe updated
mainpath unconditionally calls_load_multiple_model_schemaswhenconfig.input_modelis set, letting that function dispatch to the existing_load_model_schemafor single‑model cases and to the new multi‑model logic otherwise. This keeps backward behavior for single models while centralizing validation and schema generation for the new multi‑model scenarios.
7e63c17 to
00a3dff
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/datamodel_code_generator/__main__.py (2)
1202-1275: Fix dictionary iteration pattern (PLC0206) and remove unusednoqadirective.Two issues need attention:
- Line 1202: The
# noqa: PLR0912directive is unused per Ruff and should be removed.- Lines 1271-1273: The loop that copies extra schema keys triggers PLC0206 by re-indexing the dictionary during iteration.
🔎 Proposed fixes
-def _transform_single_model_to_inheritance( # noqa: PLR0912 +def _transform_single_model_to_inheritance( schema: dict[str, object], model_class: type, schema_generator: type, processed_parents: dict[str, dict[str, object]] | None = None, ) -> dict[str, object]:And fix the dictionary iteration:
- for key in schema: - if key not in {"$defs", "properties", "required", "title", "type", "allOf"}: - new_schema[key] = schema[key] + for key, value in schema.items(): + if key not in {"$defs", "properties", "required", "title", "type", "allOf"}: + new_schema[key] = value
1278-1415: Fix long line (E501) and remove unusednoqadirectives.Several issues need attention:
- Line 1278: The
# noqa: PLR0912, PLR0914, PLR0915directives are unused.- Lines 1295-1296: The
# noqa: PLC0415directives are unused.- Line 1359: The error message exceeds 120 characters.
🔎 Proposed fixes
Remove unused noqa directives:
-def _load_multiple_model_schemas( # noqa: PLR0912, PLR0914, PLR0915 +def _load_multiple_model_schemas( input_models: list[str], input_file_type: InputFileType, ref_strategy: InputModelRefStrategy | None = None, output_model_type: DataModelType = DataModelType.PydanticBaseModel, ) -> dict[str, object]:- import importlib.util # noqa: PLC0415 - import sys # noqa: PLC0415 + import importlib.util + import sysBreak the long error message:
- if not hasattr(obj, "model_json_schema"): - msg = "Multiple --input-model with Pydantic model requires Pydantic v2 runtime. Please upgrade Pydantic to v2." - raise Error(msg) + if not hasattr(obj, "model_json_schema"): + msg = ( + "Multiple --input-model with Pydantic model requires Pydantic v2 runtime. " + "Please upgrade Pydantic to v2." + ) + raise Error(msg)
🧹 Nitpick comments (4)
tests/test_input_model.py (2)
1316-1336: Consider consolidating duplicate test.
test_input_model_multiple_generates_anyofappears to test the same scenario astest_input_model_multiple_forked_inheritance(same inputs, same expected output file). If the intent is to emphasize the TypeAlias/union behavior, consider adding a unique assertion or documenting the distinction more clearly.
1581-1585: Consider using a closure variable instead of function attribute.The pattern of using
hasattr(mock_spec, "called")and settingmock_spec.called = Trueworks but is unconventional. A closure variable would be clearer.🔎 Alternative using closure
- def mock_spec(*args: object, **kwargs: object) -> None: - if hasattr(mock_spec, "called"): - return None - mock_spec.called = True # type: ignore[attr-defined] - return original_spec_from_file_location(*args, **kwargs) + called = False + + def mock_spec(*args: object, **kwargs: object) -> None: + nonlocal called + if called: + return None + called = True + return original_spec_from_file_location(*args, **kwargs)src/datamodel_code_generator/__main__.py (2)
388-396: Remove unusednoqadirective on Line 388.The
# noqa: PLC0415is flagged as unused. While the project keeps defensive noqa directives on lazy imports inside functions/methods, this import is at class-level within a validator block, not truly "lazy" in the same sense.🔎 Suggested fix
- from pydantic import field_validator as _field_validator # noqa: PLC0415 + from pydantic import field_validator as _field_validator
465-465: Remove unusednoqadirective.The
# noqa: UP045is flagged as unused by Ruff.🔎 Suggested fix
- input_model: Optional[list[str]] = None # noqa: UP045 + input_model: Optional[list[str]] = None
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/_types/graphql_parser_config_dict.pysrc/datamodel_code_generator/_types/jsonschema_parser_config_dict.pysrc/datamodel_code_generator/_types/openapi_parser_config_dict.pysrc/datamodel_code_generator/arguments.pytests/data/expected/main/input_model/forked_inheritance.pytests/data/expected/main/input_model/mixed_inheritance.pytests/data/expected/main/input_model/multi_level_inheritance.pytests/data/expected/main/input_model/no_inheritance.pytests/data/expected/main/input_model/single_inheritance.pytests/data/python/input_model/inheritance_models.pytests/test_input_model.py
🚧 Files skipped from review as they are similar to previous changes (3)
- src/datamodel_code_generator/_types/openapi_parser_config_dict.py
- src/datamodel_code_generator/arguments.py
- tests/data/python/input_model/inheritance_models.py
🧰 Additional context used
🧠 Learnings (1)
📚 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/__main__.py
🧬 Code graph analysis (6)
tests/data/expected/main/input_model/mixed_inheritance.py (3)
src/datamodel_code_generator/model/type_alias.py (1)
TypeAlias(37-42)src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)tests/data/expected/main/input_model/multi_level_inheritance.py (4)
GrandParent(10-11)Parent(14-15)Intermediate(18-19)GrandChild(22-23)
tests/data/expected/main/input_model/multi_level_inheritance.py (2)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)tests/data/python/input_model/inheritance_models.py (4)
GrandParent(8-11)Parent(14-17)Intermediate(32-35)GrandChild(38-41)
tests/data/expected/main/input_model/no_inheritance.py (2)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)tests/data/python/input_model/inheritance_models.py (1)
NoInheritance(44-47)
src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py (2)
src/datamodel_code_generator/_types/graphql_parser_config_dict.py (1)
ParserConfig(33-144)src/datamodel_code_generator/_types/openapi_parser_config_dict.py (1)
ParserConfig(34-145)
tests/data/expected/main/input_model/single_inheritance.py (5)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)tests/data/expected/main/input_model/forked_inheritance.py (3)
GrandParent(10-11)Parent(14-15)ChildA(18-19)tests/data/expected/main/input_model/mixed_inheritance.py (3)
GrandParent(10-11)Parent(14-15)ChildA(18-19)tests/data/expected/main/input_model/multi_level_inheritance.py (2)
GrandParent(10-11)Parent(14-15)tests/data/python/input_model/inheritance_models.py (3)
GrandParent(8-11)Parent(14-17)ChildA(20-23)
tests/test_input_model.py (1)
src/datamodel_code_generator/__main__.py (2)
main(1909-2213)Exit(125-131)
🪛 GitHub Actions: Lint
src/datamodel_code_generator/__main__.py
[error] 1267-1269: ruff: PLC0206 Extracting value from dictionary without calling .items()
[error] 1355-1355: ruff: E501 Line too long (123 > 120)
[warning] ruff-format reformatted 2 files during pre-commit hooks
[warning] ruff-format reformatted 2 files during pre-commit hooks
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py
388-388: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
464-464: Unused noqa directive (non-enabled: UP007, UP045)
Remove unused noqa directive
(RUF100)
465-465: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
1202-1202: Unused noqa directive (non-enabled: PLR0912)
Remove unused noqa directive
(RUF100)
1278-1278: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
1295-1295: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1296-1296: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (12)
- GitHub Check: 3.14 on macOS
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (19)
tests/data/expected/main/input_model/no_inheritance.py (1)
1-11: LGTM!This test fixture correctly demonstrates the expected output for a simple model with no inheritance chain, properly converted from
BaseModeltoTypedDict.tests/data/expected/main/input_model/single_inheritance.py (1)
1-19: LGTM!This test fixture correctly demonstrates single-branch inheritance preservation when converting from Pydantic models to TypedDict. The class ordering (base → derived) and field types are accurate.
src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py (1)
33-148: LGTM!The refactoring to establish
ParserConfigas the base TypedDict is well-structured. KeepingJSONSchemaParserConfigDictas an empty subclass maintains backward compatibility while enabling the shared inheritance hierarchy across parser configurations.tests/data/expected/main/input_model/forked_inheritance.py (1)
1-26: LGTM!This test fixture correctly demonstrates forked inheritance preservation with a
TypeAliasunion representing the multiple child types. The structure properly captures the diamond-shaped inheritance pattern.tests/data/expected/main/input_model/multi_level_inheritance.py (1)
1-23: LGTM!This test fixture correctly demonstrates deep multi-level inheritance preservation (4 levels) with proper handling of generic types like
list[str].src/datamodel_code_generator/_types/graphql_parser_config_dict.py (1)
33-149: LGTM!The refactoring correctly separates the shared
ParserConfigbase from GraphQL-specific fields (data_model_scalar_type,data_model_union_type). This maintains backward compatibility while enabling type hierarchy reuse.tests/data/expected/main/input_model/mixed_inheritance.py (1)
1-30: LGTM!This test fixture correctly demonstrates complex mixed-depth inheritance where
ChildAandGrandChild(at different levels) share common ancestors. TheTypeAliasproperly represents the union of the specified input models.tests/test_input_model.py (8)
20-21: LGTM!Constants are well-defined. The timestamp format with timezone (
-07:00) is consistent with the fixture files showing UTC offset conversion.
1154-1203: LGTM!The helper functions are well-structured and follow the same pattern as the single-model helpers. The
expected_output_not_containsparameter is a useful addition for verifying exclusions.
1206-1266: LGTM!Single-model inheritance tests provide good coverage of basic, multi-level, and no-inheritance scenarios with deterministic output verification.
1338-1376: LGTM!Good coverage of different output model types (
pydantic.BaseModel,dataclasses.dataclass) for multiple input models.
1396-1423: LGTM!The Pydantic v1 error simulation using
mock_hasattris a reasonable approach for testing the version detection logic without requiring actual Pydantic v1 installation.
1503-1564: LGTM!Good edge case coverage including module reuse optimization, file path format, and ref-strategy compatibility.
1678-1703: LGTM!The
sys.pathduplication test correctly verifies that cwd is not added multiple times. The assertionfinal_count <= initial_count + 1properly handles both cases (cwd already present vs. newly added).
1706-1736: LGTM!Good test coverage for mixed input formats (module path + file path) in the same invocation.
src/datamodel_code_generator/__main__.py (4)
456-462: LGTM! Consistent backwards compatibility handling.The Pydantic v1 branch correctly mirrors the v2 implementation, ensuring
input_modelaccepts both string and list inputs.
1193-1199: LGTM! Clean parent extraction logic.The function correctly identifies direct BaseModel parents while excluding
BaseModelitself. The single-inheritance limitation (only first parent honored in Line 1227) is a known design choice.
1508-1509: LGTM! Correct integration of inheritance transformation.The single-model path now correctly applies the inheritance transformation, ensuring consistency with the multi-model flow.
2139-2144: LGTM! Clean integration of multi-model loading.The main function correctly dispatches to
_load_multiple_model_schemas, passing all necessary parameters including the ref strategy and output model type.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/datamodel_code_generator/__main__.py (3)
388-396: Clean backwards-compatible field validators (with minor lint cleanup).The
coerce_input_model_to_listvalidators for both Pydantic v1 and v2 nicely handle the transition from single to multiple--input-modelvalues, preserving backwards compatibility. The type change toOptional[list[str]]on line 465 is consistent.Minor cleanup: remove the unused
noqa: PLC0415directive on line 388, as flagged by static analysis.🔎 Proposed cleanup
- from pydantic import field_validator as _field_validator # noqa: PLC0415 + from pydantic import field_validator as _field_validatorAlso applies to: 456-462, 465-465
1276-1408: Well-architected multi-model loader with comprehensive validation.The
_load_multiple_model_schemasfunction provides solid multi-model support:
- Delegates to single-model path for backwards compatibility
- Reuses module loading via
loaded_modulescache- Validates all models are Pydantic v2 BaseModel classes
- Transforms each model to inheritance structure
- Merges all models into a unified schema with
anyOfroot references- Applies ref strategy filtering
The implementation handles both module and file-path formats correctly and provides clear error messages.
Minor cleanup: remove unused
noqadirectives on lines 1276, 1293, and 1294 as flagged by static analysis.🔎 Proposed cleanup
-def _load_multiple_model_schemas( # noqa: PLR0912, PLR0914, PLR0915 +def _load_multiple_model_schemas( input_models: list[str], input_file_type: InputFileType, ref_strategy: InputModelRefStrategy | None = None, output_model_type: DataModelType = DataModelType.PydanticBaseModel, ) -> dict[str, object]: """Load and merge schemas from multiple Python import paths with inheritance support. Args: input_models: List of import paths in 'module.path:ObjectName' format input_file_type: Current input file type setting for validation ref_strategy: Strategy for handling referenced types output_model_type: Target output model type for reuse-foreign strategy Returns: Merged schema dict with anyOf referencing all root models """ - import importlib.util # noqa: PLC0415 - import sys # noqa: PLC0415 + import importlib.util + import sysNote on potential edge case: As mentioned in past reviews,
$defsentries are keyed purely bymodel_class.__name__. If users pass multiple models with the same name from different modules, later definitions will overwrite earlier ones. This is an acceptable edge case for initial implementation but could be addressed in future enhancements by using fully-qualified names.
464-465: Optional: Investigate unusednoqadirectives.Static analysis flags
noqadirectives on lines 464-465 as unused. These may be legitimate suppressions for certain type-checking rules or false positives. Consider verifying and removing if truly unnecessary.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/__main__.pytests/test_input_model.py
🧰 Additional context used
🧬 Code graph analysis (2)
tests/test_input_model.py (2)
tests/conftest.py (2)
assert_output(545-560)freeze_time(352-355)src/datamodel_code_generator/__main__.py (2)
main(1902-2206)Exit(125-131)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/util.py (1)
field_validator(175-191)src/datamodel_code_generator/enums.py (3)
InputFileType(35-45)InputModelRefStrategy(206-217)DataModelType(48-56)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py
388-388: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
464-464: Unused noqa directive (non-enabled: UP007, UP045)
Remove unused noqa directive
(RUF100)
465-465: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
1276-1276: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
1293-1293: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1294-1294: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (16)
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on macOS
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: 3.14 on macOS
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on macOS
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (8)
tests/test_input_model.py (4)
6-6: LGTM! Clean imports and well-defined constants.The addition of
Pathimport and test utilities (assert_output,freeze_time) aligns with the new inheritance test requirements. TheEXPECTED_INPUT_MODEL_PATHandTIMESTAMPconstants provide clean reusable test data references.Also applies to: 15-15, 20-21
1154-1183: Excellent test helper abstraction.The
run_multiple_input_models_and_assertfunction provides clean support for testing multiple--input-modelinvocations. The addition ofexpected_output_not_containsfor negative assertions is a thoughtful enhancement over the single-model variant.
1185-1203: LGTM! Solid error-path test helper.The
run_multiple_input_models_error_and_assertfunction mirrors the success-path helper appropriately, ensuring comprehensive error scenario coverage for multi-model inputs.
1206-1744: Outstanding comprehensive test coverage for inheritance scenarios!The inheritance test suite is exceptionally thorough, covering:
- Single and multi-level inheritance chains
- Forked inheritance (multiple models sharing a common parent)
- Multiple output types (TypedDict, Pydantic, dataclass)
- Error conditions (invalid formats, missing modules/files, Pydantic v1 runtime)
- Edge cases (empty children, optional-only fields, config string coercion)
The use of
freeze_timeandassert_outputwith expected fixture files ensures deterministic, maintainable tests.src/datamodel_code_generator/__main__.py (4)
1193-1195: LGTM! Clean parent extraction logic.The
_get_base_model_parentsfunction correctly identifies direct BaseModel parents while excluding BaseModel itself, preventing infinite recursion in inheritance transformation.
1198-1273: Solid inheritance transformation implementation.The
_transform_single_model_to_inheritancefunction correctly:
- Recursively processes parent inheritance chains using the
processed_parentscache- Merges
$defsfrom parent schemas- Creates an
allOfstructure with parent reference- Filters out parent fields from child
propertiesandrequired- Preserves extra schema properties (like
x-python-type) using.items()iterationThe limitation of only honoring the first BaseModel parent in multi-inheritance scenarios is acceptable and aligns with previous design discussions.
1501-1502: LGTM! Clean integration of inheritance transformation.The call to
_transform_single_model_to_inheritanceis correctly placed after schema generation and type preservation, ensuring single-model inputs also benefit from inheritance structure transformation.
2132-2137: Perfect integration of multi-model loader in main flow.The switch to
_load_multiple_model_schemascorrectly passes all required parameters and handles both single and multiple--input-modelscenarios transparently.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/datamodel_code_generator/__main__.py (3)
388-396: Clean up unused noqa directive.Line 388 has an unused
noqa: PLC0415directive. The PLC0415 check is not enabled in your linter configuration, so this directive can be safely removed.🔎 Proposed cleanup
- from pydantic import field_validator as _field_validator # noqa: PLC0415 + from pydantic import field_validator as _field_validatorBased on static analysis hints.
465-465: Clean up unused noqa directive.The
noqa: UP045directive is not needed as the UP045 check is not enabled.🔎 Proposed cleanup
- input_model: Optional[list[str]] = None # noqa: UP045 + input_model: Optional[list[str]] = NoneBased on static analysis hints.
1269-1400: LGTM with optional cleanup.The multi-model loading logic is well-implemented:
- Properly delegates to single-model path for backward compatibility
- Handles both module imports and file paths correctly
- Validates that objects are Pydantic v2 BaseModel classes
- Applies inheritance transformation and merges schemas appropriately
- Creates proper anyOf root references
Previous review concerns about error message formatting have been addressed.
Optional cleanup: Lines 1269, 1286, and 1287 have unused
noqadirectives that could be removed:🔎 Proposed cleanup
-def _load_multiple_model_schemas( # noqa: PLR0912, PLR0914, PLR0915 +def _load_multiple_model_schemas( input_models: list[str], input_file_type: InputFileType, ref_strategy: InputModelRefStrategy | None = None, output_model_type: DataModelType = DataModelType.PydanticBaseModel, ) -> dict[str, object]: """Load and merge schemas from multiple Python import paths with inheritance support. Args: input_models: List of import paths in 'module.path:ObjectName' format input_file_type: Current input file type setting for validation ref_strategy: Strategy for handling referenced types output_model_type: Target output model type for reuse-foreign strategy Returns: Merged schema dict with anyOf referencing all root models """ - import importlib.util # noqa: PLC0415 - import sys # noqa: PLC0415 + import importlib.util + import sysBased on static analysis hints.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/datamodel_code_generator/__main__.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/datamodel_code_generator/__main__.py (1)
src/datamodel_code_generator/util.py (1)
field_validator(175-191)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py
388-388: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
464-464: Unused noqa directive (non-enabled: UP007, UP045)
Remove unused noqa directive
(RUF100)
465-465: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
1269-1269: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
1286-1286: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1287-1287: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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: 3.12 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.14 on Ubuntu
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (5)
src/datamodel_code_generator/__main__.py (5)
456-462: LGTM!The validator correctly uses the cross-version
field_validatorutility and maintains backward compatibility by coercing string inputs to lists.
1193-1195: LGTM!The function correctly identifies BaseModel parent classes while excluding BaseModel itself. The logic is clean and straightforward.
1198-1266: LGTM!The inheritance transformation logic is sound and comprehensive:
- Correctly identifies parent BaseModel classes
- Recursively processes parent schemas with caching
- Properly merges $defs and creates allOf references
- Filters child-specific properties and required fields
- Preserves extra schema properties
Previous review concerns about dictionary iteration have been addressed.
1493-1494: LGTM!The inheritance transformation is correctly applied to single models as well, ensuring consistent behavior across both single and multi-model code paths.
2124-2129: LGTM!The integration correctly calls
_load_multiple_model_schemaswith all required parameters. Single-model cases are handled via internal delegation, preserving backward compatibility.
There was a problem hiding this comment.
Actionable comments posted: 4
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/input_model.pytests/test_input_model.py
🧰 Additional context used
🧠 Learnings (1)
📚 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/__main__.py
🧬 Code graph analysis (2)
tests/test_input_model.py (3)
tests/conftest.py (1)
assert_output(545-560)src/datamodel_code_generator/__main__.py (3)
main(973-1283)Exit(125-131)get(148-150)src/datamodel_code_generator/input_model.py (1)
load_model_schema(625-763)
src/datamodel_code_generator/input_model.py (1)
src/datamodel_code_generator/enums.py (3)
DataModelType(48-56)InputFileType(35-45)InputModelRefStrategy(206-217)
🪛 GitHub Actions: Lint
tests/test_input_model.py
[error] 1748-1748: ARG001 Unused function argument: tmp_path
src/datamodel_code_generator/input_model.py
[error] 459-459: N814 Camelcase DataModelType imported as constant DT
[error] 491-491: N814 Camelcase InputModelRefStrategy imported as constant IRS
[error] 645-645: N814 Camelcase DataModelType imported as constant DT
[error] 646-646: N817 CamelCase InputFileType imported as acronym IFT
[error] 647-647: N814 Camelcase InputModelRefStrategy imported as constant IRS
[error] 789-789: N817 CamelCase InputFileType imported as acronym IFT
[error] 790-790: N814 Camelcase InputModelRefStrategy imported as constant IRS
🪛 Ruff (0.14.10)
tests/test_input_model.py
1748-1748: Unused function argument: tmp_path
(ARG001)
src/datamodel_code_generator/__main__.py
388-388: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
464-464: Unused noqa directive (non-enabled: UP007, UP045)
Remove unused noqa directive
(RUF100)
465-465: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
1203-1203: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1204-1204: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/input_model.py
34-34: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
36-36: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
37-37: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
83-83: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
127-127: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
132-132: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
143-143: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
158-158: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
185-185: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
233-233: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
234-234: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
235-235: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
236-236: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
237-237: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
238-238: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
239-239: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
260-260: Unused noqa directive (non-enabled: PLW0603)
Remove unused noqa directive
(RUF100)
266-266: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
268-268: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
269-269: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
275-275: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
286-286: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
316-316: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
353-353: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
354-354: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
355-355: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
375-375: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
431-431: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
433-433: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
434-434: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
459-459: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
491-491: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
534-534: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
535-535: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
536-536: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
547-547: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
548-548: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
625-625: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
642-642: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
643-643: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
645-645: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
646-646: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
647-647: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
766-766: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
786-786: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
787-787: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
789-789: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
790-790: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
872-872: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
884-884: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (11)
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.14 on macOS
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.11 on macOS
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (10)
tests/test_input_model.py (3)
1154-1183: Well-structured test helper for multiple input models.The
run_multiple_input_models_and_asserthelper is well designed with:
- Clear parameter names and types
- Support for both positive and negative content assertions
- Proper use of
__tracebackhide__for cleaner test output
1185-1203: Error assertion helper follows consistent pattern.The
run_multiple_input_models_error_and_asserthelper mirrors the single-model version appropriately and handles the multiple input model case cleanly.
1206-1223: Good use of freeze_time and external expected files for deterministic tests.The inheritance tests properly use
freeze_timeto ensure consistent timestamps andassert_outputto compare against expected output files, making tests reproducible.src/datamodel_code_generator/__main__.py (3)
388-396: Correct coercion validator for backwards compatibility.The
coerce_input_model_to_listvalidator correctly handles the migration fromstrtolist[str]for theinput_modelconfig field, ensuring existing single-model configs continue to work.
456-462: Pydantic v1 validator mirrors v2 implementation correctly.The v1 branch implementation is consistent with the v2 version, maintaining backwards compatibility across Pydantic versions.
1202-1214: Clean integration with new input_model module.The loading logic properly:
- Imports the new
load_model_schemafunction andErrorclass- Passes all required parameters including the new list-based
input_model- Wraps
InputModelErrorinto the genericErrorfor consistent error handlingsrc/datamodel_code_generator/input_model.py (4)
564-622: Inheritance transformation logic is well-designed.The
_transform_single_model_to_inheritancefunction correctly:
- Recursively processes parent classes first using
processed_parentscache- Extracts child-only properties and required fields
- Builds proper
allOfstructure with parent$ref- Merges
$defsfrom parent schemasThe caching mechanism prevents redundant schema generation for shared ancestors in diamond inheritance patterns.
625-763: Core multi-model loading logic is sound.The
load_model_schemafunction handles:
- Single model delegation to
_load_single_model_schema- Module caching via
loaded_modulesdict- Both file path and module import formats
- Proper Pydantic v2 runtime validation
- Merged
$defswithanyOfroot referencesOne note: when multiple models with the same
__name__from different modules are provided, later ones will overwrite earlier ones inmerged_defs. This edge case is documented in past review comments as an optional future improvement.
15-17: Simple and clear Error class.The
Errorexception class provides a clean abstraction for input model loading errors, keeping the module's error handling separate from the main module's error types.
642-651: Fix import aliases in load_model_schema to resolve pipeline failures.Multiple N814/N817 violations here need to be addressed.
🔎 Proposed fix
- from datamodel_code_generator import DataModelType as DT # noqa: PLC0415 - from datamodel_code_generator import InputFileType as IFT # noqa: PLC0415 - from datamodel_code_generator.arguments import InputModelRefStrategy as IRS # noqa: PLC0415 + from datamodel_code_generator import DataModelType # noqa: PLC0415 + from datamodel_code_generator import InputFileType # noqa: PLC0415 + from datamodel_code_generator.arguments import InputModelRefStrategy # noqa: PLC0415 if output_model_type is None: - output_model_type = DT.PydanticBaseModel + output_model_type = DataModelType.PydanticBaseModelThen update all usages of
IFTandIRSthroughout the function.⛔ Skipped due to learnings
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.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/input_model.pytests/test_input_model.py
🧰 Additional context used
🧠 Learnings (1)
📚 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/input_model.py
🧬 Code graph analysis (2)
tests/test_input_model.py (6)
tests/conftest.py (2)
assert_output(545-560)freeze_time(352-355)src/datamodel_code_generator/parser/base.py (1)
parent(612-614)src/datamodel_code_generator/__main__.py (3)
main(973-1283)Exit(125-131)get(148-150)src/datamodel_code_generator/model/base.py (2)
name(827-829)path(908-910)src/datamodel_code_generator/enums.py (1)
InputFileType(35-45)src/datamodel_code_generator/input_model.py (1)
load_model_schema(625-765)
src/datamodel_code_generator/input_model.py (1)
src/datamodel_code_generator/enums.py (5)
DataModelType(48-56)InputFileType(35-45)InputModelRefStrategy(206-217)UnionMode(199-203)StrictTypes(220-227)
🪛 GitHub Actions: Lint
src/datamodel_code_generator/input_model.py
[error] 645-648: PL C0415 import should be at the top-level of a file.
🪛 Ruff (0.14.10)
src/datamodel_code_generator/input_model.py
34-34: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
36-36: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
37-37: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
83-83: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
127-127: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
132-132: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
143-143: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
158-158: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
185-185: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
233-233: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
234-234: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
235-235: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
236-236: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
237-237: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
238-238: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
239-239: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
260-260: Unused noqa directive (non-enabled: PLW0603)
Remove unused noqa directive
(RUF100)
266-266: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
268-268: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
269-269: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
275-275: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
286-286: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
316-316: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
353-353: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
354-354: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
355-355: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
375-375: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
431-431: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
433-433: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
434-434: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
459-459: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
491-491: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
534-534: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
535-535: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
536-536: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
547-547: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
548-548: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
625-625: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
642-642: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
643-643: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
649-649: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
768-768: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
788-788: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
789-789: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
791-791: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
792-792: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
874-874: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
886-886: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (15)
- GitHub Check: 3.14 on macOS
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.11 on macOS
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: py312-black24 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on macOS
- GitHub Check: 3.13 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/test_input_model.py (2)
1389-1416: Consider documenting the mock behavior.The mock for
hasattruses a counter-based approach that returnsFalsefor the first two calls tomodel_json_schemacheck. While this works, adding a brief comment explaining whycall_count <= 2is the threshold would improve maintainability.🔎 Suggested documentation
def mock_hasattr(obj: object, name: str) -> bool: nonlocal call_count if name == "model_json_schema": call_count += 1 + # Return False for first two calls to trigger Pydantic v1 error path + # (covers both model classes being checked) if call_count <= 2: return False return original_hasattr(obj, name)
1671-1696: Verify sys.path state restoration.The test modifies
sys.pathand checks counts, but there's no cleanup if the test fails mid-execution. Consider using a try-finally or fixture to ensuresys.pathis restored.🔎 Suggested improvement
@SKIP_PYDANTIC_V1 def test_input_model_cwd_already_in_path( tmp_path: Path, ) -> None: """Test that cwd is not duplicated in sys.path when already present.""" import sys from pathlib import Path as _Path cwd = str(_Path.cwd()) initial_count = sys.path.count(cwd) - if cwd not in sys.path: - sys.path.insert(0, cwd) - - output_path = tmp_path / "output.py" - run_multiple_input_models_and_assert( - input_models=[ - "tests.data.python.input_model.inheritance_models:ChildA", - "tests.data.python.input_model.inheritance_models:ChildB", - ], - output_path=output_path, - expected_output_contains=[ - "class ChildA(Parent):", - "class ChildB(Parent):", - ], - ) - final_count = sys.path.count(cwd) - assert final_count <= initial_count + 1 + added_cwd = cwd not in sys.path + try: + if added_cwd: + sys.path.insert(0, cwd) + + output_path = tmp_path / "output.py" + run_multiple_input_models_and_assert( + input_models=[ + "tests.data.python.input_model.inheritance_models:ChildA", + "tests.data.python.input_model.inheritance_models:ChildB", + ], + output_path=output_path, + expected_output_contains=[ + "class ChildA(Parent):", + "class ChildB(Parent):", + ], + ) + final_count = sys.path.count(cwd) + assert final_count <= initial_count + 1 + finally: + if added_cwd and cwd in sys.path: + sys.path.remove(cwd)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/input_model.pytests/test_input_model.py
🧰 Additional context used
🧠 Learnings (2)
📚 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/input_model.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.
Applied to files:
src/datamodel_code_generator/input_model.py
🧬 Code graph analysis (2)
tests/test_input_model.py (5)
src/datamodel_code_generator/parser/base.py (1)
parent(612-614)src/datamodel_code_generator/__main__.py (3)
main(973-1283)Exit(125-131)get(148-150)src/datamodel_code_generator/model/base.py (2)
name(827-829)path(908-910)src/datamodel_code_generator/__init__.py (1)
chdir(246-256)src/datamodel_code_generator/input_model.py (1)
load_model_schema(625-765)
src/datamodel_code_generator/input_model.py (1)
src/datamodel_code_generator/enums.py (4)
DataModelType(48-56)InputFileType(35-45)InputModelRefStrategy(206-217)UnionMode(199-203)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/input_model.py
34-34: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
36-36: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
37-37: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
83-83: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
127-127: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
132-132: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
143-143: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
158-158: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
185-185: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
233-233: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
234-234: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
235-235: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
236-236: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
237-237: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
238-238: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
239-239: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
260-260: Unused noqa directive (non-enabled: PLW0603)
Remove unused noqa directive
(RUF100)
266-266: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
268-268: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
269-269: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
275-275: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
286-286: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
316-316: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
353-353: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
354-354: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
355-355: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
375-375: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
431-431: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
433-433: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
434-434: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
459-459: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
491-491: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
534-534: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
535-535: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
536-536: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
547-547: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
548-548: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
625-625: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
642-642: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
643-643: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
645-645: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
649-649: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
768-768: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
788-788: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
789-789: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
791-791: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
792-792: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
874-874: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
886-886: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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: 3.11 on Windows
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.14 on macOS
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (18)
tests/test_input_model.py (5)
20-21: LGTM!The constants
EXPECTED_INPUT_MODEL_PATHandTIMESTAMPare well-defined for use in the new inheritance tests. The timestamp format is appropriate forfreeze_timeusage.
1159-1188: LGTM!The
run_multiple_input_models_and_asserthelper is well-structured, following the same pattern as the single-model helper. It properly builds the args list with multiple--input-modelentries and includes comprehensive assertions.
1190-1208: LGTM!The
run_multiple_input_models_error_and_asserthelper is consistent with the single-model error helper and properly handles multiple input models for error case testing.
1211-1227: LGTM!The test properly uses
freeze_timefor deterministic output and validates against expected output files. The test covers the inheritance chain generation for a single input model.
1752-1765: LGTM!Good unit test for the
load_model_schemafunction directly, verifying the defaultoutput_model_typebehavior.src/datamodel_code_generator/input_model.py (13)
15-31: LGTM!The
Errorexception class and type family constants are well-defined. The constants provide clear semantics for type categorization.
34-77: LGTM!The
_serialize_python_type_fullfunction comprehensively handles Python type serialization including Union types, Callable types, and generic types with proper module path preservation.
125-153: LGTM!The custom
InputModelJsonSchemaclass properly handles unserializable types by marking them withx-python-unserializable. The lazy import pattern avoids Pydantic v1 compatibility issues. Based on learnings, the# noqa: PLR6301directives should be kept due to Ruff preview mode.
200-228: LGTM!The
_add_python_type_for_unserializablefunction properly handles recursive schema processing with thevisited_defsset to prevent infinite loops. The function correctly processes both root properties and nested definitions.
258-263: LGTM!The lazy initialization pattern with the global variable is appropriate here to avoid import overhead at module load time while caching the result for subsequent calls.
327-348: LGTM!The
_collect_nested_modelsfunction properly handles recursive model collection with cycle detection via thevisitedset, supporting both Pydantic models and other types using type hints.
431-454: LGTM!The
_get_type_familyfunction correctly identifies different type families including the special case for Pydantic dataclasses (checking__pydantic_fields__beforeis_dataclass).
484-524: LGTM!The
_filter_defs_by_strategyfunction correctly implements the three ref strategies, addingx-python-importmetadata for types that should be reused and keeping schema definitions for types that need regeneration.
527-556: LGTM!The
_try_rebuild_modelfunction properly handles Pydantic model rebuilding with special namespace handling for config classes that reference forward-declared types.
564-622: LGTM!The
_transform_single_model_to_inheritancefunction correctly transforms Pydantic model schemas to useallOffor inheritance. The recursive processing of parent chains and theprocessed_parentscache prevent redundant schema generation.
625-765: LGTM!The
load_model_schemafunction is well-structured with comprehensive error handling. The module caching vialoaded_modulesdict is efficient, and the schema merging logic correctly produces ananyOfstructure for multiple root models while sharingprocessed_parentsacross models for efficient inheritance processing.
768-904: LGTM!The
_load_single_model_schemafunction provides comprehensive handling for different input types (dict, Pydantic BaseModel, dataclass, TypedDict) with appropriate validation and schema generation for each type.
36-37: Retain defensivenoqadirectives per project conventions.Based on learnings, the
# noqa: PLC0415directives on lazy imports should be kept even when Ruff reports them as unused. This is a defensive measure for potential future Ruff configuration changes. The static analysis hints about "unused noqa directive" can be safely ignored.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/datamodel_code_generator/__main__.py (1)
388-388: Consider removing unusednoqadirectives.The static analysis tool indicates several
noqadirectives are suppressing rules that aren't currently enabled (PLC0415, UP045, UP007). Removing these would reduce noise without affecting functionality.🔎 Suggested cleanup
- from pydantic import field_validator as _field_validator # noqa: PLC0415 + from pydantic import field_validator as _field_validator - input: Optional[Union[Path, str]] = None # noqa: UP007, UP045 - input_model: Optional[list[str]] = None # noqa: UP045 + input: Optional[Union[Path, str]] = None + input_model: Optional[list[str]] = None - from datamodel_code_generator.input_model import Error as InputModelError # noqa: PLC0415 - from datamodel_code_generator.input_model import load_model_schema # noqa: PLC0415 + from datamodel_code_generator.input_model import Error as InputModelError + from datamodel_code_generator.input_model import load_model_schemaAlso applies to: 464-465, 1203-1204
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/__main__.pytests/test_input_model.py
🧰 Additional context used
🧬 Code graph analysis (2)
tests/test_input_model.py (3)
tests/conftest.py (1)
assert_output(545-560)src/datamodel_code_generator/__main__.py (3)
main(973-1283)Exit(125-131)get(148-150)src/datamodel_code_generator/input_model.py (1)
load_model_schema(625-765)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/util.py (1)
field_validator(175-191)src/datamodel_code_generator/input_model.py (2)
Error(15-16)load_model_schema(625-765)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py
388-388: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
464-464: Unused noqa directive (non-enabled: UP007, UP045)
Remove unused noqa directive
(RUF100)
465-465: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
1203-1203: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1204-1204: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (11)
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (9)
tests/test_input_model.py (5)
6-6: LGTM! Well-organized imports and constants.The new imports and constants support the inheritance testing infrastructure effectively. Using
freeze_timeandassert_outputenables deterministic comparisons against expected output files.Also applies to: 15-15, 20-21
57-83: LGTM! Efficient helper enhancement.The addition of
expected_output_not_containscomplements the existing positive assertions well. Reading the file content once and checking both positive and negative expectations is efficient.
1160-1210: LGTM! Well-structured test helpers.The new helpers for multiple input models follow the established patterns and handle both success and error cases consistently. The code is clear and maintainable.
1213-1550: LGTM! Comprehensive inheritance test coverage.The inheritance tests thoroughly cover:
- Single and multiple input models with various inheritance patterns
- Different output model types (TypedDict, Pydantic BaseModel, dataclass)
- Error conditions with clear assertions
- Edge cases like same module imports and file path formats
The use of
freeze_timeandassert_outputensures deterministic, maintainable comparisons.
1553-1782: LGTM! Thorough edge case and integration testing.The remaining tests provide excellent coverage of:
- Integration with
--input-model-ref-strategy- Various error scenarios with clear error message validation
- Edge cases like empty inheritance chains and path handling
- Config file string-to-list coercion
- Default parameter behavior
All tests follow established patterns and include proper assertions.
src/datamodel_code_generator/__main__.py (4)
388-396: Excellent backwards-compatible validator implementation!The
coerce_input_model_to_listvalidator properly normalizes theinput_modelfield to always be a list, enabling the new multi-model feature while preserving backwards compatibility with single-string inputs. The use ofmode="before"is correct for type coercion.
456-462: LGTM - Pydantic v1 compatibility maintained.The validator is correctly duplicated for Pydantic v1 users, ensuring consistent behavior across both Pydantic versions.
465-465: Type annotation correctly reflects the normalized format.The type change from
Optional[str]toOptional[list[str]]properly represents the post-validation state after thecoerce_input_model_to_listvalidator runs.
1203-1214: Clean integration with the new multi-model loader!The refactored loading logic properly:
- Delegates to the new public
load_model_schemafunction- Catches
InputModelErrorand converts to the genericErrorfor consistent error handling- Maintains the existing JSON serialization flow
The guard at line 1202 ensures
config.input_modelis non-empty before this code executes, so type safety is maintained.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
tests/data/expected/main/input_model/dataclass_with_python_types.py (1)
13-14:unique_items=Trueis redundant but harmless on set/frozenset fields.The
setandfrozensettypes already guarantee uniqueness by definition, so theunique_items=Trueparameter inField()is redundant. However, since this is a test expected output file, this might be intentionally preserved from the input schema to maintain metadata fidelity for round-trip schema generation.tests/data/expected/main/input_model/config_class.py (1)
121-121: Inconsistent union syntax.Line 121 uses
Union[defaultdict[str, dict[str, Any]], None]while the rest of the file consistently uses the modern|operator for unions (enabled by line 5's future import). For consistency with the rest of the file, consider usingdefaultdict[str, dict[str, Any]] | None.🔎 Proposed fix for consistency
- extra_template_data: NotRequired[Union[defaultdict[str, dict[str, Any]], None]] + extra_template_data: NotRequired[defaultdict[str, dict[str, Any]] | None]tests/test_input_model.py (1)
1512-1534: Consider cleanup of sys.path modification.The test adds
cwdtosys.path(lines 1521-1522) but doesn't restore the original state after the test. While the impact is minimal since it only adds cwd once, consider using a try/finally block for proper cleanup to avoid potential test isolation issues.🔎 Proposed fix
@SKIP_PYDANTIC_V1 def test_input_model_cwd_already_in_path( tmp_path: Path, ) -> None: """Test that cwd is not duplicated in sys.path when already present.""" import sys from pathlib import Path as _Path cwd = str(_Path.cwd()) initial_count = sys.path.count(cwd) + added_cwd = False if cwd not in sys.path: # pragma: no cover sys.path.insert(0, cwd) + added_cwd = True - run_multiple_input_models_and_assert( - input_models=[ - "tests.data.python.input_model.inheritance_models:ChildA", - "tests.data.python.input_model.inheritance_models:ChildB", - ], - output_path=tmp_path / "output.py", - expected_file=EXPECTED_INPUT_MODEL_PATH / "multiple_with_pydantic_output.py", - extra_args=["--output-model-type", "pydantic.BaseModel"], - ) - final_count = sys.path.count(cwd) - assert final_count <= initial_count + 1 + try: + run_multiple_input_models_and_assert( + input_models=[ + "tests.data.python.input_model.inheritance_models:ChildA", + "tests.data.python.input_model.inheritance_models:ChildB", + ], + output_path=tmp_path / "output.py", + expected_file=EXPECTED_INPUT_MODEL_PATH / "multiple_with_pydantic_output.py", + extra_args=["--output-model-type", "pydantic.BaseModel"], + ) + final_count = sys.path.count(cwd) + assert final_count <= initial_count + 1 + finally: + if added_cwd: # pragma: no cover + sys.path.remove(cwd)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (41)
tests/data/expected/main/input_model/config_class.pytests/data/expected/main/input_model/custom_class.pytests/data/expected/main/input_model/custom_generic_type_import.pytests/data/expected/main/input_model/dataclass_with_python_types.pytests/data/expected/main/input_model/default_put_dict_import.pytests/data/expected/main/input_model/dict_openapi.pytests/data/expected/main/input_model/dict_with_jsonschema.pytests/data/expected/main/input_model/empty_child_no_properties.pytests/data/expected/main/input_model/model_with_callable_types.pytests/data/expected/main/input_model/model_with_python_types.pytests/data/expected/main/input_model/model_with_python_types_dataclass.pytests/data/expected/main/input_model/model_with_python_types_typeddict.pytests/data/expected/main/input_model/multiple_same_module.pytests/data/expected/main/input_model/multiple_with_dataclass_output.pytests/data/expected/main/input_model/multiple_with_pydantic_output.pytests/data/expected/main/input_model/nested_model_with_callable.pytests/data/expected/main/input_model/optional_only_child_no_required.pytests/data/expected/main/input_model/path_format.pytests/data/expected/main/input_model/path_format_filename_only.pytests/data/expected/main/input_model/pydantic_basemodel.pytests/data/expected/main/input_model/pydantic_dataclass.pytests/data/expected/main/input_model/pydantic_to_typeddict.pytests/data/expected/main/input_model/pydantic_with_jsonschema.pytests/data/expected/main/input_model/recursive_model_types.pytests/data/expected/main/input_model/ref_strategy_dataclass_reuse_foreign.pytests/data/expected/main/input_model/ref_strategy_no_nested_types.pytests/data/expected/main/input_model/ref_strategy_regenerate_all.pytests/data/expected/main/input_model/ref_strategy_reuse_all.pytests/data/expected/main/input_model/ref_strategy_reuse_foreign.pytests/data/expected/main/input_model/ref_strategy_reuse_foreign_different_family.pytests/data/expected/main/input_model/ref_strategy_reuse_foreign_mixed_types.pytests/data/expected/main/input_model/ref_strategy_reuse_foreign_msgspec_output.pytests/data/expected/main/input_model/ref_strategy_reuse_foreign_pydantic_output.pytests/data/expected/main/input_model/ref_strategy_reuse_foreign_same_family_dataclass.pytests/data/expected/main/input_model/ref_strategy_reuse_foreign_same_family_typeddict.pytests/data/expected/main/input_model/ref_strategy_typeddict_reuse_all.pytests/data/expected/main/input_model/ref_strategy_typeddict_reuse_foreign.pytests/data/expected/main/input_model/std_dataclass.pytests/data/expected/main/input_model/typeddict.pytests/data/expected/main/input_model/union_callable.pytests/test_input_model.py
✅ Files skipped from review due to trivial changes (2)
- tests/data/expected/main/input_model/pydantic_dataclass.py
- tests/data/expected/main/input_model/model_with_python_types_dataclass.py
🧰 Additional context used
🧬 Code graph analysis (25)
tests/data/expected/main/input_model/pydantic_basemodel.py (4)
tests/data/expected/main/input_model/path_format.py (1)
User(10-12)tests/data/expected/main/input_model/path_format_filename_only.py (1)
User(10-12)tests/data/expected/main/input_model/pydantic_to_typeddict.py (1)
User(10-12)tests/data/expected/main/input_model/pydantic_with_jsonschema.py (1)
User(10-12)
tests/data/expected/main/input_model/model_with_python_types_typeddict.py (4)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)tests/data/expected/main/input_model/model_with_python_types.py (2)
Tag(12-13)ModelWithPythonTypes(16-26)tests/data/expected/main/input_model/model_with_python_types_dataclass.py (2)
Tag(12-13)ModelWithPythonTypes(17-27)tests/data/expected/main/input_model/ref_strategy_dataclass_reuse_foreign.py (1)
Tag(13-15)
tests/data/expected/main/input_model/dataclass_with_python_types.py (1)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
Field(6-7)
tests/data/expected/main/input_model/optional_only_child_no_required.py (2)
tests/data/expected/main/input_model/empty_child_no_properties.py (2)
GrandParent(10-11)Parent(14-15)tests/data/expected/main/input_model/multiple_with_pydantic_output.py (2)
GrandParent(10-11)Parent(14-15)
tests/data/expected/main/input_model/custom_generic_type_import.py (2)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
Field(6-7)tests/data/python/input_model/pydantic_models.py (1)
CustomGenericDict(16-19)
tests/data/expected/main/input_model/multiple_same_module.py (1)
src/datamodel_code_generator/model/type_alias.py (1)
TypeAlias(37-42)
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_msgspec_output.py (4)
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_different_family.py (2)
NestedPydantic(12-14)ModelWithPydantic(17-19)tests/data/expected/main/input_model/ref_strategy_reuse_foreign_mixed_types.py (1)
NestedPydantic(17-19)src/datamodel_code_generator/model/base.py (1)
name(827-829)tests/data/expected/main/input_model/ref_strategy_reuse_foreign_pydantic_output.py (1)
ModelWithPydantic(11-13)
tests/data/expected/main/input_model/multiple_with_dataclass_output.py (1)
src/datamodel_code_generator/model/type_alias.py (1)
TypeAlias(37-42)
tests/data/expected/main/input_model/custom_class.py (2)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
Field(6-7)tests/data/python/input_model/pydantic_models.py (1)
CustomClass(82-85)
tests/data/expected/main/input_model/std_dataclass.py (3)
tests/data/expected/main/input_model/dict_openapi.py (1)
User(10-12)tests/data/expected/main/input_model/path_format.py (1)
User(10-12)tests/data/expected/main/input_model/path_format_filename_only.py (1)
User(10-12)
tests/data/expected/main/input_model/model_with_python_types.py (3)
tests/data/expected/main/input_model/model_with_python_types_dataclass.py (2)
Tag(12-13)ModelWithPythonTypes(17-27)tests/data/expected/main/input_model/model_with_python_types_typeddict.py (2)
Tag(11-12)ModelWithPythonTypes(15-25)tests/data/expected/main/input_model/ref_strategy_dataclass_reuse_foreign.py (1)
Tag(13-15)
tests/data/expected/main/input_model/ref_strategy_dataclass_reuse_foreign.py (2)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)src/datamodel_code_generator/model/base.py (1)
name(827-829)
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_same_family_dataclass.py (1)
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_mixed_types.py (1)
NestedDataclass(12-14)
tests/data/expected/main/input_model/default_put_dict_import.py (1)
src/datamodel_code_generator/parser/__init__.py (1)
DefaultPutDict(28-47)
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_same_family_typeddict.py (2)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)tests/data/python/input_model/mixed_nested.py (1)
NestedTypedDict(19-23)
tests/data/expected/main/input_model/empty_child_no_properties.py (2)
tests/data/expected/main/input_model/multiple_with_pydantic_output.py (2)
GrandParent(10-11)Parent(14-15)tests/data/expected/main/input_model/optional_only_child_no_required.py (2)
GrandParent(10-11)Parent(14-15)
tests/data/expected/main/input_model/ref_strategy_regenerate_all.py (4)
src/datamodel_code_generator/model/type_alias.py (1)
TypeAlias(37-42)src/datamodel_code_generator/model/typed_dict.py (2)
TypedDict(49-114)key(131-135)tests/data/expected/main/input_model/ref_strategy_reuse_foreign.py (3)
Address(13-15)Metadata(18-20)User(23-27)tests/data/expected/main/input_model/ref_strategy_reuse_all.py (1)
User(13-17)
tests/data/expected/main/input_model/pydantic_to_typeddict.py (1)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)
tests/data/expected/main/input_model/path_format.py (10)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
Field(6-7)tests/data/expected/main/input_model/dict_openapi.py (1)
User(10-12)tests/data/expected/main/input_model/path_format_filename_only.py (1)
User(10-12)tests/data/expected/main/input_model/pydantic_basemodel.py (1)
User(10-12)tests/data/expected/main/input_model/pydantic_dataclass.py (1)
User(10-12)tests/data/expected/main/input_model/pydantic_to_typeddict.py (1)
User(10-12)tests/data/expected/main/input_model/pydantic_with_jsonschema.py (1)
User(10-12)tests/data/expected/main/input_model/ref_strategy_no_nested_types.py (1)
User(11-13)tests/data/expected/main/input_model/std_dataclass.py (1)
User(10-12)tests/data/expected/main/input_model/typeddict.py (1)
User(10-12)
tests/data/expected/main/input_model/ref_strategy_typeddict_reuse_foreign.py (2)
tests/data/python/input_model/typeddict_nested.py (1)
Role(11-15)tests/data/expected/main/input_model/ref_strategy_typeddict_reuse_all.py (1)
Member(13-16)
tests/data/expected/main/input_model/ref_strategy_reuse_foreign.py (2)
src/datamodel_code_generator/model/typed_dict.py (2)
TypedDict(49-114)key(131-135)tests/data/expected/main/input_model/ref_strategy_reuse_all.py (1)
User(13-17)
tests/data/expected/main/input_model/typeddict.py (2)
tests/data/expected/main/input_model/path_format.py (1)
User(10-12)tests/data/expected/main/input_model/path_format_filename_only.py (1)
User(10-12)
tests/data/expected/main/input_model/model_with_callable_types.py (1)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
Field(6-7)
tests/data/expected/main/input_model/path_format_filename_only.py (2)
tests/data/expected/main/input_model/dict_openapi.py (1)
User(10-12)tests/data/expected/main/input_model/path_format.py (1)
User(10-12)
tests/data/expected/main/input_model/multiple_with_pydantic_output.py (3)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
Field(6-7)tests/data/expected/main/input_model/empty_child_no_properties.py (2)
GrandParent(10-11)Parent(14-15)tests/data/expected/main/input_model/optional_only_child_no_required.py (2)
GrandParent(10-11)Parent(14-15)
🪛 Ruff (0.14.10)
tests/data/expected/main/input_model/model_with_callable_types.py
11-11: Redefinition of unused BaseModel from line 10
(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). (12)
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.13 on Windows
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (56)
tests/data/expected/main/input_model/ref_strategy_no_nested_types.py (1)
1-13: LGTM! Test expected output is correct.The generated dataclass is syntactically valid and appropriate for testing the "ref_strategy_no_nested_types" scenario. The fixed timestamp ensures test reproducibility, and the simple two-field dataclass correctly represents the expected output format.
tests/data/expected/main/input_model/dataclass_with_python_types.py (3)
1-4: LGTM!The generated file header follows the expected format for datamodel-codegen output.
5-9: LGTM!The imports are correct and follow Python best practices:
- Future annotations enable modern type syntax
- Abstract types from
collections.abcare preferred for immutable/read-only interfaces
15-16: LGTM!Using
MappingandSequencefromcollections.abcis excellent practice for fields that should be immutable or read-only interfaces.tests/data/expected/main/input_model/custom_generic_type_import.py (3)
1-8: LGTM: File header and imports are correct.The generated file header and imports are properly structured. The import of
CustomGenericDictfrom the test data module correctly references the custom generic type defined in the codebase.
11-12: LGTM: Model and first field definition are correct.The model class and
custom_dictfield properly demonstrate the use of a custom generic type with type parameters.
13-15: Verify the field semantics match the input schema.The field definition is syntactically correct. The type
CustomGenericDict[str, str] | NonewithField(...)means the field is required (must be provided) but can acceptNoneas a value. The nameoptional_custom_dictmight suggest the field can be omitted, but Pydantic will require it to be explicitly passed.Please confirm this behavior matches the input schema's intent (nullable but required field).
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_msgspec_output.py (3)
1-5: LGTM!The generated file header and future annotations import are correct.
13-15: LGTM!The
NestedPydanticclass correctly uses msgspecStructwith properly annotated fields. The field titles are appropriately specified usingMeta.
18-20: LGTM!The
ModelWithPydanticclass correctly demonstrates the ref_strategy reuse_foreign behavior by combining a locally defined nested model with an imported foreign type (Category).tests/data/expected/main/input_model/config_class.py (4)
1-11: LGTM! Clean imports.The imports are appropriate for this type definition file. The
from __future__ import annotationsimport enables modern union syntax (|) for the rest of the file.
13-107: LGTM! Comprehensive type aliases for configuration.The TypeAlias definitions provide strong typing for all configuration options. The literal values are appropriate and well-structured for each option.
40-50: LGTM! Correct dataclass parameter mapping.The
DataclassArgumentsTypedDict correctly models all standard dataclass decorator parameters with appropriate optional boolean types.
109-232: Comprehensive configuration schema with extensive options.The
GenerateConfigTypedDict provides a thorough type definition for all configuration options. The structure is well-organized and uses appropriate types for each field.tests/data/expected/main/input_model/ref_strategy_dataclass_reuse_foreign.py (2)
21-21: TheNotRequired[Tag | None]pattern is correct. When converting from the input dataclasstag: Optional[Tag] = None, the TypedDict representationNotRequired[Tag | None]accurately preserves both the optionality (field can be absent) and nullability (value can be None) semantics. UsingNotRequired[Tag]instead would incorrectly excludeNoneas a valid value, contradicting the input model's explicitOptional[Tag]type.
9-9: The Priority import path is correct and accessible.The
Priorityenum is properly defined intests/data/python/input_model/dataclass_nested.pyand the import statement on line 9 correctly references it. No issues identified.tests/data/expected/main/input_model/ref_strategy_typeddict_reuse_foreign.py (2)
18-22: Member definition correctly matches reuse-all strategy.The
Memberdataclass structure is identical to the one inref_strategy_typeddict_reuse_all.py, which is correct. The only difference is that this file definesProfilelocally while the reuse-all version imports it, demonstrating the two different reuse strategies as intended.
12-15: Profile definition correctly matches source module.The locally-defined
Profileclass in the expected file has the same fields as the sourceProfileintests.data.python.input_model.typeddict_nested.py:bio: strandwebsite: str.tests/data/expected/main/input_model/ref_strategy_typeddict_reuse_all.py (1)
1-16: Test expected output looks correct for reuse-all strategy.The file correctly demonstrates the "reuse all" behavior by importing both
ProfileandRolefromtests.data.python.input_model.typeddict_nested. TheMemberdataclass properly uses these imported types.tests/data/expected/main/input_model/model_with_python_types_typeddict.py (3)
5-8: LGTM: Imports are correct.The imports are appropriate for TypedDict-based models with modern Python typing features.
11-12: LGTM: Tag definition is correct.The Tag TypedDict is properly defined and consistent with other model variants in the test suite.
23-25: No changes needed. The TypedDict semantics are correct.The fields
optional_set,nullable_frozenset, andoptional_mappingare required fields in the source Pydantic model (none have default values). In Pydantic,Optional[T]orT | Nonemeans the value can beNone, not that the field can be missing. The TypedDict representationfield: T | Nonecorrectly captures this: the key must be present, but the value can beNone. UsingNotRequiredwould contradict the source model's semantics and make the code incorrect.Likely an incorrect or invalid review comment.
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_same_family_typeddict.py (1)
1-14: LGTM! Test fixture correctly demonstrates TypedDict with foreign type references.This generated test output correctly demonstrates the reuse of foreign types (
CategoryandNestedTypedDict) from another module within a TypedDict definition, aligning with the PR's multi-model input support objectives.tests/data/expected/main/input_model/dict_openapi.py (1)
1-12: LGTM! Clean test fixture for basic Pydantic model generation.This expected output correctly represents a simple Pydantic BaseModel with scalar fields, suitable for validating dict/OpenAPI input model scenarios.
tests/data/expected/main/input_model/dict_with_jsonschema.py (1)
1-12: LGTM! Test fixture validates JSON Schema input model generation.This expected output is syntactically correct and appropriately demonstrates model generation from JSON Schema input.
tests/data/expected/main/input_model/pydantic_to_typeddict.py (1)
1-12: LGTM! Test fixture demonstrates Pydantic-to-TypedDict transformation.This expected output correctly validates the code generator's ability to transform Pydantic input models to TypedDict output format.
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_same_family_dataclass.py (1)
1-15: LGTM! Test fixture validates dataclass output with foreign type reuse.This expected output correctly demonstrates dataclass generation with foreign type references from
mixed_nested, complementing the TypedDict variant and validating ref-strategy reuse across different output formats.tests/data/expected/main/input_model/ref_strategy_reuse_all.py (1)
1-17: LGTM! Test fixture demonstrates optional fields and comprehensive ref-reuse.This expected output correctly validates TypedDict generation with
NotRequiredoptional fields and demonstrates comprehensive reference reuse with imported types fromnested_models.tests/data/expected/main/input_model/path_format_filename_only.py (1)
1-12: LGTM! Test fixture validates Field metadata generation.This expected output correctly demonstrates Pydantic model generation with Field metadata, including title attributes for each field.
tests/data/expected/main/input_model/empty_child_no_properties.py (1)
1-19: LGTM! Test fixture demonstrates multi-level inheritance with empty child.This expected output correctly validates inheritance preservation across three levels (GrandParent → Parent → EmptyChild), with the empty child class containing no additional properties—a key scenario for testing the PR's inheritance preservation functionality.
tests/data/expected/main/input_model/path_format.py (1)
1-12: LGTM!This test fixture correctly defines a Pydantic
Usermodel with the expectedField(...)syntax for required fields with title metadata. The structure is consistent with other similar expected output files in the test suite.tests/data/expected/main/input_model/union_callable.py (1)
1-14: LGTM!The test fixture correctly demonstrates union types with
Callableand uses the moderncollections.abc.Callableimport. The field definitions with union types (Callable[[str], str] | int) are valid Python 3.10+ syntax.tests/data/expected/main/input_model/pydantic_basemodel.py (1)
1-12: LGTM!This test fixture is consistent with the expected Pydantic
BaseModeloutput pattern and matches similar expected output files in the test suite (e.g.,path_format.py,path_format_filename_only.py).tests/data/expected/main/input_model/nested_model_with_callable.py (1)
12-18: LGTM!The nested model structure is correct. The
nested: NestedCallableModelfield appropriately omitsField(...)since it doesn't require additional metadata, while fields with title metadata properly use theField(...)pattern.tests/data/expected/main/input_model/ref_strategy_regenerate_all.py (1)
1-29: LGTM!The test fixture correctly demonstrates:
TypedDictwith optional fields usingNotRequiredTypeAliasfor literal union types- Proper import organization (stdlib
typingthentyping_extensions)The structure is consistent with related ref_strategy expected output files.
tests/data/expected/main/input_model/model_with_python_types.py (1)
12-26: LGTM!The test fixture comprehensively covers various Python collection types (
set,frozenset,Mapping,Sequence, nested generics) and demonstrates proper handling of:
- Required fields with and without
Field()metadata- Nullable/optional union types (
... | None)- Nested model references (
tag_obj: Tag)The structure aligns with related TypedDict and dataclass variants in the test suite.
tests/data/expected/main/input_model/pydantic_with_jsonschema.py (1)
1-12: LGTM!This test fixture correctly represents the expected Pydantic output when processing input models with JSON Schema metadata. The structure matches other similar expected output files in the suite.
tests/data/expected/main/input_model/recursive_model_types.py (1)
10-19: LGTM - recursive model pattern is correctly structured for Pydantic v1.This test fixture demonstrates proper handling of recursive/self-referential models using Pydantic v1 patterns. The
__root__wrapper andupdate_forward_refs()call are intentional for v1 compatibility, as evidenced by the test not being marked with the v2-only@SKIP_PYDANTIC_V1decorator.tests/data/expected/main/input_model/ref_strategy_reuse_foreign_pydantic_output.py (1)
1-13: LGTM! Clean Pydantic model with foreign type reuse.The generated output correctly demonstrates Pydantic model generation with imported types from external modules. The structure is clean and follows standard Pydantic conventions.
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_different_family.py (1)
1-19: LGTM! Proper TypedDict generation with foreign type reuse.The output correctly demonstrates conversion to TypedDict format while preserving references to external types. Both local and imported types are properly declared.
tests/data/expected/main/input_model/default_put_dict_import.py (1)
1-13: LGTM! Correct usage of internal generic type.The generated output properly imports and uses
DefaultPutDictfrom the internal parser module, demonstrating support for internal generic types in generated models. Both required and optional field variants are correctly represented.tests/data/expected/main/input_model/custom_class.py (1)
1-12: LGTM! Proper handling of custom class references.The generated output correctly imports and uses a custom class type as a field, demonstrating support for non-standard Pydantic field types. The structure follows expected patterns.
tests/data/expected/main/input_model/optional_only_child_no_required.py (1)
1-19: LGTM! Clean three-level inheritance with optional fields.The generated output correctly demonstrates multi-level inheritance with a mix of required and optional fields. The child class properly inherits from its parent while adding its own optional field, following standard Pydantic patterns.
tests/data/expected/main/input_model/ref_strategy_reuse_foreign_mixed_types.py (1)
1-26: LGTM! Correct mixed-type reference handling.The generated output properly demonstrates TypedDict generation with a mix of local and imported type references. The structure correctly handles multiple nested types with different origins.
Note: Class names like
NestedDataclassandNestedPydanticmight be slightly misleading since they're all TypedDicts in this output, but this likely reflects the original model types being converted to a common format.tests/data/expected/main/input_model/ref_strategy_reuse_foreign.py (1)
1-27: LGTM! Proper TypedDict with foreign imports and optional fields.The generated output correctly demonstrates:
- Foreign type import (Status) from external module
- Local TypedDict definitions (Address, Metadata)
- Proper use of NotRequired for optional nullable fields
- Clean structure following TypedDict conventions
tests/data/expected/main/input_model/typeddict.py (1)
1-12: The filename is correct. The naming convention in the test suite describes the input model type or transformation scenario being tested, not the output format.typeddict.pycorrectly indicates that a TypedDict input model is being converted to the default output format (Pydantic BaseModel). This is consistent with other files likepydantic_basemodel.py(Pydantic input to default output) andpydantic_to_typeddict.py(Pydantic to TypedDict output). No changes are needed.tests/data/expected/main/input_model/multiple_same_module.py (1)
1-34: LGTM!The expected output file correctly demonstrates the multi-level inheritance hierarchy with TypedDict classes and generates a proper TypeAlias union for the leaf types. The structure aligns with the test case
test_input_model_multiple_same_module.tests/data/expected/main/input_model/model_with_callable_types.py (1)
14-25: LGTM!The Pydantic model correctly demonstrates various
Callablefield types andType[BaseModel]for comprehensive testing of unserializable type preservation.tests/test_input_model.py (5)
20-21: LGTM!The constants are well-defined.
EXPECTED_INPUT_MODEL_PATHuses proper path construction relative to the test file, andTIMESTAMPprovides a consistent frozen time for reproducible test outputs.
50-67: LGTM!The helper function properly uses
freeze_timefor reproducible test outputs andassert_outputfor clean assertion of expected file contents.
1034-1054: LGTM!The helper function properly handles multiple
--input-modelarguments and follows the same pattern as the single model helper withfreeze_timeandassert_output.
1598-1609: LGTM!The test correctly calls
load_model_schemadirectly without needing a temporary path. The past review concern about unusedtmp_pathhas been addressed - the parameter is no longer present.
1538-1572: LGTM!Good edge case test for loading
.pyfiles without path separators. The inline assertions appropriately verify both the inheritance chain from the module path and the locally createdTempModel.tests/data/expected/main/input_model/multiple_with_dataclass_output.py (1)
1-31: LGTM! Clean dataclass implementation with proper inheritance.The inheritance chain (GrandParent → Parent → ChildA/ChildB) is correctly structured, and the type alias pattern for the union type is appropriate for this use case.
tests/data/expected/main/input_model/multiple_with_pydantic_output.py (2)
10-23: LGTM! Proper Pydantic inheritance hierarchy.The inheritance chain is correctly implemented with appropriate Field metadata for each field.
26-27: The__root__pattern here is appropriate—the test explicitly targets v1 output via--output-model-type pydantic.BaseModel, not v2. While Pydantic v2 replaced__root__withRootModel, this generator is intentionally producing v1-compatible output for backward compatibility. This test validates that the code generator can read Pydantic v2 input models and generate older v1-compatible code when requested.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
tests/test_input_model.py (1)
1245-1255: Remove or differentiate this duplicate test.This test (
test_input_model_multiple_only_not_contains) is identical totest_input_model_multiple_with_pydantic_output(lines 1217-1227) — same input models, same expected file, and same extra args. The test name and docstring also don't match each other, suggesting this is leftover from refactoring.🔎 Proposed fix - remove the duplicate
-@SKIP_PYDANTIC_V1 -def test_input_model_multiple_only_not_contains(tmp_path: Path) -> None: - """Test multiple with Pydantic output.""" - run_multiple_input_models_and_assert( - input_models=[ - "tests.data.python.input_model.inheritance_models:ChildA", - "tests.data.python.input_model.inheritance_models:ChildB", - ], - output_path=tmp_path / "output.py", - expected_file=EXPECTED_INPUT_MODEL_PATH / "multiple_with_pydantic_output.py", - extra_args=["--output-model-type", "pydantic.BaseModel"], - ) - -tests/data/expected/main/input_model/model_with_python_types_dataclass.py (1)
27-27: Verify duplicate type in union is intentional.The
optional_mappingfield has the same redundant duplicate type as in the TypedDict variant:Mapping[str, str] | Mapping[str, str] | None. This pattern appears consistently across both dataclass and TypedDict expected outputs, which suggests it may be a systematic issue in the code generation logic.Please verify whether this duplication is intentional for testing purposes or represents a bug that should be fixed in the generator before these expected outputs are finalized.
🧹 Nitpick comments (3)
tests/test_input_model.py (3)
810-854: Consider consolidating near-duplicate test functions.
test_input_model_ref_strategy_reuse_foreign_no_regeneration(lines 810-822) andtest_input_model_ref_strategy_reuse_all_no_regeneration(lines 842-854) have nearly identical implementations to their respective base tests (test_input_model_ref_strategy_reuse_foreignandtest_input_model_ref_strategy_reuse_all). The docstrings suggest different intents but the test code is identical. Either the tests should verify something different, or they should be removed as duplicates.
1475-1502: Unusedcall_countvariable.The
call_countvariable is incremented but never used for any assertion or logic control. If it was intended for debugging or future verification, consider either using it in an assertion or removing it.🔎 Proposed fix - remove unused variable
original_find_spec = importlib.util.find_spec original_import_module = importlib.import_module - call_count = 0 def fake_find_spec(name: str, *args: object, **kwargs: object) -> FakeSpec | None: - nonlocal call_count - call_count += 1 if "nonexistent_import_module" in name: return FakeSpec() return original_find_spec(name, *args, **kwargs)
1529-1552: Minor: Redundant Path import aliasing.
Pathis already imported at the module level, but here it's imported again as_Path. While functional, this is unusual. Consider using the already-importedPathdirectly.🔎 Proposed fix
def test_input_model_cwd_already_in_path( tmp_path: Path, ) -> None: """Test that cwd is not duplicated in sys.path when already present.""" import sys - from pathlib import Path as _Path - cwd = str(_Path.cwd()) + cwd = str(Path.cwd()) initial_count = sys.path.count(cwd)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
tests/data/expected/main/input_model/config_class.pytests/data/expected/main/input_model/model_with_python_types.pytests/data/expected/main/input_model/model_with_python_types_dataclass.pytests/data/expected/main/input_model/model_with_python_types_typeddict.pytests/test_input_model.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/data/expected/main/input_model/model_with_python_types.py
⏰ 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). (2)
- GitHub Check: combine coverage
- GitHub Check: benchmarks
🔇 Additional comments (10)
tests/test_input_model.py (4)
1-33: LGTM on imports and constants setup.The new imports, constants (
EXPECTED_INPUT_MODEL_PATH,TIMESTAMP), and theSKIP_PYTHON_314marker are well-structured. The Python 3.14 skip marker is appropriately documented with a clear reason about different type annotations inmodel_json_schemaoutput.
56-73: Well-designed test helper with time freezing.The updated
run_input_model_and_asserthelper properly integratesfreeze_timefor deterministic timestamp generation and usesassert_outputfor comparing against expected files. This is a good pattern for snapshot-style testing.
1052-1093: Clean implementation of multiple input model helpers.The
run_multiple_input_models_and_assertandrun_multiple_input_models_error_and_asserthelpers follow the same pattern as their single-model counterparts, maintaining consistency. Good use of__tracebackhide__for cleaner pytest output.
1615-1628: LGTM ontest_input_model_output_model_type_default.Good unit test that directly exercises
load_model_schemawithout needing filesystem fixtures. Thetmp_pathparameter was correctly removed as indicated by the past review.tests/data/expected/main/input_model/config_class.py (4)
1-11: LGTM on file header and imports.The generated header with timestamp, and the imports structure look correct for a generated TypedDict configuration file.
109-238: Overall structure of GenerateConfig is well-formed.The
GenerateConfigTypedDict comprehensively covers all configuration options with appropriateNotRequiredwrappers. The TypeAlias definitions for constrained literal types (likeDataModelType,PythonVersion, etc.) provide good type safety.
121-121: The type hint correctly reflects the actual runtime type.The
defaultdict[str, dict[str, Any]]type hint is intentional and accurate. The codebase explicitly createsdefaultdictobjects (seesrc/datamodel_code_generator/__init__.py:501andsrc/datamodel_code_generator/__main__.py:1131where JSON is loaded withobject_hook=lambda d: defaultdict(dict, **d)). The code also relies ondefaultdict's default_factory behavior—accessing nested keys directly without checking existence (e.g.,src/datamodel_code_generator/parser/jsonschema.py:1107). Since the actual runtime values aredefaultdictobjects, the type hint should accurately reflect that.Likely an incorrect or invalid review comment.
126-128: The redundant union types in this file are confirmed, but this is generated test expected output.The types
Mapping[str, str | list[str]] | Mapping[str, str | list[str]],Sequence[StrictTypes] | Sequence[StrictTypes], and similar patterns at lines 163, 166, 168-170, 181-183, 211-213 are indeed redundant—they duplicate the same type in the union.However, comparing the source (
src/datamodel_code_generator/config.pyline 94:aliases: Mapping[str, str | list[str]] | None) to this generated output reveals the duplication originates from the code generator itself during Pydantic-to-TypedDict conversion, not from hand-written code. This test file correctly captures what the generator currently produces, but the underlying issue is a bug in the generation logic that merges or duplicates types during the JSON schema conversion pipeline. The generator should be fixed to eliminate these redundant union members before writing output.tests/data/expected/main/input_model/model_with_python_types_typeddict.py (1)
1-24: LGTM! Standard TypedDict model definitions.The imports and TypedDict definitions follow expected patterns for generated code. The use of Python collection types (set, frozenset, Mapping, Sequence) is appropriate.
tests/data/expected/main/input_model/model_with_python_types_dataclass.py (1)
1-26: LGTM! Standard dataclass model definitions.The imports and dataclass definitions follow expected patterns for generated code. The use of Python collection types is appropriate and mirrors the TypedDict variant.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/datamodel_code_generator/parser/jsonschema.py (1)
1880-1888: Useself.SCHEMA_OBJECT_TYPE.__extra_key__instead of hardcoding the extras alias.The hardcoded string
"#-datamodel-code-generator-#-extras-#-special-#"duplicates the value defined byJsonSchemaObject.__extra_key__on line 235. If the format changes, this code would break silently.🔎 Proposed fix
# Don't propagate x-python-type from parent to children if it's a union type, # as this causes duplicate types (e.g., "Mapping[str, str] | None" becoming # "Mapping[str, str] | Mapping[str, str] | None") x_python_type = obj.extras.get("x-python-type", "") if " | " in x_python_type: # Remove from the extras dict in base_object (uses alias key) - extras_alias = "#-datamodel-code-generator-#-extras-#-special-#" + extras_alias = self.SCHEMA_OBJECT_TYPE.__extra_key__ if extras_alias in base_object: base_object[extras_alias].pop("x-python-type", None)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/datamodel_code_generator/parser/jsonschema.pytests/data/expected/main/input_model/config_class.pytests/test_input_model.py
🧰 Additional context used
🧬 Code graph analysis (3)
src/datamodel_code_generator/parser/jsonschema.py (1)
src/datamodel_code_generator/imports.py (2)
Import(20-38)from_full_path(35-38)
tests/test_input_model.py (3)
tests/conftest.py (1)
assert_output(545-560)src/datamodel_code_generator/__init__.py (1)
chdir(246-256)src/datamodel_code_generator/input_model.py (1)
load_model_schema(625-765)
tests/data/expected/main/input_model/config_class.py (2)
src/datamodel_code_generator/enums.py (17)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfClassHierarchy(155-159)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)DataModelType(48-56)FieldTypeCollisionStrategy(105-113)GraphQLScope(162-165)InputFileType(35-45)ModuleSplitMode(179-185)NamingStrategy(116-128)OpenAPIScope(70-78)ReadOnlyWriteOnlyModelType(168-176)ReuseScope(59-67)StrictTypes(220-227)TargetPydanticVersion(188-196)UnionMode(199-203)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)
⏰ 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). (12)
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (9)
tests/test_input_model.py (5)
5-32: LGTM! Well-organized imports and constants.The addition of centralized constants (
EXPECTED_INPUT_MODEL_PATH,TIMESTAMP) and theSKIP_PYTHON_314marker improves test maintainability and clarity. The reasoning for skipping Python 3.14+ tests is clear and appropriate.
56-73: Excellent refactoring to golden file approach.The shift from
expected_output_containssubstring matching toexpected_filecomparison withassert_outputimproves test reliability and makes test expectations explicit and reviewable. Usingfreeze_timeensures deterministic timestamps in generated output.
1052-1094: Well-designed helper functions.The new
run_multiple_input_models_and_assertandrun_multiple_input_models_error_and_asserthelpers follow the established pattern from single-model helpers and eliminate code duplication across the multiple-model test suite. Proper use of__tracebackhide__improves pytest output clarity.
1096-1220: Comprehensive inheritance test coverage.This test suite thoroughly exercises inheritance scenarios:
- Single vs. multiple model loading
- Multi-level inheritance chains
- Forked inheritance (shared parents)
- Mixed inheritance depths
- Various output types (TypedDict, Pydantic, dataclass)
The consistent use of
freeze_timeand golden files ensures deterministic, reviewable expectations.
1224-1467: Thorough error handling test coverage.The error tests comprehensively cover failure modes:
- Invalid input types and formats
- Missing files, modules, and attributes
- Version compatibility issues
- Import failures
All tests properly verify error messages and use appropriate mocking techniques. This ensures robust error reporting for users.
src/datamodel_code_generator/parser/jsonschema.py (3)
616-618: LGTM!
from pydantic import BaseModelis the standard way to define models that "inherit from BaseModel and define fields as annotated attributes." This addition correctly uses the public API path.
1201-1204: LGTM!The logic correctly preserves union
x-python-typevalues whenschema_typeis None (typically from anyOf/oneOf constructs). ReturningFalseensures the override path is taken, preventing the union type from being dropped.
1279-1281: LGTM!The priority lookup via
_resolve_type_import(class_name)ensures well-known types (likeBaseModel) use their canonical public import paths, with a sensible fallback to the fully-qualified path for unknown types.tests/data/expected/main/input_model/config_class.py (1)
1-232: LGTM!This generated test expected output file correctly defines TypeAlias declarations matching the enum values from
src/datamodel_code_generator/enums.pyandsrc/datamodel_code_generator/format.py. TheGenerateConfigTypedDict comprehensively covers the configuration options with appropriateNotRequiredwrappers.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/datamodel_code_generator/parser/jsonschema.py (1)
1876-1880: Use the class constant instead of hardcoding the extras alias.The hardcoded string
"#-datamodel-code-generator-#-extras-#-special-#"duplicates the value defined inJsonSchemaObject.__extra_key__(line 235). Using the constant would be more maintainable.🔎 Proposed fix
base_object = model_dump(obj, exclude={target_attribute_name}, exclude_unset=True, by_alias=True) x_python_type = obj.extras.get("x-python-type", "") if " | " in x_python_type: - extras_alias = "#-datamodel-code-generator-#-extras-#-special-#" + extras_alias = self.SCHEMA_OBJECT_TYPE.__extra_key__ if extras_alias in base_object: base_object[extras_alias].pop("x-python-type", None)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/datamodel_code_generator/parser/jsonschema.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/datamodel_code_generator/parser/jsonschema.py (1)
src/datamodel_code_generator/imports.py (2)
Import(20-38)from_full_path(35-38)
⏰ 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). (5)
- GitHub Check: benchmarks
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.13 on Windows
🔇 Additional comments (3)
src/datamodel_code_generator/parser/jsonschema.py (3)
616-616: LGTM!Adding
BaseModeltoPYTHON_TYPE_IMPORTSenables proper public import path resolution for pydantic.BaseModel when used in x-python-type overrides.
1200-1203: LGTM - Union type handling for x-python-type overrides.The new condition correctly identifies union types (
|syntax) with no schema type as requiring a type override. This ensures unions in x-python-type are processed rather than passed through as compatible.
1276-1278: LGTM - Prefer public import paths for nested types.The change to first try
_resolve_type_import(class_name)before falling back toImport.from_full_path(qualified_name)enables reuse of well-known public import paths fromPYTHON_TYPE_IMPORTS. This is especially useful for types likeBaseModelthat should be imported from their public API path.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/datamodel_code_generator/input_model.py (3)
429-473: Ref-strategy implementation matches tests but diverges fromInputModelRefStrategydocstringFunctionally,
_get_output_family,_get_type_family,_should_reuse_type, and_filter_defs_by_strategycorrectly implement:
- Always reusing enums via
x-python-import.- Under
ReuseForeign, reusing same-family types (e.g., Pydantic when output is Pydantic, TypedDict when output is TypedDict) plus enums, while regenerating other families into the target output type.- Under
ReuseAll, reusing all nested types viax-python-import.This aligns with the new test docstrings like
test_input_model_ref_strategy_reuse_foreign_*, which explicitly describe “imports enum (always) and same-family types”.However, the
InputModelRefStrategydocstring insrc/datamodel_code_generator/enums.pystill states thatReuseForeignreuses “types from different model families,” which is now the opposite of what the code and tests do. It would be good to update that docstring (and any CLI help that mirrors it) to avoid confusion.Also applies to: 482-523
562-621: Inheritance transformation handles single BaseModel parent chains but ignores multiple BaseModel bases
_transform_single_model_to_inheritancecorrectly reshapes flat Pydantic schemas into:
$defsentries for each BaseModel ancestor, and- a child schema with
allOf: [{"$ref": "#/$defs/Parent"}]and only the child-specific properties/required fields,recursing up the chain and merging
$defs. This matches the new single- and multi-level inheritance tests.One limitation is that when a model has multiple BaseModel parents (multiple inheritance), only
direct_parents[0]is honored; fields from other BaseModel bases stay on the child and those bases never appear inallOf. That’s probably acceptable for now given the focus on simple single-inheritance hierarchies, but you may want to:
- either document that only the first BaseModel parent is used, or
- eventually extend this to support multiple BaseModel parents or raise a clear error in that case.
623-764:load_model_schemamulti-model loader logic is solid and matches the new testsHighlights:
- Correctly defaults
output_model_typetoDataModelType.PydanticBaseModelwhen omitted, which your newtest_input_model_output_model_type_defaultverifies for the single-model path.- For
len(input_models) > 1, it:
- Ensures CWD is on
sys.pathonce.- Distinguishes module-vs-path imports (including
.pyfilename heuristics), shares loaded modules vialoaded_modules, and raises clearErrormessages for bad formats, missing files/modules, or import failures.- Enforces that all objects are Pydantic
BaseModelsubclasses withmodel_json_schema(v2 runtime) and thatinput_file_typeisAutoorJsonSchemafor multi-Pydantic scenarios.- Generates per-model schemas through the custom generator, augments them with
x-python-type/ unserializable handling and inheritance transformation, merges$defs, and returns ananyOfroot of$refs into those defs.- Applies
ref_strategyvia_filter_defs_by_strategywhen requested, using_collect_nested_modelsacross all roots.Behavior lines up with the matrix of multiple
--input-modelsuccess/error tests, and the module-loading duplication vs_load_single_model_schemais acceptable, though you could factor a shared “load object from input-model string” helper later if you want to DRY it up.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
tests/data/jsonschema/x_python_type_union_anyof.jsonis excluded by!tests/data/**/*.jsonand included by none
📒 Files selected for processing (5)
src/datamodel_code_generator/input_model.pysrc/datamodel_code_generator/parser/jsonschema.pytests/data/expected/main/jsonschema/x_python_type_union_anyof.pytests/main/jsonschema/test_main_jsonschema.pytests/test_input_model.py
🧰 Additional context used
🧠 Learnings (2)
📚 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/input_model.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.
Applied to files:
src/datamodel_code_generator/input_model.py
🧬 Code graph analysis (3)
tests/data/expected/main/jsonschema/x_python_type_union_anyof.py (1)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
Field(6-7)
src/datamodel_code_generator/input_model.py (1)
src/datamodel_code_generator/enums.py (3)
DataModelType(48-56)InputFileType(35-45)InputModelRefStrategy(206-217)
src/datamodel_code_generator/parser/jsonschema.py (1)
src/datamodel_code_generator/imports.py (2)
Import(20-38)from_full_path(35-38)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/input_model.py
34-34: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
36-36: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
37-37: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
83-83: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
127-127: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
132-132: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
143-143: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
158-158: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
185-185: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
233-233: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
234-234: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
235-235: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
236-236: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
237-237: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
238-238: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
239-239: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
260-260: Unused noqa directive (non-enabled: PLW0603)
Remove unused noqa directive
(RUF100)
266-266: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
268-268: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
269-269: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
275-275: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
284-284: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
314-314: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
351-351: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
352-352: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
353-353: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
373-373: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
429-429: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
431-431: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
432-432: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
457-457: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
489-489: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
532-532: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
533-533: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
534-534: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
545-545: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
546-546: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
623-623: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
640-640: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
641-641: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
643-643: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
647-647: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
766-766: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
786-786: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
787-787: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
789-789: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
790-790: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
870-870: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
882-882: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (12)
- GitHub Check: py312-black24 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.12 on macOS
- 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: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (9)
tests/data/expected/main/jsonschema/x_python_type_union_anyof.py (1)
1-13: Generated model fixture looks consistent and correctHeader, imports, and the
ModelWithUnionTypedefinition (nullableMapping[str, str]withField(..., title='Optional Mapping')) align with existing expected JSON Schema outputs and union-operator style in this test suite.tests/main/jsonschema/test_main_jsonschema.py (1)
7209-7216: New x-python-type anyOf union test is well-integratedThe
test_x_python_type_union_anyofwiring (JSON_SCHEMA_DATA_PATH input,input_file_type=None,assert_file_content, no extra args) matches the surroundingx_python_type_*tests and will exercise the new expected fixture without introducing new behavior in the helper.src/datamodel_code_generator/parser/jsonschema.py (2)
554-617: BaseModel entry inPYTHON_TYPE_IMPORTSlooks correct and consistentAdding
"BaseModel": Import.from_full_path("pydantic.BaseModel")aligns with how other common types are handled and lets_resolve_type_importcanonicalizeBaseModelcoming fromx-python-typewithout ad-hoc imports. No issues here.
1192-1203: Union guard and nested import resolution forx-python-typeare sound
- The extra check in
_is_compatible_python_typeto returnFalsewhenpython_typecontains" | "andschema_typeisNoneensures union-stylex-python-type(PEP 604) is treated as an override instead of being silently considered "compatible". That matches the new union/Mapping[...] | Nonepreservation tests and avoids losing override semantics when the schema has no explicittype.- In
_get_python_type_override, preferringself._resolve_type_import(class_name)overImport.from_full_path(qualified_name)for nested/qualified names reuses the canonical import mapping (e.g.,BaseModel, collections.abc types) and only falls back to a full-path import when needed, which should reduce duplicate/odd imports.Behavior is coherent with the new tests and doesn’t introduce obvious regressions.
Also applies to: 1273-1277
tests/test_input_model.py (3)
16-23: Shared expected path, timestamp freezing, and golden-file assertion are well factoredUsing
EXPECTED_INPUT_MODEL_PATHplusTIMESTAMPwithfreeze_timeinrun_input_model_and_assertand delegating toassert_outputgives stable, golden-file based tests and eliminates per-test duplication. The helper argument order (input_model,output_path,expected_file,extra_args) is clear and matches how it’s used throughout the file.Also applies to: 56-74
29-33: Python 3.14 skip marker is appropriate for schema-string-sensitive tests
SKIP_PYTHON_314plus its use on the x-python-type preservation tests and the config-class test cleanly isolates cases that depend onmodel_json_schema’s exact annotation formatting. This keeps the suite green on Python 3.14+ without weakening coverage on earlier versions.Also applies to: 475-552, 575-621, 1036-1043
1052-1591: Multiple--input-modelhelpers and inheritance/error-matrix tests give strong coverage
run_multiple_input_models_and_assert/run_multiple_input_models_error_and_assertmirror the single-model helpers cleanly, construct the CLI args correctly (repeating--input-modeland appending--output/ extras), and consistently assert on exit codes, file existence, and stderr.- The new tests cover:
- Single-model inheritance (flat, multi-level, no-inheritance) and forked/mixed multi-model inheritance against golden files.
- Output-model-type variants (Pydantic, dataclass, TypedDict) and ref-strategy combinations.
- All major error surfaces for multiple
--input-model(non-BaseModel, Pydantic v1 runtime, bad format, missing file/module/attribute, non-jsonschemainput-file-type, module load/import failures).- sys.path behavior (cwd added vs already present), path-based module loading (with and without separators), and config coercion of
input-modelfrom string to list.- Direct
load_model_schemadefaulting ofoutput_model_typeviatest_input_model_output_model_type_default.The scenarios align with the new loader’s behavior and look comprehensive without obvious gaps.
src/datamodel_code_generator/input_model.py (2)
19-24: Type-serialization and unserializable handling pipeline is coherentThe combination of:
_get_input_model_json_schema_classmarking all invalid/callable types with_UNSERIALIZABLE_MARKER,_add_python_type_for_unserializable/_process_unserializable_property/_set_python_type_for_unserializableusing full serialization (_serialize_python_type_full) to attachx-python-typeat the right level (includinganyOf/oneOf/itemsbranches andType[X]),_init_preserved_type_origins+_serialize_python_type/_simple_type_nameto addx-python-typefor container types that are JSON-schema-serializable (set/frozenset/mappings/sequences, both typing and collections.abc origins), and_collect_nested_models/_add_python_type_info/_add_python_type_info_genericfor BaseModel vs dataclass/TypedDict,forms a consistent story that matches the new tests around
ModelWithPythonTypes, callables, unions, and nested definitions. The use of lazy imports with# noqa: PLC0415is also aligned with prior project guidance to keep these defensive directives.Also applies to: 34-107, 125-229, 231-427
766-901: Single-model loader_load_single_model_schemacovers all supported types and validation pathsThe single-model path:
- Validates the
module:Object/path/to/file.py:Objectformat and uses a CWD-injecting import strategy symmetric withload_model_schema.- Distinguishes:
dict→ returns the dict directly, requiring a non-AutoInputFileType, which the dict tests exercise.- Pydantic BaseModel subclasses → enforces
Auto/JsonSchemainput_file_type, requiresmodel_json_schema(v2 runtime), runs_try_rebuild_model, applies the same schema generator +x-python-type+ inheritance transform as in the multi-case, and then ref-strategy filtering if requested.- dataclass / TypedDict types → enforces
Auto/JsonSchema, usesTypeAdapter(obj).json_schema(), augments with_add_python_type_info_generic, and applies ref-strategy filtering, with clear error messaging ifTypeAdapteris unavailable (v1 runtime).- Everything else → raises a concise “not a supported type”
Error.This matches the various error tests (
*_non_jsonschema_error, Pydantic v1 runtime, dataclass/TypedDict Pydantic v1, unsupported type) and the positive dataclass/TypedDict and config-class cases. The loader’s responsibilities are clear and the branching looks correct.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/test_input_model.py (1)
1-1574: Fix formatting to resolve pipeline failure.The pipeline reports that ruff-format made formatting changes to this file. Run
ruff format tests/test_input_model.pyto fix the formatting issues and commit the changes.
🧹 Nitpick comments (1)
tests/test_input_model.py (1)
365-365: Remove redundant local sys imports.The module-level
import syson line 5 is available throughout the file. The local imports on lines 365 and 1483 inside test functions are redundant and trigger the Ruff F811 warning.🔎 Proposed fix
Remove the local imports on lines 365 and 1483:
Line 365 (inside
test_input_model_adds_cwd_to_sys_path):def test_input_model_adds_cwd_to_sys_path( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: """Test that --input-model adds cwd to sys.path if not present.""" - import sys - cwd = str(tmp_path)Line 1483 (inside
test_input_model_cwd_already_in_path):def test_input_model_cwd_already_in_path( tmp_path: Path, ) -> None: """Test that cwd is not duplicated in sys.path when already present.""" - import sys from pathlib import Path as _PathAlso applies to: 1483-1483
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/input_model.pytests/test_input_model.py
🧰 Additional context used
🧠 Learnings (2)
📚 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/input_model.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.
Applied to files:
src/datamodel_code_generator/input_model.py
🧬 Code graph analysis (1)
src/datamodel_code_generator/input_model.py (2)
src/datamodel_code_generator/enums.py (3)
DataModelType(48-56)InputFileType(35-45)InputModelRefStrategy(206-217)src/datamodel_code_generator/model/base.py (2)
name(827-829)DataModel(621-930)
🪛 GitHub Actions: Lint
tests/test_input_model.py
[error] 1-1: ruff-format: 1 file reformatted by hook; some formatting changes were made.
🪛 Ruff (0.14.10)
src/datamodel_code_generator/input_model.py
34-34: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
36-36: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
37-37: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
83-83: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
127-127: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
132-132: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
143-143: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
158-158: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
185-185: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
233-233: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
234-234: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
235-235: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
236-236: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
237-237: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
238-238: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
239-239: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
260-260: Unused noqa directive (non-enabled: PLW0603)
Remove unused noqa directive
(RUF100)
266-266: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
268-268: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
269-269: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
275-275: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
285-285: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
315-315: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
352-352: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
353-353: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
354-354: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
374-374: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
430-430: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
432-432: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
433-433: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
458-458: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
490-490: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
533-533: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
534-534: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
535-535: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
546-546: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
547-547: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
624-624: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
641-641: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
642-642: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
644-644: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
648-648: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
767-767: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
787-787: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
788-788: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
790-790: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
791-791: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
871-871: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
883-883: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
tests/test_input_model.py
1483-1483: Redefinition of unused sys from line 5
Remove definition: sys
(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-isort5 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.13 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (1)
src/datamodel_code_generator/input_model.py (1)
1-902: LGTM! Solid implementation of input model loading and schema transformation.The new input model loading infrastructure is well-designed and comprehensive. The public API (
load_model_schemaandError) provides clean interfaces for loading and merging schemas from Python import paths with inheritance support. The implementation properly handles:
- Type preservation via x-python-type annotations for types lost during JSON Schema conversion
- Inheritance transformation using allOf structures
- Multiple input model families (Pydantic v2, dataclass, TypedDict, msgspec)
- Ref-strategy options for controlling type reuse vs regeneration
- Robust error handling with descriptive messages
All previously flagged issues (import aliases, noqa directive placement) have been addressed in prior commits.
Based on learnings, defensive
# noqa: PLC0415and# noqa: PLR6301directives should be kept even when Ruff reports them as unused via RUF100, as they prepare for potential future configuration changes.
- Add _resolve_type_import_from_defs method to resolve imports from $defs entries with x-python-import metadata - Handle Annotated types in _serialize_python_type_full to prevent invalid type serialization with FieldInfo
16ba6c0 to
325ed3c
Compare
Add _full_type_name helper function that generates fully qualified names for type arguments while keeping outer types as short names. This ensures proper import resolution for custom types like StrictTypes. - Add _full_type_name function with Union type handling (| syntax) - Update _serialize_python_type to use _full_type_name for type args - Update expected test file for config_class output
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/datamodel_code_generator/input_model.py (1)
876-881: Consider renaming variable for clarity.The variable
moduleis reused at line 877 (assignedModuleSpec | None) and line 881 (reassigned to actual module). While not incorrect, using distinct names likemodule_specandmodulewould improve readability.🔎 Suggested refactor for clarity
else: try: - module = importlib.util.find_spec(modname) - if module is None: + module_spec = importlib.util.find_spec(modname) + if module_spec is None: msg = f"Cannot find module {modname!r}" raise Error(msg) module = importlib.import_module(modname)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/input_model.pytests/data/expected/main/input_model/config_class.py
🧰 Additional context used
🧠 Learnings (2)
📚 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/input_model.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.
Applied to files:
src/datamodel_code_generator/input_model.py
🧬 Code graph analysis (2)
src/datamodel_code_generator/input_model.py (2)
src/datamodel_code_generator/enums.py (3)
DataModelType(48-56)InputFileType(35-45)InputModelRefStrategy(206-217)src/datamodel_code_generator/parser/jsonschema.py (1)
model_rebuild(218-220)
tests/data/expected/main/input_model/config_class.py (4)
src/datamodel_code_generator/model/type_alias.py (1)
TypeAlias(37-42)src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)src/datamodel_code_generator/enums.py (4)
StrictTypes(220-227)AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfClassHierarchy(155-159)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/input_model.py
34-34: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
36-36: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
37-37: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
66-66: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
90-90: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
134-134: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
139-139: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
150-150: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
165-165: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
192-192: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
240-240: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
241-241: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
242-242: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
243-243: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
244-244: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
245-245: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
246-246: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
267-267: Unused noqa directive (non-enabled: PLW0603)
Remove unused noqa directive
(RUF100)
273-273: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
275-275: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
276-276: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
282-282: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
292-292: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
322-322: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
333-333: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
339-339: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
340-340: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
408-408: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
409-409: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
410-410: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
430-430: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
486-486: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
488-488: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
489-489: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
514-514: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
546-546: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
589-589: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
590-590: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
591-591: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
602-602: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
603-603: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
680-680: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
697-697: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
698-698: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
700-700: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
704-704: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
823-823: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
843-843: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
844-844: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
846-846: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
847-847: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
927-927: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
939-939: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (10)
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.13 on macOS
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.14 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (2)
src/datamodel_code_generator/input_model.py (1)
34-958: LGTM! The implementation is solid.This file introduces comprehensive input model loading and schema transformation capabilities. The code handles complex type serialization, inheritance preservation, and various edge cases appropriately.
Regarding static analysis warnings: The RUF100 warnings about "unused noqa directives" should be ignored. Based on learnings, defensive
# noqa: PLC0415directives should be kept on lazy imports even when Ruff reports them as unused, and# noqa: PLR6301directives are necessary for methods in Ruff preview mode.The complexity suppressions (
PLR0911,PLR0912,PLR0914,PLR0915) are appropriate given the nature of type serialization and multi-model loading logic.Note on learnings: Based on learnings, defensive
# noqa: PLC0415directives 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. Similarly,noqa: PLR6301directives are necessary and should not be removed even if RUF100 suggests they are unused, as Ruff preview mode is enabled vialint.preview = truein pyproject.toml.tests/data/expected/main/input_model/config_class.py (1)
1-233: LGTM! Generated test file is well-formed.This generated test file correctly defines comprehensive type aliases and TypedDict structures for configuration. The fixed timestamp (1985-10-26T08:21:00+00:00) is appropriate for deterministic test output. All type definitions are consistent with the source enums and structures.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/datamodel_code_generator/input_model.py
🧰 Additional context used
🧠 Learnings (2)
📚 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/input_model.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.
Applied to files:
src/datamodel_code_generator/input_model.py
🪛 Ruff (0.14.10)
src/datamodel_code_generator/input_model.py
34-34: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
36-36: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
37-37: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
66-66: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
90-90: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
134-134: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
139-139: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
150-150: Unused noqa directive (non-enabled: PLR6301)
Remove unused noqa directive
(RUF100)
165-165: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
192-192: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
240-240: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
241-241: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
242-242: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
243-243: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
244-244: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
245-245: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
246-246: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
267-267: Unused noqa directive (non-enabled: PLW0603)
Remove unused noqa directive
(RUF100)
273-273: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
275-275: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
276-276: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
282-282: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
292-292: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
322-322: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
333-333: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
339-339: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
340-340: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
408-408: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
409-409: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
410-410: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
430-430: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
486-486: Unused noqa directive (non-enabled: PLR0911)
Remove unused noqa directive
(RUF100)
488-488: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
489-489: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
514-514: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
546-546: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
589-589: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
590-590: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
591-591: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
602-602: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
603-603: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
680-680: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
697-697: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
698-698: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
700-700: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
704-704: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
823-823: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
843-843: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
844-844: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
846-846: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
847-847: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
927-927: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
939-939: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
⏰ 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). (2)
- GitHub Check: 3.10 on Windows
- GitHub Check: benchmarks
🔇 Additional comments (10)
src/datamodel_code_generator/input_model.py (10)
1-130: LGTM! Solid foundation with type serialization utilities.The module structure, constants, and initial type serialization utilities are well-designed. The
_serialize_python_type_full()function comprehensively handles various Python type representations including Union, Annotated, Callable, and generic types.
132-161: LGTM! Custom schema generator correctly handles unserializable types.The lazy-loaded
InputModelJsonSchemaclass properly catches types that Pydantic cannot serialize to JSON Schema, including Callable types. Thenoqa: PLR6301directives on Lines 139 and 150 should be kept despite Ruff's RUF100 warnings, as they prepare for potential future configuration changes.Based on learnings, these defensive directives are intentional for preview rules.
163-236: LGTM! Robust handling of unserializable types with proper recursion guards.The functions correctly process properties marked as unserializable, handle complex structures (anyOf/oneOf/items), and use
visited_defstracking to prevent infinite recursion when processing nested models.
238-380: LGTM! Comprehensive type serialization with preserved type origins.The lazy initialization of preserved type origins and the type serialization functions handle complex scenarios including Union types (with modern
|syntax), Annotated types, and fully qualified names. The logic correctly preserves important type information that would be lost in JSON Schema conversion.
382-484: LGTM! Well-designed nested model discovery and type annotation.The nested model collection uses proper recursion guards with
visitedsets, supports multiple type families (BaseModel, Enum, dataclass, TypedDict, msgspec), and safely handles type hints with appropriate fallback. The x-python-type annotation functions correctly preserve type information across different input formats.
486-537: LGTM! Type family classification and reuse logic are correct.The type family determination correctly handles the precedence of different type categories, the output family mapping properly handles all DataModelType cases, and the reuse logic appropriately treats Enums as always reusable while requiring family matching for other types.
539-612: LGTM! Strategy-based filtering and model rebuilding are well-implemented.The
_filter_defs_by_strategy()function correctly implements the three strategies (RegenerateAll, ReuseAll, ReuseForeign) and properly annotates reused types with x-python-import metadata. The_try_rebuild_model()function appropriately handles special config classes with their required type namespaces.
614-678: LGTM! Inheritance transformation correctly implements allOf structure.The
_transform_single_model_to_inheritance()function properly handles multi-level inheritance by recursively processing parent schemas, using a cache (processed_parents) to avoid reprocessing, and correctly separating parent and child properties/requirements. The resulting allOf structure with parent references preserves the inheritance hierarchy in JSON Schema.
680-821: LGTM! Main API function correctly handles multiple input models with comprehensive validation.The
load_model_schema()function properly:
- Validates input format and loads modules/classes
- Enforces Pydantic v2 BaseModel requirement for multiple inputs
- Validates
input_file_typecompatibility- Applies inheritance transformation to each model
- Merges schemas into an anyOf structure with aggregated $defs
- Applies reference strategy filtering
The error messages are clear and helpful, and the function handles both module import paths and file paths correctly.
823-876: LGTM! Single model loading correctly handles multiple input types (after bug fix).The
_load_single_model_schema()function (aside from the Lines 877-881 bug) properly:
- Parses input format and distinguishes module vs file paths
- Handles dict inputs (raw schema)
- Handles Pydantic v2 BaseModel with inheritance transformation
- Handles dataclass/TypedDict via Pydantic v2 TypeAdapter
- Validates
input_file_typecompatibility for each case- Applies appropriate schema transformations and ref strategy filtering
The error messages provide clear guidance, and the function correctly uses the various helper functions for schema generation and transformation.
Also applies to: 882-958
- Add tests for _simple_type_name edge cases (NoneType, generic types) - Add tests for _full_type_name (string annotation, ForwardRef, typing specials) - Add tests for _serialize_python_type_full with Annotated type - Add tests for _resolve_type_import_from_defs (found, not found, no x-python-import, exception handling) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Use list.__class_getitem__(()) to create a GenericAlias with origin but no args, avoiding the ruff UP035 auto-fix that converted typing.List to list. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Renamed misleading variable from 'module' to 'spec' when storing the result of importlib.util.find_spec(), as it returns a ModuleSpec not a module object. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Test builtin type (module='builtins') returns short name - Test collections.abc type returns short name 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Breaking Change AnalysisResult: Breaking changes detected Reasoning: The PR changes Config.input_model from Optional[str] to Optional[list[str]]. While a field validator ensures backward compatibility when setting the value (single strings are coerced to lists), code that reads this field will now receive a list instead of a string. This affects users who programmatically interact with the Config class. The CLI remains backward compatible since --input-model can still be used once as before, or multiple times for the new functionality. Content for Release NotesAPI/CLI Changes
This analysis was performed by Claude Code Action |
|
🎉 Released in 0.51.0 This PR is now available in the latest release. See the release notes for details. |
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.