Skip to content

Add --input-model option for Pydantic models and dicts#2804

Merged
koxudaxi merged 28 commits intomainfrom
feature/input-model-option
Dec 26, 2025
Merged

Add --input-model option for Pydantic models and dicts#2804
koxudaxi merged 28 commits intomainfrom
feature/input-model-option

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Dec 25, 2025

Summary by CodeRabbit

  • New Features

    • Added --input-model to import Python types or dict schemas (MODULE:NAME) as an input source.
  • Behavior & Validation

    • Supports Pydantic v2, dataclasses, TypedDict and dict schemas; dict imports require explicit file type.
    • --input-model must not be combined with --input or --url and is incompatible with --watch.
    • Improved error messages for missing/invalid imports and incompatible flags.
  • Tests

    • New comprehensive test suite for supported inputs and error cases.
  • Documentation

    • CLI reference, quick-reference, and new Python model guide updated.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 25, 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 8 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 44040cd and 998797c.

📒 Files selected for processing (4)
  • README.md
  • docs/index.md
  • docs/python-model.md
  • zensical.toml
📝 Walkthrough

Walkthrough

Adds a new CLI option --input-model and runtime support to import a Python module:attr (dict schema, Pydantic v2 BaseModel, dataclass, or TypedDict), convert/validate it to JSON schema, feed that schema into the generation pipeline, and enforce mutual-exclusion/compatibility with --input, --url, and --watch.

Changes

