Skip to content

Add --input-model-ref-strategy option for controlling type reuse#2850

Merged
koxudaxi merged 2 commits intomainfrom
feature/input-model-ref-strategy
Dec 29, 2025
Merged

Add --input-model-ref-strategy option for controlling type reuse#2850
koxudaxi merged 2 commits intomainfrom
feature/input-model-ref-strategy

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Dec 29, 2025

Summary by CodeRabbit

  • New Features

    • Added a new CLI option --input-model-ref-strategy to control how referenced input types are handled (regenerate-all, reuse-foreign, reuse-all) and exposed the corresponding strategy type in the public API.
  • Documentation

    • Updated CLI reference, quick reference, and option descriptions with the new option, examples, and usage guidance.
  • Tests

    • Added test data and extensive tests covering the new strategies (including nested/reused models).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 29, 2025

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 33 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between bb17d1f and 8d5fb5d.

📒 Files selected for processing (14)
  • docs/cli-reference/base-options.md
  • docs/cli-reference/index.md
  • docs/cli-reference/quick-reference.md
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/enums.py
  • src/datamodel_code_generator/parser/jsonschema.py
  • src/datamodel_code_generator/prompt_data.py
  • tests/data/python/input_model/dataclass_nested.py
  • tests/data/python/input_model/nested_models.py
  • tests/data/python/input_model/typeddict_nested.py
  • tests/test_input_model.py
📝 Walkthrough

Walkthrough

Adds a new CLI option --input-model-ref-strategy, introduces InputModelRefStrategy enum, wires the strategy through Config and _load_model_schema, filters/annotates referenced $defs (e.g., x-python-import), and updates the JSON Schema parser to respect those annotations; plus docs and tests.

Changes

Cohort / File(s) Summary
Documentation
docs/cli-reference/base-options.md, docs/cli-reference/index.md, docs/cli-reference/quick-reference.md
Documented new --input-model-ref-strategy option, its values, examples, and index entries.
Enum & Exports
src/datamodel_code_generator/enums.py, src/datamodel_code_generator/__init__.py
Added InputModelRefStrategy enum and exported it from the package.
CLI wiring
src/datamodel_code_generator/arguments.py, src/datamodel_code_generator/cli_options.py, src/datamodel_code_generator/prompt_data.py
Registered new CLI option metadata, added argument parsing help/choices, and included option description in prompt data.
Core logic
src/datamodel_code_generator/__main__.py
Added input_model_ref_strategy to Config; extended _load_model_schema() signature and flow; introduced type-family classification, _filter_defs_by_strategy(), and expanded nested-model discovery to include Enums and dataclasses.
Parser
src/datamodel_code_generator/parser/jsonschema.py
Added x-python-import handling: early parse short-circuit for x-python-import, _handle_python_import() helper, and get_ref_data_type() support to create imports from metadata and avoid regenerating annotated types.
Tests — fixtures
tests/data/python/input_model/dataclass_nested.py, tests/data/python/input_model/nested_models.py
New test input modules with enums, dataclasses, and Pydantic models to exercise ref-strategy behavior.
Tests — cases
tests/test_input_model.py
Added comprehensive tests for --input-model-ref-strategy scenarios (regenerate-all, reuse-foreign, reuse-all); includes multiple model/type permutations.

Sequence Diagram

sequenceDiagram
    autonumber
    participant CLI as CLI Parser
    participant Config as Config
    participant Loader as _load_model_schema
    participant Filter as _filter_defs_by_strategy
    participant Parser as JsonSchemaParser
    participant Output as Code Generator

    CLI->>Config: parse --input-model-ref-strategy
    Config->>Loader: pass input_model_ref_strategy
    Loader->>Loader: generate JSON Schema from input model
    Loader->>Loader: collect nested types (pydantic, enum, dataclass, typedict)
    Loader->>Filter: filter/annotate $defs using strategy
    alt strategy marks reuse
        Filter->>Filter: classify type families, add `x-python-import` to reused defs
        Filter->>Loader: return modified schema
    end
    Loader->>Parser: provide annotated schema
    Parser->>Parser: detect `x-python-import` on $ref
    alt x-python-import present
        Parser->>Parser: create Import, mark ref as handled, skip generation
    else
        Parser->>Parser: generate model from schema
    end
    Parser->>Output: emit code and imports
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #2804: Modifies the input-model loading path and _load_model_schema() — directly related to the same codepaths this change extends.
  • PR #2837: Adds/consumes Python-specific JSON Schema metadata; overlaps with parser/schema annotation behavior introduced here.