Cohort / File(s) Summary of changes (attention areas)
Core CLI & loader
src/datamodel_code_generator/__main__.py
Added Config.input_model: Optional[str]. Added _load_model_schema(input_model, input_file_type) -> dict to import/validate module:attr (dict, Pydantic v2 BaseModel, dataclass, TypedDict), normalize to JSON schema, wire into input resolution, and enforce mutual-exclusion and error messages (with --input/--url/--watch).
Argument parsing & metadata
src/datamodel_code_generator/arguments.py, src/datamodel_code_generator/cli_options.py, src/datamodel_code_generator/prompt_data.py
Introduced --input-model CLI option (metavar MODULE:NAME, help text), added CLI metadata and prompt description. Parser/metadata note: requires --input-file-type for raw dict inputs and disallows --input/--url when used.
Tests & fixtures
tests/test_input_model.py
New comprehensive tests exercising Pydantic v2, pydantic dataclasses, stdlib dataclasses, TypedDicts, dict/OpenAPI schemas, and many error conditions; adds autouse reset_namespace fixture.
Documentation & references
docs/python-model.md, docs/cli-reference/*.md, docs/index.md
New docs page and updated CLI reference/quick-reference/index to include --input-model, examples, supported types, and mutual-exclusion guidance.
Test sample modules
tests/data/python/input_model/*
Added example modules used by tests: pydantic_models.py, pydantic_dataclass_models.py, dataclass_models.py, typeddict_models.py, dict_schemas.py, and __init__.py.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CLI as CLI
  participant Importer as Module Importer
  participant Normalizer as Schema Normalizer
  participant Generator as Code Generator

  CLI->>Importer: receive --input-model (module:Name)
  Importer-->>CLI: import attribute (dict / dataclass / TypedDict / Pydantic v2 BaseModel)
  alt imported is dict or OpenAPI spec
    Importer->>Normalizer: validate/verify dict (may require --input-file-type)
    Normalizer-->>Generator: provide JSON schema (tagged JsonSchema)
  else imported is Pydantic v2 BaseModel / pydantic dataclass
    Importer->>Normalizer: call model.model_json_schema() / extract schema
    Normalizer-->>Generator: provide JSON schema (tagged JsonSchema)
  end
  CLI->>Generator: invoke generate() with JSON-serialized schema input
  Generator-->>CLI: generation result / exit code
  Note right of CLI: Errors if used with `--input` / `--url` or together with `--watch`
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

breaking-change-analyzed

"I hopped through imports with joy so spry,
Pulled schemas from modules, up to the sky.
Turned models to JSON, neat and bright,
Fed them to the generator — code takes flight! 🐇✨"

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a new --input-model CLI option that supports Pydantic models and dict schemas as input sources.
Docstring Coverage ✅ Passed Docstring coverage is 90.48% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

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

🧹 Nitpick comments (5)
src/datamodel_code_generator/__main__.py (5)

445-445: Remove unused noqa directive.

Static analysis indicates the noqa: UP045 directive is unused and should be removed.

🔎 Proposed fix
-    input_model: Optional[str] = None  # noqa: UP045
+    input_model: Optional[str] = None

594-649: Well-implemented schema loading function.

The _load_model_schema function properly handles:

  • Format validation for the module:name syntax
  • Import error handling with clear messages
  • Support for both dict and Pydantic v2 BaseModel inputs
  • Appropriate validation for input_file_type compatibility
  • Detection of Pydantic v1 models with helpful error messages

The dynamic import is acceptable in this CLI context where users control the input.

However, line 610 has an unused noqa directive that should be removed:

🔎 Proposed fix for unused noqa
-    import importlib  # noqa: PLC0415
+    import importlib

1024-1030: LGTM on logic, but clean up unused noqa directives.

The updated error message correctly includes --input-model as an alternative input source. The logic properly validates that at least one input source is provided.

However, static analysis flags unused noqa directives on lines 1025-1026 that should be removed:

🔎 Proposed fix
-    if not config.input and not config.url and not config.input_model and sys.stdin.isatty():
-        print(  # noqa: T201
-            "Not Found Input: require `stdin` or arguments `--input`, `--url`, or `--input-model`",
+    if not config.input and not config.url and not config.input_model and sys.stdin.isatty():
+        print(
+            "Not Found Input: require `stdin` or arguments `--input`, `--url`, or `--input-model`",
             file=sys.stderr,
         )

1032-1037: Correct mutual exclusion check.

The validation properly prevents using --input-model together with --input or --url, which would be conflicting input sources. The error message is clear.

However, line 1033 has an unused noqa directive:

🔎 Proposed fix
     if config.input_model and (config.input or config.url):
-        print(  # noqa: T201
-            "Error: --input-model cannot be used with --input or --url",
+        print(
+            "Error: --input-model cannot be used with --input or --url",
             file=sys.stderr,
         )

1053-1058: Correct mutual exclusion check for watch mode.

Preventing --watch with --input-model is appropriate since watch mode monitors file changes, which doesn't apply to Python import paths. The error message is clear.

However, line 1054 has an unused noqa directive:

🔎 Proposed fix
     if config.watch and config.input_model:
-        print(  # noqa: T201
-            "Error: --watch cannot be used with --input-model",
+        print(
+            "Error: --watch cannot be used with --input-model",
             file=sys.stderr,
         )
📜 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 355a344 and c45ba71.

📒 Files selected for processing (4)
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.py
  • tests/test_input_model.py
🧰 Additional context used
🧬 Code graph analysis (2)
src/datamodel_code_generator/__main__.py (3)
src/datamodel_code_generator/enums.py (1)
  • InputFileType (35-45)
src/datamodel_code_generator/__init__.py (1)
  • Error (224-233)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
  • BaseModel (162-342)
tests/test_input_model.py (1)
src/datamodel_code_generator/__main__.py (2)
  • Exit (123-129)
  • main (965-1254)
🪛 GitHub Actions: Lint
tests/test_input_model.py

[warning] 1-1: ruff-format reformatted 1 file during pre-commit hooks. Some changes were made automatically.


[error] 327-327: ARG002 Unused method argument: tmp_path (from ruff).

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

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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


1025-1025: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1033-1033: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1054-1054: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)

tests/test_input_model.py

328-328: Unused method argument: tmp_path

(ARG002)

⏰ 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). (20)
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: py312-black23 on Ubuntu
  • GitHub Check: 3.14 on macOS
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: 3.12 on macOS
  • GitHub Check: 3.14 on Windows
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.12 on Windows
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.13 on Ubuntu
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: Analyze (python)
  • GitHub Check: benchmarks
🔇 Additional comments (7)
src/datamodel_code_generator/cli_options.py (1)

66-66: LGTM!

The CLI option metadata entry for --input-model is correctly categorized under BASE and follows the established pattern for other input options.

src/datamodel_code_generator/arguments.py (1)

159-166: LGTM!

The --input-model argument is well-defined with clear help text that explains:

  • The expected format (module.path:ObjectName)
  • Support for Pydantic v2 models and schema dicts
  • The requirement for --input-file-type when using dicts
  • Mutual exclusion constraints
src/datamodel_code_generator/__main__.py (1)

1183-1190: Clean integration of input-model flow.

The logic correctly:

  • Loads the schema via _load_model_schema when --input-model is provided
  • Serializes the schema to JSON for downstream processing
  • Auto-detects and sets input_file_type to JsonSchema when appropriate
  • Maintains backwards compatibility with the existing input flow
tests/test_input_model.py (4)

17-37: Well-designed test fixtures.

The fixtures provide:

  • reset_namespace: Ensures clean state between tests by resetting the global namespace (autouse is appropriate here)
  • pydantic_model_module: Creates a reusable temporary module with a Pydantic model for testing

40-149: Comprehensive Pydantic model tests.

The test class thoroughly validates:

  • Basic usage with Pydantic models
  • Output format variations (TypedDict)
  • Explicit input-file-type specification
  • Error handling for incompatible input-file-type

Tests properly manage sys.path and sys.modules for cleanup, ensuring isolation.


151-270: Thorough dict input tests.

The test class validates:

  • Dict input with required --input-file-type
  • Error when --input-file-type is omitted
  • OpenAPI spec handling

Good practice using uuid for unique module names to prevent test collisions.


362-438: Comprehensive mutual exclusion tests.

The test class validates all mutual exclusion scenarios:

  • --input-model with --input
  • --input-model with --url
  • --input-model with --watch

Each test properly verifies both the exit code and error message content, ensuring the feature behaves as documented.

Comment thread tests/test_input_model.py Outdated
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 25, 2025

CodSpeed Performance Report

Merging #2804 will not alter performance

Comparing feature/input-model-option (998797c) with main (64f7a8b)

Summary

✅ 73 untouched
⏩ 10 skipped1

Footnotes

  1. 10 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.

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 (2)
tests/test_input_model.py (2)

45-144: Well-structured test coverage for Pydantic models.

The test class comprehensively covers the happy path, output model transformation, explicit input-file-type handling, and error scenarios. The consistent try-finally cleanup pattern ensures proper resource management.

Minor observation: Some tests explicitly check output_file.exists() before reading (line 67), while others don't (line 92). While not a bug, consistent existence checks improve test clarity.


53-64: Consider extracting the sys.path manipulation pattern.

The sys.path insert/cleanup pattern is repeated across 10+ tests. While the explicit approach aids readability, a context manager could reduce duplication and ensure consistency.

💡 Example context manager approach
from contextlib import contextmanager

@contextmanager
def module_in_path(module_path: Path, module_name: str):
    """Temporarily add module to sys.path and clean up."""
    sys.path.insert(0, str(module_path))
    try:
        yield
    finally:
        sys.path.remove(str(module_path))
        sys.modules.pop(module_name, None)

Usage:

with module_in_path(pydantic_model_module, "test_pydantic_models"):
    exit_code = main([...])

Also applies to: 76-89, 99-112, 126-139, 170-186, 201-214, 247-262, 329-349, 366-377, 389-400, 413-425

📜 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 c45ba71 and 48a7e16.

📒 Files selected for processing (1)
  • tests/test_input_model.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). (20)
  • GitHub Check: 3.11 on macOS
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.12 on macOS
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.12 on Windows
  • GitHub Check: py312-black23 on Ubuntu
  • GitHub Check: 3.10 on macOS
  • GitHub Check: 3.13 on Ubuntu
  • GitHub Check: 3.13 on Windows
  • GitHub Check: 3.13 on macOS
  • GitHub Check: Analyze (python)
  • GitHub Check: benchmarks
🔇 Additional comments (4)
tests/test_input_model.py (4)

20-43: Excellent fixture design for test isolation.

The reset_namespace autouse fixture ensures clean state between tests, and pydantic_model_module provides a reusable test model. The pattern of returning the parent directory for sys.path manipulation is correct.


146-267: Strong test coverage for dict-based schemas with smart collision avoidance.

The UUID-based module naming (lines 154, 195, 225) effectively prevents test collisions and makes parallel execution safe. The use of importlib.invalidate_caches() ensures proper module loading after dynamic file creation.


269-354: Comprehensive error handling with creative test approach.

The error test suite covers all failure modes effectively. The Pydantic v1 simulation (lines 333-340) using monkeypatch to hide model_json_schema is a clever approach to testing version compatibility without requiring Pydantic v1 installation.

Note: The unused tmp_path parameter issue from the previous review has been correctly resolved in the current code.


356-429: Thorough mutual exclusion validation.

The tests correctly verify that --input-model conflicts with --input, --url, and --watch. The defensive approach of setting up sys.path even for expected failures ensures the tests would catch validation bypasses.

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

🧹 Nitpick comments (1)
src/datamodel_code_generator/cli_options.py (1)

47-55: Consider alphabetical ordering for better maintainability.

While the order doesn't affect functionality (frozensets are unordered), maintaining alphabetical order in the literal would improve code readability and make it easier to spot duplicates or missing entries.

🔎 Proposed refactor for alphabetical ordering
 MANUAL_DOCS: frozenset[str] = frozenset({
+    "--debug",
+    "--generate-prompt",
     "--help",
-    "--version",
-    "--debug",
-    "--profile",
+    "--input-model",
     "--no-color",
-    "--generate-prompt",
-    "--input-model",
+    "--profile",
+    "--version",
 })
📜 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 48a7e16 and 6cef10e.

📒 Files selected for processing (2)
  • src/datamodel_code_generator/cli_options.py
  • tests/test_input_model.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_input_model.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). (20)
  • GitHub Check: 3.11 on Windows
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: py312-black23 on Ubuntu
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.13 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: Analyze (python)
  • GitHub Check: benchmarks

Comment thread src/datamodel_code_generator/cli_options.py Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.52%. Comparing base (25053ac) to head (998797c).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2804    +/-   ##
========================================
  Coverage   99.51%   99.52%            
========================================
  Files          89       90     +1     
  Lines       13855    14090   +235     
  Branches     1634     1658    +24     
========================================
+ Hits        13788    14023   +235     
  Misses         36       36            
  Partials       31       31            
Flag Coverage Δ
unittests 99.52% <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: 0

♻️ Duplicate comments (1)
src/datamodel_code_generator/cli_options.py (1)

54-54: Past review issue remains unresolved: Manual documentation file is still missing.

The previous review correctly identified that docs/cli-reference/manual/input-model.md is missing. Since --input-model is included in MANUAL_DOCS, the corresponding hand-written documentation file must be created to complete this feature addition.

🧹 Nitpick comments (5)
src/datamodel_code_generator/__main__.py (5)

445-445: Clean up unused noqa directive.

Static analysis correctly identifies that the # noqa: UP045 directive is unused and can be removed.

🔎 Proposed fix
-    input_model: Optional[str] = None  # noqa: UP045
+    input_model: Optional[str] = None

612-612: Remove unused noqa directive.

The # noqa: PLC0415 directive is unnecessary. Import statements within functions are acceptable in this context.

🔎 Proposed fix
-    import importlib  # noqa: PLC0415
+    import importlib

1028-1034: Clean up unused noqa directive.

The # noqa: T201 directive on line 1029 is unused and can be removed.

🔎 Proposed fix
     if not config.input and not config.url and not config.input_model and sys.stdin.isatty():
-        print(  # noqa: T201
+        print(
             "Not Found Input: require `stdin` or arguments `--input`, `--url`, or `--input-model`",
             file=sys.stderr,
         )

1036-1042: Mutual exclusion validation is correct; clean up noqa directive.

The validation correctly prevents conflicting input sources. However, the # noqa: T201 directive on line 1037 is unused.

🔎 Proposed fix
     if config.input_model and (config.input or config.url):
-        print(  # noqa: T201
+        print(
             "Error: --input-model cannot be used with --input or --url",
             file=sys.stderr,
         )

1057-1063: Watch prevention is appropriate; clean up noqa directive.

Correctly prevents --watch with --input-model since watch mode is designed for file monitoring. The # noqa: T201 directive on line 1058 is unused.

🔎 Proposed fix
     if config.watch and config.input_model:
-        print(  # noqa: T201
+        print(
             "Error: --watch cannot be used with --input-model",
             file=sys.stderr,
         )
📜 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 6cef10e and afbc253.

📒 Files selected for processing (3)
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/datamodel_code_generator/arguments.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/datamodel_code_generator/__main__.py (3)
src/datamodel_code_generator/enums.py (1)
  • InputFileType (35-45)
src/datamodel_code_generator/__init__.py (1)
  • Error (224-233)
src/datamodel_code_generator/model/pydantic/base_model.py (1)
  • BaseModel (331-420)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


1029-1029: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1037-1037: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1058-1058: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)

🔇 Additional comments (2)
src/datamodel_code_generator/__main__.py (2)

596-652: Acknowledge the security trade-off of dynamic imports.

The function uses importlib.import_module() to dynamically load user-specified Python modules. This executes arbitrary code from the specified module path. While this is acceptable for a CLI tool where users control the input, be aware that this design trusts the user-provided --input-model argument.

The implementation is well-structured with comprehensive error handling for invalid formats, import failures, missing attributes, and unsupported types. The distinction between dict and Pydantic v2 BaseModel with appropriate input_file_type validation is correct.


1187-1195: Input resolution logic is well-implemented.

The implementation correctly:

  • Loads the schema via _load_model_schema when --input-model is provided
  • Serializes the schema to JSON for the generator
  • Sets input_file_type to JsonSchema when auto-detecting
  • Preserves existing behavior for other input sources

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: 6

📜 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 afbc253 and a8e67ee.

📒 Files selected for processing (6)
  • docs/cli-reference/base-options.md
  • docs/cli-reference/index.md
  • docs/cli-reference/quick-reference.md
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/prompt_data.py
  • tests/test_input_model.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). (1)
  • GitHub Check: benchmarks
🔇 Additional comments (7)
docs/cli-reference/index.md (1)

11-11: LGTM!

The Base Options count is correctly updated to 6, and the --input-model entry is properly added in alphabetical order in section I.

Also applies to: 108-108

src/datamodel_code_generator/cli_options.py (1)

68-68: LGTM!

The --input-model option is correctly added to CLI_OPTION_META under the BASE category, consistent with other input/output options.

tests/test_input_model.py (5)

26-31: LGTM!

The reset_namespace autouse fixture ensures a clean state for each test by resetting the global namespace, preventing test pollution.


51-150: Well-structured Pydantic model tests.

Good coverage of the main use cases including output type conversion and input-file-type handling. The cleanup in finally blocks properly removes the temporary module from both sys.path and sys.modules.


152-273: Good dict input test coverage.

The use of uuid.uuid4().hex[:8] for unique module names prevents test interference. Tests cover both success cases (with proper --input-file-type) and error cases (missing --input-file-type), as well as OpenAPI dict input.


275-367: Thorough error handling tests.

All error paths are covered with appropriate assertions on exit codes and error messages. The Pydantic v1 simulation using monkeypatch on builtins.hasattr is a clever approach to test version compatibility without requiring Pydantic v1.


369-442: Complete mutual exclusion tests.

All mutual exclusion scenarios are covered:

  • --input-model with --input
  • --input-model with --url
  • --input-model with --watch

Each test properly verifies the exit code and error message.

Comment thread docs/cli-reference/base-options.md Outdated
Comment thread docs/cli-reference/base-options.md
Comment thread docs/cli-reference/quick-reference.md Outdated
Comment thread docs/cli-reference/quick-reference.md Outdated
Comment thread src/datamodel_code_generator/prompt_data.py Outdated
Comment thread tests/test_input_model.py Outdated
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 (5)
src/datamodel_code_generator/__main__.py (5)

445-445: Remove unused noqa directive.

The # noqa: UP045 directive appears to be unnecessary based on static analysis. Consider removing it unless the UP045 rule is conditionally enabled in specific environments.

🔎 Proposed fix
-    input_model: Optional[str] = None  # noqa: UP045
+    input_model: Optional[str] = None

596-651: Well-designed schema loader with comprehensive validation.

The function properly handles both dict schemas and Pydantic v2 models, with clear error messages for each failure mode. The isinstance(obj, type) check before issubclass prevents potential TypeErrors.

One minor cleanup:

🔎 Remove unused noqa directive
-    import importlib  # noqa: PLC0415
+    import importlib

1028-1034: LGTM: Input validation properly includes --input-model.

The validation logic correctly checks for the new --input-model option and the error message helpfully lists all input methods.

Minor cleanup - the noqa directive appears unnecessary:

🔎 Remove unused noqa directive
-        print(  # noqa: T201
+        print(
             "Not Found Input: require `stdin` or arguments `--input`, `--url`, or `--input-model`",
             file=sys.stderr,
         )

1036-1041: LGTM: Proper mutual exclusion enforcement.

The validation correctly prevents using --input-model with --input or --url.

Minor cleanup:

🔎 Remove unused noqa directive
-        print(  # noqa: T201
+        print(
             "Error: --input-model cannot be used with --input or --url",
             file=sys.stderr,
         )

1057-1062: LGTM: Watch incompatibility properly enforced.

The validation correctly prevents using --watch with --input-model, which makes sense since watch monitors file changes.

Minor cleanup:

🔎 Remove unused noqa directive
-        print(  # noqa: T201
+        print(
             "Error: --watch cannot be used with --input-model",
             file=sys.stderr,
         )
📜 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 1f52b17 and 6f3e1c1.

📒 Files selected for processing (2)
  • src/datamodel_code_generator/__main__.py
  • tests/test_input_model.py
🧰 Additional context used
🧬 Code graph analysis (2)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/enums.py (1)
  • InputFileType (35-45)
src/datamodel_code_generator/__init__.py (1)
  • Error (297-306)
tests/test_input_model.py (2)
tests/data/expected/main/openapi/const_pydantic_v2.py (1)
  • Namespace (12-14)
src/datamodel_code_generator/__main__.py (2)
  • Exit (123-129)
  • main (969-1258)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


1029-1029: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1037-1037: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1058-1058: Unused noqa directive (non-enabled: T201)

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). (20)
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: 3.13 on Windows
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: 3.11 on Windows
  • GitHub Check: py312-black23 on Ubuntu
  • GitHub Check: 3.10 on macOS
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.12 on macOS
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.13 on Ubuntu
  • GitHub Check: benchmarks
  • GitHub Check: Analyze (python)
🔇 Additional comments (23)
tests/test_input_model.py (22)

1-25: LGTM: Clean test module setup.

The imports and conditional skip marker for Pydantic v1 are well-structured.


27-53: LGTM: Well-designed test helpers.

The assertion helpers use __tracebackhide__ appropriately and provide clear error messages for test failures.


55-96: LGTM: Effective test runner helpers.

These functions reduce duplication and make the test cases more concise and maintainable.


98-103: LGTM: Proper test isolation.

The autouse fixture correctly resets the global namespace to ensure test isolation.


106-125: LGTM: Robust fixture with proper cleanup.

The fixture correctly manages sys.path and sys.modules, ensuring proper cleanup in the finally block.


128-148: LGTM: Consistent fixture pattern.

The dict schema fixture follows the same robust pattern as the Pydantic model fixture.


151-177: LGTM: OpenAPI fixture is well-structured.

The OpenAPI spec dict is valid and the fixture maintains consistency with the other module fixtures.


185-201: LGTM: Core functionality test with proper documentation.

The test covers the basic use case and the docstring is appropriate for auto-generated CLI documentation.


204-215: LGTM: Tests output model type compatibility.

The test verifies that --input-model works correctly with --output-model-type.


218-228: LGTM: Tests explicit input file type.

The test ensures that explicitly specifying --input-file-type jsonschema works with Pydantic models.


231-243: LGTM: Validates input file type constraint.

The test ensures Pydantic models can only be used with jsonschema input file type.


251-260: LGTM: Tests dict schema with jsonschema type.

The test correctly validates that dict schemas work with --input-file-type jsonschema.


263-274: LGTM: Validates required type for dict schemas.

The test ensures that dict schemas require an explicit --input-file-type.


277-287: LGTM: Tests OpenAPI dict schema.

The test validates that OpenAPI specs can be loaded as dicts via --input-model.


295-301: LGTM: Tests invalid format error.

The test ensures proper validation of the module:Name format.


304-310: LGTM: Tests missing module error.

The test validates error handling when the specified module cannot be imported.


313-319: LGTM: Tests missing attribute error.

The test validates error handling when the specified attribute doesn't exist in the module.


322-328: LGTM: Tests unsupported type error.

The test ensures proper error handling for objects that are neither dicts nor Pydantic models.


331-355: LGTM: Clever test for Pydantic v1 detection.

The use of monkeypatch to simulate a Pydantic v1 model (lacking model_json_schema) is an elegant testing approach.


363-375: LGTM: Tests mutual exclusion with --input.

The test validates that --input-model and --input cannot be used together.


378-389: LGTM: Tests mutual exclusion with --url.

The test validates that --input-model and --url cannot be used together.


392-404: LGTM: Tests watch incompatibility.

The test validates that --input-model cannot be used with --watch.

src/datamodel_code_generator/__main__.py (1)

1187-1194: LGTM: Clean integration of input-model loading.

The logic properly loads the schema, serializes it to JSON, and sets the appropriate input file type. The fallback to existing input sources is well-structured.

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

♻️ Duplicate comments (2)
docs/cli-reference/base-options.md (2)

228-234: Usage example violates mutual exclusion rule.

The usage example combines --input schema.json with --input-model mymodule:MyModel, but according to the documentation in docs/python-model.md (lines 158-164) and the PR objectives, --input-model is mutually exclusive with --input and --url.

🔎 Proposed fix
 !!! tip "Usage"
 
     ```bash
-    datamodel-codegen --input schema.json --input-model mymodule:MyModel # (1)!
+    datamodel-codegen --input-model mymodule:MyModel --output output.py # (1)!
     ```
 
     1. :material-arrow-left: `--input-model` - the option documented here

236-239: Examples section is empty.

The Examples section contains only an "Output:" heading with no actual example content. This should include a concrete example showing input (e.g., a simple Pydantic model) and the corresponding generated output.

🔎 Suggested example content

Consider adding an example similar to the ones in docs/python-model.md, such as:

 ??? example "Examples"
 
+    **Input (mymodule.py):**
+
+    ```python
+    from pydantic import BaseModel
+
+    class User(BaseModel):
+        name: str
+        age: int
+    ```
+
+    **Command:**
+
+    ```bash
+    datamodel-codegen --input-model mymodule:User --output model.py
+    ```
+
     **Output:**
+
+    ```python
+    from __future__ import annotations
+
+    from pydantic import BaseModel
+
+
+    class User(BaseModel):
+        name: str
+        age: int
+    ```
🧹 Nitpick comments (3)
tests/test_input_model.py (1)

303-309: Fragile mock condition for import interception.

The check "TypeAdapter" in str(args) relies on the string representation of the args tuple, which is brittle. The fromlist parameter is typically the third positional argument. A more robust check would inspect the actual structure:

🔎 More robust mock implementation
     def mock_import(name: str, *args: object, **kwargs: object) -> object:
-        if name == "pydantic" and "TypeAdapter" in str(args):
+        # fromlist is typically args[2] when called via 'from X import Y'
+        fromlist = args[2] if len(args) > 2 else kwargs.get("fromlist", [])
+        if name == "pydantic" and fromlist and "TypeAdapter" in fromlist:
             msg = "mocked import error"
             raise ImportError(msg)
         return original_import(name, *args, **kwargs)
src/datamodel_code_generator/__main__.py (2)

445-445: Remove unused noqa directive.

Static analysis indicates the # noqa: UP045 directive on this line is unused.

🔎 Proposed fix
-    input_model: Optional[str] = None  # noqa: UP045
+    input_model: Optional[str] = None

596-672: Well-structured schema loading with proper type handling.

The _load_model_schema function correctly handles:

  • Format validation with clear error messages
  • Dict inputs requiring explicit --input-file-type
  • Pydantic v2 models via model_json_schema()
  • dataclass/TypedDict via TypeAdapter
  • Runtime Pydantic version detection

Per static analysis, several # noqa: PLC0415 directives on lines 612, 651, and 663 are unused and can be removed for cleaner code.

🔎 Remove unused noqa directives
-    import importlib  # noqa: PLC0415
+    import importlib
     ...
-    from dataclasses import is_dataclass  # noqa: PLC0415
+    from dataclasses import is_dataclass
     ...
-            from pydantic import TypeAdapter  # noqa: PLC0415
+            from pydantic import TypeAdapter
📜 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 6f3e1c1 and ba4080c.

📒 Files selected for processing (13)
  • docs/cli-reference/base-options.md
  • docs/cli-reference/quick-reference.md
  • docs/index.md
  • docs/python-model.md
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/prompt_data.py
  • tests/data/python/input_model/__init__.py
  • tests/data/python/input_model/dataclass_models.py
  • tests/data/python/input_model/dict_schemas.py
  • tests/data/python/input_model/pydantic_dataclass_models.py
  • tests/data/python/input_model/pydantic_models.py
  • tests/data/python/input_model/typeddict_models.py
  • tests/test_input_model.py
✅ Files skipped from review due to trivial changes (2)
  • tests/data/python/input_model/dict_schemas.py
  • tests/data/python/input_model/init.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/cli-reference/quick-reference.md
🧰 Additional context used
🧬 Code graph analysis (4)
tests/data/python/input_model/pydantic_models.py (4)
tests/data/python/input_model/dataclass_models.py (1)
  • User (7-11)
tests/data/python/input_model/pydantic_dataclass_models.py (1)
  • User (7-11)
tests/data/python/input_model/typeddict_models.py (1)
  • User (6-10)
src/datamodel_code_generator/model/base.py (1)
  • name (826-828)
tests/data/python/input_model/pydantic_dataclass_models.py (4)
tests/data/python/input_model/dataclass_models.py (1)
  • User (7-11)
tests/data/python/input_model/pydantic_models.py (1)
  • User (6-10)
tests/data/python/input_model/typeddict_models.py (1)
  • User (6-10)
src/datamodel_code_generator/model/base.py (1)
  • name (826-828)
tests/data/python/input_model/typeddict_models.py (1)
src/datamodel_code_generator/model/typed_dict.py (1)
  • TypedDict (47-112)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/enums.py (1)
  • InputFileType (35-45)
src/datamodel_code_generator/__init__.py (1)
  • Error (297-306)
🪛 LanguageTool
docs/python-model.md

[style] ~119-~119: Using many exclamation marks might seem excessive (in this case: 6 exclamation marks for a text that’s 1984 characters long)
Context: ...-type jsonschema --output model.py ``` !!! warning "Dict requires --input-file-typ...

(EN_EXCESSIVE_EXCLAMATION)

🪛 markdownlint-cli2 (0.18.1)
docs/python-model.md

28-28: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


41-41: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


59-59: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


73-73: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


89-89: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


104-104: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


125-125: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

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

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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


1049-1049: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1057-1057: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1078-1078: Unused noqa directive (non-enabled: T201)

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: py312-black23 on Ubuntu
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.13 on Windows
  • GitHub Check: 3.14 on Windows
  • GitHub Check: benchmarks
🔇 Additional comments (12)
docs/python-model.md (1)

1-172: Comprehensive documentation for the new feature.

The documentation is well-structured, covering all essential aspects: quick start, supported input types, multiple examples for different model types, formatting guidelines, and mutual exclusion rules. The use of bold text for labeling code examples and MkDocs admonitions is appropriate.

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

1-11: LGTM! Test fixture is consistent with other input-model test data.

The Pydantic dataclass structure follows the same pattern as the related test files (dataclass_models.py, pydantic_models.py, typeddict_models.py), providing appropriate test coverage for the --input-model feature.

docs/index.md (1)

97-97: LGTM! Table entry clearly documents the new Python Models input type.

The row addition is consistent with the existing table structure and accurately links to the new python-model.md documentation. The file type and description appropriately summarize the supported input types.

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

1-10: LGTM! Test fixture follows consistent pattern.

The TypedDict structure matches the pattern established in related test files (dataclass_models.py, pydantic_models.py, pydantic_dataclass_models.py), providing comprehensive coverage for different input model types.

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

1-10: LGTM! Test fixture is well-structured.

The Pydantic BaseModel follows the established pattern across the input_model test data files, providing consistent test coverage for the new --input-model feature.

src/datamodel_code_generator/prompt_data.py (1)

64-64: LGTM! Option description is clear and accurate.

The description "Import a Python type (Pydantic, dataclass, TypedDict) or dict schema from a module." accurately summarizes the --input-model option and is consistent with the documentation across other files.

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

1-11: LGTM! Test fixture uses standard library dataclass appropriately.

The dataclass structure is consistent with the other input_model test files and uses only the Python standard library, making it a good baseline test case for the --input-model feature.

tests/test_input_model.py (3)

1-23: LGTM on imports and skip marker.

The module structure is clean, with appropriate imports and a well-defined SKIP_PYDANTIC_V1 marker that correctly uses version comparison to conditionally skip Pydantic v2-specific tests.


96-102: LGTM on the reset_namespace fixture.

Using autouse=True with monkeypatch properly ensures test isolation by resetting the global namespace before each test, with automatic cleanup after.


104-356: Comprehensive test coverage for the --input-model option.

The tests provide excellent coverage across:

  • Multiple input types (Pydantic models, dicts, dataclasses, TypedDicts)
  • Error scenarios (invalid format, missing modules, unsupported types)
  • Mutual exclusion checks with --input, --url, and --watch
  • Pydantic v1/v2 runtime detection

The use of SKIP_PYDANTIC_V1 appropriately guards v2-specific tests.

src/datamodel_code_generator/__main__.py (2)

1048-1082: Input validation and mutual exclusion logic is correct.

The validation properly:

  • Includes --input-model in the "Not Found Input" check
  • Prevents combining --input-model with --input or --url
  • Disallows --watch with --input-model (watching a Python module is not meaningful)

Static analysis notes unused # noqa: T201 directives on lines 1049, 1057, and 1078 which can be cleaned up.


1207-1218: LGTM on input resolution logic.

The input handling correctly:

  1. Loads the schema via _load_model_schema()
  2. Serializes to JSON string for the generator pipeline
  3. Auto-sets input_file_type to JsonSchema when Auto (for non-dict types)
  4. Falls back to existing url/input/stdin behavior when input_model is not specified

Comment thread tests/test_input_model.py
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 (2)
tests/test_input_model.py (2)

269-317: Consider more robust mock implementations.

The mock functions work but rely on fragile techniques:

  • Line 282: Identity check obj is pydantic_models.User could fail if modules are reloaded
  • Line 306: String matching "TypeAdapter" in str(args) is imprecise for import arguments
🔎 More robust mock approaches

For the hasattr mock (lines 281-284), consider checking the class name and module:

def mock_hasattr(obj: object, name: str) -> bool:
    if name == "model_json_schema" and (
        type(obj).__name__ == "User" 
        and type(obj).__module__ == "tests.data.python.input_model.pydantic_models"
    ):
        return False
    return original_hasattr(obj, name)

For the import mock (lines 305-309), consider checking the fromlist more precisely:

def mock_import(name: str, *args: object, **kwargs: object) -> object:
    fromlist = kwargs.get("fromlist", args[3] if len(args) > 3 else ())
    if name == "pydantic" and fromlist and "TypeAdapter" in fromlist:
        msg = "mocked import error"
        raise ImportError(msg)
    return original_import(name, *args, **kwargs)

233-266: Consider additional edge case tests.

The error handling tests are solid, but could be enhanced with additional edge cases for malformed --input-model arguments:

  • Empty module: :ClassName
  • Empty attribute: module:
  • Multiple colons: module:nested:ClassName
  • Whitespace: module : ClassName or leading/trailing spaces
🔎 Example edge case tests
def test_input_model_empty_module(capsys: pytest.CaptureFixture[str]) -> None:
    """Test error when module name is empty."""
    run_input_model_error_and_assert(
        input_model=":ClassName",
        capsys=capsys,
        expected_stderr_contains="Invalid --input-model format",
    )

def test_input_model_empty_attribute(capsys: pytest.CaptureFixture[str]) -> None:
    """Test error when attribute name is empty."""
    run_input_model_error_and_assert(
        input_model="module:",
        capsys=capsys,
        expected_stderr_contains="Invalid --input-model format",
    )
📜 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 2aeea50 and b3d602d.

📒 Files selected for processing (1)
  • tests/test_input_model.py
🔇 Additional comments (2)
tests/test_input_model.py (2)

25-103: Excellent test infrastructure design.

The helper functions and fixtures are well-structured:

  • Proper use of __tracebackhide__ for cleaner pytest output
  • Guards for file existence and content checks are correctly implemented (lines 70-76)
  • The reset_namespace autouse fixture prevents test pollution

106-216: Comprehensive coverage of input types.

The test suite thoroughly validates all supported input types (Pydantic models, dataclasses, TypedDict, and dict schemas) with clear, consistent test patterns. The CLI documentation marker is appropriately placed on the basic usage test.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 26, 2025

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 (1)
src/datamodel_code_generator/__main__.py (1)

445-445: Consider removing unused noqa directives.

Static analysis reports several unused noqa directives (RUF100). These are low-priority cleanup items that don't affect functionality.

🔎 Lines with unused noqa directives
  • Line 445: UP045
  • Line 596: PLR0912, PLR0915
  • Line 612: PLC0415
  • Line 613: PLC0415
  • Line 678: PLC0415
  • Line 690: PLC0415
  • Line 1076: T201
  • Line 1084: T201
  • Line 1105: T201

You can remove these if they're not needed in your CI environment, or keep them if they suppress warnings in specific tooling configurations.

Also applies to: 596-596, 612-613, 678-678, 690-690, 1076-1076, 1084-1084, 1105-1105

📜 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 b3d602d and 44040cd.

📒 Files selected for processing (7)
  • docs/cli-reference/base-options.md
  • docs/cli-reference/quick-reference.md
  • docs/python-model.md
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/prompt_data.py
  • tests/test_input_model.py
✅ Files skipped from review due to trivial changes (1)
  • docs/cli-reference/base-options.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/datamodel_code_generator/arguments.py
🧰 Additional context used
🧬 Code graph analysis (1)
tests/test_input_model.py (2)
src/datamodel_code_generator/__main__.py (2)
  • Exit (123-129)
  • main (1016-1305)
src/datamodel_code_generator/__init__.py (1)
  • chdir (245-255)
🪛 LanguageTool
docs/python-model.md

[style] ~168-~168: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 2094 characters long)
Context: ...work without additional configuration. !!! tip "File and package name conflict" ...

(EN_EXCESSIVE_EXCLAMATION)

🪛 markdownlint-cli2 (0.18.1)
docs/python-model.md

28-28: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


41-41: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


59-59: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


73-73: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


89-89: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


104-104: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


125-125: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

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

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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


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

Remove unused noqa directive

(RUF100)


1076-1076: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1084-1084: Unused noqa directive (non-enabled: T201)

Remove unused noqa directive

(RUF100)


1105-1105: Unused noqa directive (non-enabled: T201)

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). (20)
  • GitHub Check: 3.13 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: py312-black23 on Ubuntu
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.12 on macOS
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: 3.13 on macOS
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: 3.13 on Windows
  • GitHub Check: Analyze (python)
🔇 Additional comments (10)
src/datamodel_code_generator/prompt_data.py (1)

64-64: LGTM!

The description accurately reflects the --input-model option's functionality and format requirements.

docs/python-model.md (1)

1-189: LGTM!

The documentation is comprehensive, accurate, and well-structured. It covers all supported input types, provides clear examples, and documents important constraints like mutual exclusion with other input options.

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

22-22: LGTM!

Both entries for --input-model (in the Base Options table and Alphabetical Index) are consistent and accurately describe the option's functionality.

Also applies to: 248-248

tests/test_input_model.py (3)

25-93: LGTM!

The helper functions are well-designed with proper use of __tracebackhide__ for cleaner pytest output and clear separation of concerns for success and error cases.


95-101: LGTM!

The reset_namespace autouse fixture properly prevents test pollution by resetting global namespace state before each test.


103-461: LGTM!

The test suite is comprehensive and well-structured, covering:

  • All supported input types (Pydantic, dataclass, TypedDict, dict schemas)
  • Conversion between output types
  • All error cases (invalid format, missing modules/attributes, unsupported types)
  • Mutual exclusion constraints
  • Path format variations

The use of SKIP_PYDANTIC_V1 marker appropriately guards tests requiring Pydantic v2, and past review issues have been addressed.

src/datamodel_code_generator/__main__.py (4)

445-445: LGTM!

The input_model field is properly added to the Config model with correct typing.


596-699: LGTM!

The _load_model_schema function is well-implemented with:

  • Clear format parsing and validation
  • Proper distinction between file paths and module imports
  • Comprehensive error handling for all failure modes
  • Runtime checks for Pydantic v2 availability
  • Clear, actionable error messages

1075-1110: LGTM!

The validation logic correctly enforces mutual exclusion constraints and provides clear error messages when --input-model is used with incompatible options.


1234-1242: LGTM!

The input resolution logic correctly handles the --input-model pathway by loading the schema, serializing it to JSON, and defaulting the input file type to JsonSchema when needed, while preserving existing behavior for other input sources.

koxudaxi and others added 3 commits December 26, 2025 17:06
- Move Format section to top for quick reference
- Emphasize path format (./file.py:Object) as recommended approach
- Update all examples to use path format for easy copy-paste
- Add Python Models page to left navigation under Input Formats

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@koxudaxi koxudaxi enabled auto-merge (squash) December 26, 2025 18:13
@koxudaxi koxudaxi merged commit 12fdab5 into main Dec 26, 2025
58 of 62 checks passed
@koxudaxi koxudaxi deleted the feature/input-model-option branch December 26, 2025 18:16
@github-actions
Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: No breaking changes detected

Reasoning: This PR adds a new CLI option (--input-model) that allows users to import Python types or dict schemas as input sources. The change is purely additive: 1) No existing CLI options were modified or removed, 2) No changes to generated code output, 3) No template changes required, 4) No default behavior changes - all existing workflows continue to work identically, 5) No Python version support dropped, 6) The error message update is just help text that now lists the additional input option. The new mutual exclusion rules (--input-model cannot be combined with --input, --url, or --watch) only apply when using the new option, not affecting any existing usage patterns.


This analysis was performed by Claude Code Action

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.

1 participant