Suggested labels

breaking-change-analyzed

Poem

🐰 I hopped through schemas, three ways to choose,
Regenerate, reuse—no need to lose,
I tuck imports into x-python-import bright,
Parsers skip what I mark, and code builds right. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature being added: a new CLI option --input-model-ref-strategy that controls how referenced types are reused.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 29, 2025

📚 Docs Preview: https://pr-2850.datamodel-code-generator.pages.dev

Comment thread src/datamodel_code_generator/__main__.py Fixed
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 29, 2025

CodSpeed Performance Report

Merging #2850 will not alter performance

Comparing feature/input-model-ref-strategy (8d5fb5d) with main (16f27ef)

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

Summary

✅ 11 untouched
⏩ 98 skipped1

Footnotes

  1. 98 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@koxudaxi koxudaxi force-pushed the feature/input-model-ref-strategy branch from a99405b to 1d6e5a3 Compare December 29, 2025 03:57
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
tests/test_input_model.py (1)

609-801: Ref-strategy tests correctly exercise all strategies and key behaviors

The new tests cover default vs explicit regenerate-all, reuse-foreign and reuse-all (including “no regeneration” checks), plus dataclass/TypedDict inputs and the “ignored without --input-model” case. This gives good confidence in the new option’s semantics.

If this area grows further, consider parametrizing the nested_models/dataclass_nested cases to reduce repetition, but that’s purely optional.

src/datamodel_code_generator/parser/jsonschema.py (1)

1223-1237: x-python-import handling is aligned with reuse strategies; consider a couple of small robustness tweaks

The new behavior in get_ref_data_type and parse_raw_obj achieves the intended effect:

  • $ref targets whose resolved schema has extras["x-python-import"] are now turned into direct imports via Import.from_full_path(...) and self.data_type.from_import(import_), with no model generation.
  • Definitions whose raw value contains x-python-import are marked as loaded via _handle_python_import, so the later reserved-ref machinery won’t try to parse them into models, which fits the “reuse imported type” semantics.

Two minor points you might want to tighten up:

  1. Guard the parse_raw_obj fast-path on shape, not just key presence

    Right now any dict with an "x-python-import" key is skipped:

    if isinstance(raw, dict) and "x-python-import" in raw:
        self._handle_python_import(name, path)
        return

    but get_ref_data_type only treats it specially when ref_schema.extras["x-python-import"] is a dict with both module and name. If someone supplied a malformed x-python-import (or used that key for a different extension), we’d end up with a loaded reference and no generated model, while get_ref_data_type would fall back to regular ref handling and never see a backing model. You could instead only short-circuit when the value is a proper dict with the expected keys, otherwise fall back to normal parsing.

  2. Confirm self.data_type is bound to the DataType class

    self.data_type is used elsewhere as a callable factory; here you’re calling self.data_type.from_import(import_). This assumes self.data_type is a DataType class (or subclass) exposing from_import. That matches typical wiring in this project but is worth verifying; if it were ever rebound to a plain factory function, this would raise at runtime. An explicit DataType.from_import(import_) (or going through self.data_type_manager if you prefer) would make the dependency clearer.

These are non-blocking; the core logic and interactions with model_resolver/reserved_refs look solid.

Also applies to: 3536-3549

src/datamodel_code_generator/__main__.py (5)

447-447: Remove unused noqa directive.

The noqa: UP045 directive is unused per static analysis. While the code is correct, removing unnecessary directives keeps the codebase clean.

🔎 Proposed fix
-    input_model_ref_strategy: Optional[InputModelRefStrategy] = None  # noqa: UP045
+    input_model_ref_strategy: Optional[InputModelRefStrategy] = None

Based on static analysis hints.


686-709: Remove unused noqa directives.

The function logic correctly handles collecting nested types from Pydantic models, dataclasses, and TypedDicts. However, the noqa: PLC0415 directive at line 688 is unused per static analysis.

🔎 Proposed fix
-    from dataclasses import is_dataclass  # noqa: PLC0415
+    from dataclasses import is_dataclass

Based on static analysis hints.


712-726: Remove unused noqa directives.

The enhanced logic to find BaseModel subclasses, Enums, and dataclasses looks correct. However, static analysis flags unused noqa: PLC0415 directives at lines 714, 715, and 716.

🔎 Proposed fix
-    from dataclasses import is_dataclass  # noqa: PLC0415
-    from enum import Enum as PyEnum  # noqa: PLC0415
+    from dataclasses import is_dataclass
+    from enum import Enum as PyEnum
     from typing import get_args  # noqa: PLC0415

Based on static analysis hints.


791-828: Remove unused _OUTPUT_TYPE_FAMILY global and unused noqa directives.

The _get_type_family() function implementation looks correct for determining type families. However:

  1. The _OUTPUT_TYPE_FAMILY mapping defined at lines 797-804 is never used in the code (flagged by CodeQL).
  2. The noqa: PLC0415 directives at lines 809-810 are unused per static analysis.

If _OUTPUT_TYPE_FAMILY was intended for future use or comparison against output model types, consider either implementing that functionality or removing the unused mapping to reduce code clutter.

🔎 Proposed fix
 _TYPE_FAMILY_ENUM = "enum"
 _TYPE_FAMILY_PYDANTIC = "pydantic"
 _TYPE_FAMILY_DATACLASS = "dataclass"
 _TYPE_FAMILY_TYPEDDICT = "typeddict"
 _TYPE_FAMILY_OTHER = "other"
 
-_OUTPUT_TYPE_FAMILY: dict[DataModelType, str] = {
-    DataModelType.PydanticBaseModel: _TYPE_FAMILY_PYDANTIC,
-    DataModelType.PydanticV2BaseModel: _TYPE_FAMILY_PYDANTIC,
-    DataModelType.DataclassesDataclass: _TYPE_FAMILY_DATACLASS,
-    DataModelType.PydanticV2Dataclass: _TYPE_FAMILY_PYDANTIC,
-    DataModelType.TypingTypedDict: _TYPE_FAMILY_TYPEDDICT,
-    DataModelType.MsgspecStruct: "msgspec",
-}
-
 
 def _get_type_family(tp: type) -> str:
     """Determine the type family of a Python type."""
-    from dataclasses import is_dataclass  # noqa: PLC0415
-    from enum import Enum as PyEnum  # noqa: PLC0415
+    from dataclasses import is_dataclass
+    from enum import Enum as PyEnum

Based on static analysis hints and CodeQL findings.


872-999: Remove unused noqa directive; otherwise LGTM.

The enhanced _load_model_schema function correctly applies the reference strategy for both Pydantic models and dataclass/TypedDict inputs. The logic consistently:

  1. Generates the JSON schema
  2. Adds Python type information
  3. Filters $defs based on the strategy when applicable

However, the noqa: PLR0912, PLR0914, PLR0915 directive at line 872 is unused per static analysis.

🔎 Proposed fix
-def _load_model_schema(  # noqa: PLR0912, PLR0914, PLR0915
+def _load_model_schema(
     input_model: str,
     input_file_type: InputFileType,
     ref_strategy: InputModelRefStrategy | None = None,

Based on static analysis hints.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16f27ef and a99405b.

📒 Files selected for processing (13)
  • docs/cli-reference/base-options.md
  • docs/cli-reference/index.md
  • docs/cli-reference/quick-reference.md
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/enums.py
  • src/datamodel_code_generator/parser/jsonschema.py
  • src/datamodel_code_generator/prompt_data.py
  • tests/data/python/input_model/dataclass_nested.py
  • tests/data/python/input_model/nested_models.py
  • tests/test_input_model.py
🧰 Additional context used
🧬 Code graph analysis (9)
src/datamodel_code_generator/enums.py (1)
src/datamodel_code_generator/model/enum.py (1)
  • Enum (39-121)
src/datamodel_code_generator/arguments.py (1)
src/datamodel_code_generator/enums.py (1)
  • InputModelRefStrategy (199-210)
tests/data/python/input_model/dataclass_nested.py (2)
src/datamodel_code_generator/model/enum.py (1)
  • Enum (39-121)
src/datamodel_code_generator/model/base.py (1)
  • name (827-829)
tests/test_input_model.py (1)
src/datamodel_code_generator/__main__.py (2)
  • main (1355-1658)
  • Exit (124-130)
src/datamodel_code_generator/__init__.py (1)
src/datamodel_code_generator/enums.py (1)
  • InputModelRefStrategy (199-210)
src/datamodel_code_generator/parser/jsonschema.py (3)
src/datamodel_code_generator/reference.py (4)
  • get (983-985)
  • reference (76-78)
  • add_ref (805-828)
  • add (906-981)
src/datamodel_code_generator/imports.py (2)
  • Import (20-38)
  • from_full_path (35-38)
src/datamodel_code_generator/types.py (2)
  • imports (482-536)
  • from_import (358-382)
tests/data/python/input_model/nested_models.py (3)
src/datamodel_code_generator/model/enum.py (1)
  • Enum (39-121)
src/datamodel_code_generator/model/typed_dict.py (1)
  • key (131-135)
src/datamodel_code_generator/model/base.py (1)
  • name (827-829)
src/datamodel_code_generator/cli_options.py (1)
src/datamodel_code_generator/model/base.py (1)
  • name (827-829)
src/datamodel_code_generator/__main__.py (1)
src/datamodel_code_generator/enums.py (3)
  • InputModelRefStrategy (199-210)
  • DataModelType (48-56)
  • InputFileType (35-45)
🪛 GitHub Check: CodeQL
src/datamodel_code_generator/__main__.py

[notice] 797-797: Unused global variable
The global variable '_OUTPUT_TYPE_FAMILY' is not used.

🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

447-447: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)


688-688: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


714-714: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


715-715: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


716-716: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


809-809: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


810-810: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


872-872: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)

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: 3.13 on Windows
🔇 Additional comments (13)
docs/cli-reference/index.md (1)

11-11: LGTM! Documentation properly updated for new option.

The Base Options count is correctly incremented to 7, and the new --input-model-ref-strategy option is properly added to the alphabetical index in the correct position.

Also applies to: 110-110

tests/data/python/input_model/dataclass_nested.py (1)

1-31: LGTM! Well-structured test data for dataclass nesting.

This test data file provides clear examples of nested types (Enum + dataclasses) for exercising the --input-model-ref-strategy feature. The structure is clean with proper type hints and descriptive docstrings explaining the purpose of each component.

tests/data/python/input_model/nested_models.py (1)

1-40: LGTM! Excellent test data for mixed model types.

This file provides comprehensive test coverage by mixing three different model families (Enum, dataclass, BaseModel) in a single structure. The User model references all three types, which effectively exercises the different reuse strategies. The docstrings clearly explain the intended behavior for each strategy.

docs/cli-reference/quick-reference.md (1)

23-23: LGTM! Quick reference properly updated.

The new option is correctly added to both the Base Options table and the alphabetical index with a clear, concise description.

Also applies to: 256-256

src/datamodel_code_generator/enums.py (1)

199-211: LGTM! Well-defined enum with clear documentation.

The InputModelRefStrategy enum follows the established patterns in this module:

  • PascalCase member names with kebab-case string values
  • Comprehensive docstring explaining each strategy's purpose
  • Proper placement in the module and __all__ export list

Also applies to: 236-236

src/datamodel_code_generator/__init__.py (1)

42-42: LGTM! Proper public API exposure.

The InputModelRefStrategy enum is correctly imported from the enums module and added to the __all__ export list, maintaining alphabetical ordering in both locations. This properly exposes it as part of the package's public API.

Also applies to: 1059-1059

src/datamodel_code_generator/cli_options.py (1)

69-69: LGTM! CLI metadata properly registered.

The new option is correctly registered in the CLI metadata system with the appropriate category (BASE) and is logically placed next to the related --input-model option.

docs/cli-reference/base-options.md (1)

11-11: Documentation is accurate and well-written.

The documentation correctly identifies regenerate-all as the default strategy. This is confirmed by the argument parser help text ("If not specified, defaults to regenerate-all behavior") and the code logic, where None (the default argument value) results in RegenerateAll behavior since the special filtering is only applied when ref_strategy is explicitly set to a non-default value.

src/datamodel_code_generator/prompt_data.py (1)

66-66: New prompt description for --input-model-ref-strategy is consistent

The added OPTION_DESCRIPTIONS entry is concise and aligned with the CLI/help semantics of the new flag. No issues here.

src/datamodel_code_generator/arguments.py (1)

16-35: CLI wiring for --input-model-ref-strategy looks correct; verify default mapping

Importing InputModelRefStrategy and exposing --input-model-ref-strategy via base_options with choices=[s.value for s in InputModelRefStrategy] is consistent with how other enum-backed options are handled.

The help text says the behavior defaults to regenerate-all, while the argparse default is None. That’s fine as long as Config.input_model_ref_strategy or _load_model_schema maps None to InputModelRefStrategy.RegenerateAll internally. Please double-check that mapping so the documented default matches runtime behavior.

Also applies to: 167-176

src/datamodel_code_generator/__main__.py (3)

62-62: LGTM!

The import of InputModelRefStrategy is correctly added and used throughout the file.


830-869: LGTM!

The _filter_defs_by_strategy() function correctly implements the filtering logic:

  • RegenerateAll: No filtering (defensive check, though callers already exclude this case)
  • ReuseAll: All nested types marked for reuse with x-python-import
  • ReuseForeign: Only types from different families than the input model are marked for reuse

The implementation aligns with the documented strategy behaviors.


1585-1589: LGTM!

The call to _load_model_schema correctly passes config.input_model_ref_strategy, properly wiring the new configuration option through to the implementation.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.50%. Comparing base (16f27ef) to head (8d5fb5d).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2850    +/-   ##
========================================
  Coverage   99.50%   99.50%            
========================================
  Files          90       90            
  Lines       14489    14605   +116     
  Branches     1736     1748    +12     
========================================
+ Hits        14417    14533   +116     
  Misses         37       37            
  Partials       35       35            
Flag Coverage Δ
unittests 99.50% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a99405b and bb17d1f.

📒 Files selected for processing (13)
  • docs/cli-reference/base-options.md
  • docs/cli-reference/index.md
  • docs/cli-reference/quick-reference.md
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/enums.py
  • src/datamodel_code_generator/parser/jsonschema.py
  • src/datamodel_code_generator/prompt_data.py
  • tests/data/python/input_model/dataclass_nested.py
  • tests/data/python/input_model/nested_models.py
  • tests/test_input_model.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/datamodel_code_generator/init.py
  • tests/data/python/input_model/nested_models.py
  • tests/data/python/input_model/dataclass_nested.py
  • src/datamodel_code_generator/parser/jsonschema.py
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/enums.py
  • docs/cli-reference/quick-reference.md
  • src/datamodel_code_generator/prompt_data.py
  • docs/cli-reference/base-options.md
🧰 Additional context used
🧬 Code graph analysis (3)
src/datamodel_code_generator/arguments.py (1)
src/datamodel_code_generator/enums.py (1)
  • InputModelRefStrategy (199-210)
tests/test_input_model.py (1)
src/datamodel_code_generator/__main__.py (2)
  • main (1355-1658)
  • Exit (124-130)
src/datamodel_code_generator/__main__.py (1)
src/datamodel_code_generator/enums.py (2)
  • InputModelRefStrategy (199-210)
  • DataModelType (48-56)
🪛 GitHub Check: CodeQL
src/datamodel_code_generator/__main__.py

[notice] 797-797: Unused global variable
The global variable '_OUTPUT_TYPE_FAMILY' is not used.

🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

447-447: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)


688-688: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


714-714: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


715-715: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


716-716: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


809-809: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


810-810: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


872-872: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)

Remove unused noqa directive

(RUF100)

🔇 Additional comments (14)
docs/cli-reference/index.md (2)

11-11: LGTM! Documentation update is accurate.

The Base Options count has been correctly incremented from 6 to 7 to reflect the addition of the new --input-model-ref-strategy option.


110-110: LGTM! New option properly documented.

The new --input-model-ref-strategy option has been correctly added to the alphabetical index under section I, with proper formatting and link to the base-options documentation.

tests/test_input_model.py (2)

609-627: LGTM! Well-documented test with CLI documentation marker.

The test includes proper CLI documentation metadata via the @pytest.mark.cli_doc decorator, which helps generate user-facing documentation. The description clearly explains the three strategy options and their purposes.


628-803: LGTM! Comprehensive test coverage for the new feature.

The test suite thoroughly covers all three strategies (regenerate-all, reuse-foreign, reuse-all) with both positive assertions (what should be present) and negative assertions (what should NOT be regenerated). Tests also cover:

  • Multiple output model types (TypedDict, dataclass)
  • Edge cases (strategy without --input-model)
  • Different input model types (Pydantic models, dataclasses, TypedDict)

The use of helper functions like run_input_model_and_assert keeps tests concise and maintainable.

src/datamodel_code_generator/arguments.py (2)

26-26: LGTM! Import correctly added.

The InputModelRefStrategy enum is properly imported alongside other enums in the appropriate section.


167-176: LGTM! Well-designed CLI argument with clear documentation.

The new --input-model-ref-strategy option is properly implemented with:

  • Clear help text explaining all three strategies
  • Proper validation using enum values
  • Sensible default of None to distinguish unspecified from explicitly set

The help text effectively communicates the behavior of each strategy to users.

src/datamodel_code_generator/__main__.py (8)

62-62: LGTM! Import correctly added.

The InputModelRefStrategy import is properly placed with other enum imports from the main package.


447-447: LGTM! Config field properly added.

The input_model_ref_strategy field is correctly typed and positioned in the Config model.


686-727: LGTM! Enhanced type collection for ref strategy support.

The functions _collect_nested_models and _find_models_in_type have been properly extended to:

  • Collect Enum and dataclass types in addition to BaseModel subclasses
  • Recursively discover nested types in dataclass and TypedDict via type hints
  • Handle both Pydantic models (via model_fields) and dataclass/TypedDict (via annotations)

This enhancement is essential for the ref-strategy feature to identify which types can be reused vs. regenerated.


830-870: LGTM! Core strategy logic correctly implemented.

The _filter_defs_by_strategy function properly implements the three strategies:

  1. RegenerateAll: Returns schema unchanged (all types regenerated)
  2. ReuseForeign: Marks types from different families with x-python-import for reuse
  3. ReuseAll: Marks all nested types with x-python-import for reuse

The logic correctly:

  • Preserves unknown types (not in nested_models)
  • Determines type families and applies strategy rules
  • Uses x-python-import annotation with module and name for import generation

872-876: LGTM! Function signature properly updated.

The _load_model_schema function signature correctly adds the optional ref_strategy parameter with proper type hints and documentation.


954-964: LGTM! Pydantic model path correctly implements ref strategy.

The code properly:

  1. Adds x-python-type information for type preservation
  2. Only applies strategy filtering when a non-RegenerateAll strategy is specified
  3. Collects nested models including the main model if present in $defs
  4. Determines input family and applies the filter

982-996: LGTM! Dataclass/TypedDict path correctly implements ref strategy.

Parallel to the Pydantic path, this properly:

  1. Adds x-python-type information via the generic function
  2. Applies strategy filtering when specified
  3. Handles both dataclass and TypedDict as obj_type

The implementation is consistent with the Pydantic path.


1585-1589: LGTM! Main function correctly wires the ref strategy.

The main function properly passes config.input_model_ref_strategy to _load_model_schema, completing the end-to-end flow from CLI argument to schema loading logic.

Comment thread src/datamodel_code_generator/__main__.py
@koxudaxi koxudaxi force-pushed the feature/input-model-ref-strategy branch 2 times, most recently from 0523e20 to 9212c59 Compare December 29, 2025 04:24
@koxudaxi koxudaxi force-pushed the feature/input-model-ref-strategy branch from 69711cc to ddf21d3 Compare December 29, 2025 04:33
@koxudaxi koxudaxi merged commit 055f8ed into main Dec 29, 2025
38 checks passed
@koxudaxi koxudaxi deleted the feature/input-model-ref-strategy branch December 29, 2025 04:56
@github-actions
Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: No breaking changes detected

Reasoning: This PR is purely additive - it introduces a new optional CLI option --input-model-ref-strategy with three choices (regenerate-all, reuse-foreign, reuse-all). When the option is not specified, the behavior defaults to regenerate-all which matches the existing behavior before this PR. The new InputModelRefStrategy enum is added to the public API exports, but this is additive. No existing CLI options, default behaviors, or generated code output changes unless users explicitly opt-in by using the new option.


This analysis was performed by Claude Code Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 1, 2026

🎉 Released in 0.51.0

This PR is now available in the latest release. See the release notes for details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants