Skip to content

Fix generation reliability edge cases#3561

Merged
koxudaxi merged 10 commits into
mainfrom
fix-reliability-edge-cases
Jul 3, 2026
Merged

Fix generation reliability edge cases#3561
koxudaxi merged 10 commits into
mainfrom
fix-reliability-edge-cases

Conversation

@koxudaxi

@koxudaxi koxudaxi commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Fixes: #2381

Summary by CodeRabbit

  • New Features
    • Enhanced generate() string handling to better distinguish inline schema text from existing local paths (including unresolved ~ cases).
    • Improved --enable-command-header to redact sensitive HTTP header/query-parameter values in the emitted command.
  • Bug Fixes
    • Made CLI temporary-directory cleanup consistent across --check/diff and --watch exit paths.
    • Strengthened Ruff format/lint/check execution with clearer failure behavior and more reliable ruff discovery.
    • Improved Pydantic v2 BaseModel/RootModel config synchronization and rendering.
  • Tests
    • Added/updated golden-file, CLI header, and Ruff-focused tests for the new behaviors.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds string-path coercion in generate(), redacts sensitive values in emitted command headers, centralizes cleanup in main(), refactors Ruff subprocess execution and path resolution, and updates Pydantic v2 config propagation for BaseModel and RootModel.

Changes

String Path Input Handling

Layer / File(s) Summary
Schema-text detection and path coercion helper
src/datamodel_code_generator/__init__.py
Adds _SCHEMA_TEXT_START_CHARS and _coerce_existing_path_input() to convert eligible string inputs into Path objects while leaving schema text, URLs, and multiline strings unchanged.
Modular output writing refactor
src/datamodel_code_generator/__init__.py
Refactors _emit_results() to write modular output files via a context manager instead of manual open/close, and adjusts the noqa suppression list.
Tests and fixtures for path coercion behavior
tests/main/test_main_general.py, tests/data/expected/main/generate_accepts_string_path.py, tests/data/expected/main/generate_keeps_non_path_string_input.py, tests/data/expected/main/generate_keeps_unresolved_user_path_string_input.py
Adds tests and golden fixtures covering existing string paths, inline schema strings, and unresolved user-path strings.

CLI Command Header Redaction and Cleanup

Layer / File(s) Summary
Redaction constants and helper functions
src/datamodel_code_generator/__main__.py
Adds sensitive-option constants plus _redact_command_args() and _command_header() for redacted command-line output.
Cleanup helper wiring into main() flow
src/datamodel_code_generator/__main__.py
Adds cleanup_and_return(), uses the redacted command header in generation, and routes diff, error, watch, and normal exits through centralized cleanup.
Command header redaction test
tests/main/openapi/test_main_openapi.py
Adds a parametrized test that checks redaction of sensitive HTTP header and query parameter values in emitted command text.

Ruff Subprocess Execution Centralization

Layer / File(s) Summary
_run_ruff_command helper and callers
src/datamodel_code_generator/format.py
Adds _run_ruff_command() and updates Ruff lint/format/check paths to use it with encoded stdin and decoded stdout.
Ruff executable resolution change
src/datamodel_code_generator/format.py
Changes _find_ruff_path() to use shutil.which("ruff") and raises an install-hint error when Ruff is missing; format_directory() now uses the shared Ruff runner.
Ruff execution and path resolution tests
tests/test_format.py
Updates Ruff mocks to set returncode, and adds tests for non-zero exits, stdout-on-error behavior, and executable lookup outcomes.

Pydantic v2 Config Propagation

Layer / File(s) Summary
BaseModel config extraction
src/datamodel_code_generator/model/pydantic_v2/base_model.py
Updates _config_dict_items() to read config via model_dump() or dict(), and changes BaseModel.__init__ to merge config data from dict-like template data or converted config objects while cleaning up empty config template entries.
RootModel config sync and render
src/datamodel_code_generator/model/pydantic_v2/root_model.py, tests/model/pydantic_v2/test_root_model.py
Introduces RootModel config-key filtering and sync helpers, then updates render() to sync config items before templating and adds tests covering ConfigDict propagation and stale config-item rebuilding.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: safe-to-fix

Suggested reviewers: ilovelinux

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes unrelated changes for command-header redaction, Ruff execution, and Pydantic config/root-model rendering beyond the path-handling bug. Split the unrelated CLI, formatting, and model-rendering refactors into separate PRs or remove them from this fix.
Title check ❓ Inconclusive The title is related but too generic to clearly describe the main path-handling fix. Use a concise title that names the primary change, such as fixing string file-path handling in generate().
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The string-path handling bug from #2381 is addressed by coercing existing string paths and adding tests for path, inline, and unresolved inputs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-reliability-edge-cases

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.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

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

@codspeed-hq

codspeed-hq Bot commented Jul 3, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 17.85%

⚠️ 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.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 11 improved benchmarks
⏩ 98 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime test_perf_complex_refs 2 s 1.7 s +21.9%
WallTime test_perf_duplicate_names 1,048.6 ms 877.6 ms +19.48%
WallTime test_perf_multiple_files_input 3.6 s 3 s +19.41%
WallTime test_perf_deep_nested 5.2 s 4.3 s +19.06%
WallTime test_perf_openapi_large 3 s 2.5 s +18.85%
WallTime test_perf_large_models_pydantic_v2 3.5 s 3 s +17.81%
WallTime test_perf_all_options_enabled 5.4 s 4.6 s +17.67%
WallTime test_perf_aws_style_openapi_pydantic_v2 1.9 s 1.6 s +16.76%
WallTime test_perf_kubernetes_style_pydantic_v2 2.6 s 2.2 s +16.3%
WallTime test_perf_graphql_style_pydantic_v2 782.2 ms 674.4 ms +15.99%
WallTime test_perf_stripe_style_pydantic_v2 1.9 s 1.7 s +13.39%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix-reliability-edge-cases (a46d57b) with main (b5d167a)

Open in CodSpeed

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.

@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@b5d167a). Learn more about missing BASE report.
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main     #3561   +/-   ##
========================================
  Coverage        ?   100.00%           
========================================
  Files           ?       163           
  Lines           ?     34928           
  Branches        ?      4044           
========================================
  Hits            ?     34928           
  Misses          ?         0           
  Partials        ?         0           
Flag Coverage Δ
unittests 100.00% <100.00%> (?)

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

☔ View full report in Codecov by Harness.
📢 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/datamodel_code_generator/__main__.py (1)

191-227: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Redact --http-query-parameters in command headers.
SENSITIVE_COMMAND_OPTIONS only includes --http-headers, but the CLI also accepts --http-query-parameters, which can carry tokens or API keys. When --enable-command-header is enabled, those values will be written verbatim; add that option to the sensitive set.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/datamodel_code_generator/__main__.py` around lines 191 - 227, Add
--http-query-parameters to SENSITIVE_COMMAND_OPTIONS so _redact_command_args in
__main__.py treats it like --http-headers and redacts its values when command
headers are enabled. Update the sensitive option set near the redaction helpers
and ensure both the standalone option and the =value form are covered by the
existing redaction logic.
🧹 Nitpick comments (2)
tests/main/openapi/test_main_openapi.py (1)

1458-1469: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider simplifying the assertion pattern.

Two minor points on this test's tail:

  • Line 1459's next(...) has no default; if the # command: line is ever missing, this raises a bare StopIteration instead of a clear assertion failure.
  • Building a synthetic redacted=/secret_absent=/following_option_preserved= string and diffing it against a golden fixture via assert_output is more indirect than plain assert statements, and requires maintaining an extra fixture file for what is effectively three booleans.
♻️ Suggested simplification
-    content = output_file.read_text(encoding="utf-8")
-    command_line = next(line for line in content.splitlines() if line.startswith("#   command:"))
-    following_option_preserved = expected_visible is None or expected_visible in command_line
-    assert_output(
-        "\n".join([
-            f"redacted={'yes' if '<redacted>' in command_line else 'no'}",
-            f"secret_absent={'yes' if 'secret-token' not in command_line else 'no'}",
-            f"following_option_preserved={'yes' if following_option_preserved else 'no'}",
-        ])
-        + "\n",
-        EXPECTED_OPENAPI_PATH / "enable_command_header_redacts_http_headers.txt",
-    )
+    content = output_file.read_text(encoding="utf-8")
+    command_line = next(
+        (line for line in content.splitlines() if line.startswith("#   command:")), None
+    )
+    assert command_line is not None, "command header line not found in output"
+    assert "<redacted>" in command_line
+    assert "secret-token" not in command_line
+    if expected_visible is not None:
+        assert expected_visible in command_line

This is purely a test-clarity nit; the current logic is correct.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/main/openapi/test_main_openapi.py` around lines 1458 - 1469, The test
tail in test_main_openapi.py is overly indirect: update the command-line lookup
in the openapi header redaction test so a missing “#   command:” line fails with
a clear assertion instead of bare StopIteration, and replace the synthetic
status-string plus assert_output fixture check with direct assert statements for
redaction, secret absence, and following-option preservation. Keep the existing
intent in the same test function, but simplify the logic around content,
command_line, and following_option_preserved so the assertions are explicit and
no extra golden file is needed.
src/datamodel_code_generator/format.py (1)

537-563: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: parametrize the return type and reuse errors="replace" on success decode.

The helper is correct and the error-selection logic matches the accompanying tests. Two small polish items:

  • The return annotation subprocess.CompletedProcess is unparametrized; since capture_output=True yields bytes, subprocess.CompletedProcess[bytes] documents intent and satisfies stricter type-checking configs.
  • The failure path decodes with errors="replace", but the callers decode result.stdout without it; harmless for generated code, just noting the inconsistency.

The static-analysis S603 flag on Line 547 is a false positive here — the command tuple is constructed internally from resolved paths and fixed Ruff flags, not from request input, and is already suppressed via # noqa: S603.

♻️ Proposed annotation tweak
-    ) -> subprocess.CompletedProcess:
+    ) -> subprocess.CompletedProcess[bytes]:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/datamodel_code_generator/format.py` around lines 537 - 563, The
`_run_ruff_command` helper should use a parametrized return type and consistent
decoding behavior. Update the return annotation on `_run_ruff_command` to
reflect bytes output from `subprocess.run`, and reuse the same
`errors="replace"` decoding approach for any success-path stdout handling so the
typing and decode behavior stay aligned. Use the existing `_run_ruff_command`
symbol and keep the current error-selection logic unchanged.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/datamodel_code_generator/__init__.py`:
- Around line 764-778: The _coerce_existing_path_input helper can still fail on
unresolved user-home paths because Path.expanduser() may raise RuntimeError;
update the exception handling in _coerce_existing_path_input to also catch
RuntimeError alongside OSError and ValueError so it safely falls back to
returning the original input_ instead of crashing.

---

Outside diff comments:
In `@src/datamodel_code_generator/__main__.py`:
- Around line 191-227: Add --http-query-parameters to SENSITIVE_COMMAND_OPTIONS
so _redact_command_args in __main__.py treats it like --http-headers and redacts
its values when command headers are enabled. Update the sensitive option set
near the redaction helpers and ensure both the standalone option and the =value
form are covered by the existing redaction logic.

---

Nitpick comments:
In `@src/datamodel_code_generator/format.py`:
- Around line 537-563: The `_run_ruff_command` helper should use a parametrized
return type and consistent decoding behavior. Update the return annotation on
`_run_ruff_command` to reflect bytes output from `subprocess.run`, and reuse the
same `errors="replace"` decoding approach for any success-path stdout handling
so the typing and decode behavior stay aligned. Use the existing
`_run_ruff_command` symbol and keep the current error-selection logic unchanged.

In `@tests/main/openapi/test_main_openapi.py`:
- Around line 1458-1469: The test tail in test_main_openapi.py is overly
indirect: update the command-line lookup in the openapi header redaction test so
a missing “#   command:” line fails with a clear assertion instead of bare
StopIteration, and replace the synthetic status-string plus assert_output
fixture check with direct assert statements for redaction, secret absence, and
following-option preservation. Keep the existing intent in the same test
function, but simplify the logic around content, command_line, and
following_option_preserved so the assertions are explicit and no extra golden
file is needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1627d071-32da-4217-a606-1af23ae8690e

📥 Commits

Reviewing files that changed from the base of the PR and between 5cdacb4 and 4736008.

⛔ Files ignored due to path filters (1)
  • tests/data/expected/main/openapi/enable_command_header_redacts_http_headers.txt is excluded by !tests/data/**/*.txt and included by none
📒 Files selected for processing (8)
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/format.py
  • tests/data/expected/main/generate_accepts_string_path.py
  • tests/data/expected/main/generate_keeps_non_path_string_input.py
  • tests/main/openapi/test_main_openapi.py
  • tests/main/test_main_general.py
  • tests/test_format.py

Comment thread src/datamodel_code_generator/__init__.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/main/test_main_general.py (1)

2899-2917: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stale # pragma: no cover on the exercised except branch.

This test now covers the except (OSError, RuntimeError, ValueError) branch in _coerce_existing_path_input (src/datamodel_code_generator/__init__.py), which is currently marked # pragma: no cover. Consider removing that pragma so coverage reporting stays accurate now that the branch is tested.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/main/test_main_general.py` around lines 2899 - 2917, The new test
covers the exception path in _coerce_existing_path_input, so the stale # pragma:
no cover on the except (OSError, RuntimeError, ValueError) branch should be
removed. Update that branch in datamodel_code_generator.__init__ to no longer
exclude it from coverage, keeping the behavior unchanged while allowing the
exercised path to count in coverage reports.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/main/test_main_general.py`:
- Around line 2899-2917: The new test covers the exception path in
_coerce_existing_path_input, so the stale # pragma: no cover on the except
(OSError, RuntimeError, ValueError) branch should be removed. Update that branch
in datamodel_code_generator.__init__ to no longer exclude it from coverage,
keeping the behavior unchanged while allowing the exercised path to count in
coverage reports.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ee6b0359-7858-40fa-841c-af5a44e9d453

📥 Commits

Reviewing files that changed from the base of the PR and between 3361c73 and c627786.

📒 Files selected for processing (5)
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/format.py
  • tests/main/openapi/test_main_openapi.py
  • tests/main/test_main_general.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/datamodel_code_generator/init.py
  • tests/main/openapi/test_main_openapi.py
  • src/datamodel_code_generator/format.py
  • src/datamodel_code_generator/main.py

Comment thread src/datamodel_code_generator/model/pydantic_v2/root_model.py Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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/model/pydantic_v2/root_model.py (1)

106-109: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Undocumented side-effect: forcing fields[0].type_hint evaluation and discarding the result.

fields = self.fields if use_custom_template else self.rendered_fields
if fields:
    _ = fields[0].type_hint
self._sync_config_items()

Per the commit message this is meant to avoid "path monkeypatch leakage," but nothing here explains why evaluating (and discarding) the first field's type_hint before syncing config is necessary. Without a comment, a future refactor could easily drop this line and silently reintroduce the exact regression being fixed here.

📝 Suggested comment
         fields = self.fields if use_custom_template else self.rendered_fields
         if fields:
+            # Force type_hint resolution before any config sync so the underlying
+            # data-type resolution runs while `self.path` is still authoritative,
+            # avoiding stale/leaked path state from monkeypatching during rendering.
             _ = fields[0].type_hint
         self._sync_config_items()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/datamodel_code_generator/model/pydantic_v2/root_model.py` around lines
106 - 109, The RootModel sync flow in the method that selects `self.fields` or
`self.rendered_fields` and then calls `_sync_config_items()` relies on forcing
`fields[0].type_hint` evaluation for its side effect, but this is undocumented.
Add a concise comment next to that access in the `RootModel` logic explaining
that the first field’s `type_hint` must be realized before syncing config to
avoid path monkeypatch leakage, so future refactors don’t remove it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/datamodel_code_generator/model/pydantic_v2/root_model.py`:
- Around line 76-88: The `_sync_config_items()` logic in `RootModel` is
overwriting `extra_template_data["config"]` with a plain mapping, which breaks
templates that expect the original `ConfigDict` object. Update
`_sync_config_items()` so `config` remains the model/config object, and only
store the rendered key-value mapping in `_CONFIG_ITEMS_TEMPLATE_DATA_KEY`
(exposed as `config_items`). Keep the import/cache handling in sync with this
behavior inside `root_model.py`.

---

Nitpick comments:
In `@src/datamodel_code_generator/model/pydantic_v2/root_model.py`:
- Around line 106-109: The RootModel sync flow in the method that selects
`self.fields` or `self.rendered_fields` and then calls `_sync_config_items()`
relies on forcing `fields[0].type_hint` evaluation for its side effect, but this
is undocumented. Add a concise comment next to that access in the `RootModel`
logic explaining that the first field’s `type_hint` must be realized before
syncing config to avoid path monkeypatch leakage, so future refactors don’t
remove it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c1d7ba6f-c570-4a90-8fb7-acda26e5665c

📥 Commits

Reviewing files that changed from the base of the PR and between c627786 and e34ecfa.

📒 Files selected for processing (5)
  • src/datamodel_code_generator/model/pydantic_v2/base_model.py
  • src/datamodel_code_generator/model/pydantic_v2/root_model.py
  • tests/data/expected/main/generate_keeps_unresolved_user_path_string_input.py
  • tests/main/test_main_general.py
  • tests/model/pydantic_v2/test_root_model.py
✅ Files skipped from review due to trivial changes (1)
  • tests/data/expected/main/generate_keeps_unresolved_user_path_string_input.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/main/test_main_general.py

Comment thread src/datamodel_code_generator/model/pydantic_v2/root_model.py
@koxudaxi koxudaxi force-pushed the fix-reliability-edge-cases branch from e34ecfa to 712b980 Compare July 3, 2026 10:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/datamodel_code_generator/format.py`:
- Around line 554-555: The stdout fallback in the Ruff invocation path is too
broad because it accepts any non-zero exit with stdout as success. Update the
return handling in the formatting flow around the result check so stdout
fallback is only allowed when Ruff exits with code 1, and keep all other
non-zero codes as failures even if stdout is present. Use the existing result
handling in the formatting function to gate the fallback by the Ruff returncode.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3d91423a-e8d8-44d0-80d1-011b108f1883

📥 Commits

Reviewing files that changed from the base of the PR and between e34ecfa and 712b980.

⛔ Files ignored due to path filters (1)
  • tests/data/expected/main/openapi/enable_command_header_redacts_http_headers.txt is excluded by !tests/data/**/*.txt and included by none
📒 Files selected for processing (12)
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/format.py
  • src/datamodel_code_generator/model/pydantic_v2/base_model.py
  • src/datamodel_code_generator/model/pydantic_v2/root_model.py
  • tests/data/expected/main/generate_accepts_string_path.py
  • tests/data/expected/main/generate_keeps_non_path_string_input.py
  • tests/data/expected/main/generate_keeps_unresolved_user_path_string_input.py
  • tests/main/openapi/test_main_openapi.py
  • tests/main/test_main_general.py
  • tests/model/pydantic_v2/test_root_model.py
  • tests/test_format.py
✅ Files skipped from review due to trivial changes (2)
  • tests/data/expected/main/generate_keeps_non_path_string_input.py
  • tests/data/expected/main/generate_keeps_unresolved_user_path_string_input.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • tests/data/expected/main/generate_accepts_string_path.py
  • tests/model/pydantic_v2/test_root_model.py
  • tests/main/test_main_general.py
  • src/datamodel_code_generator/init.py
  • tests/test_format.py
  • src/datamodel_code_generator/model/pydantic_v2/base_model.py
  • tests/main/openapi/test_main_openapi.py
  • src/datamodel_code_generator/model/pydantic_v2/root_model.py
  • src/datamodel_code_generator/main.py

Comment thread src/datamodel_code_generator/format.py Outdated
@koxudaxi koxudaxi merged commit 730b494 into main Jul 3, 2026
60 checks passed
@koxudaxi koxudaxi deleted the fix-reliability-edge-cases branch July 3, 2026 10:53
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: Breaking changes detected

Reasoning: The diff introduces four observable behavior/output changes beyond internal refactoring. (1) Ruff subprocess failures and missing-ruff now raise RuntimeError where the removed lines show failures were previously ignored (check=False, stdout used unconditionally) — an Error Handling change. (2) The removed shlex.join(["datamodel-codegen", *args]) line is replaced with redaction of --http-headers/--http-query-parameters, changing the generated command-header output. (3) A new _coerce_existing_path_input call in generate() changes how string input_ is interpreted (existing paths read as files) — a Default Behavior change to the public API. (4) RootModel/base_model config handling now renders model_config from config objects previously dropped, changing generated pydantic v2 output. The remaining changes (temp_context cleanup refactor via cleanup_and_return, with-statement file handling, test additions) are behavior-preserving.

Content for Release Notes

Error Handling Changes

  • Ruff formatting failures now raise instead of being ignored - Ruff subprocess calls previously ran with check=False and used their stdout regardless of exit code, so a failed ruff run silently produced (possibly empty or partial) output. _run_ruff_command now raises RuntimeError when ruff exits non-zero (except the allowed check-with-remaining-diagnostics case), and _find_ruff_path raises a RuntimeError with an install hint when ruff is missing instead of falling back to "ruff". Workflows that relied on generation silently succeeding despite a ruff error will now fail with an exception. (Fix generation reliability edge cases #3561)

Code Generation Changes

  • --enable-command-header now redacts sensitive HTTP options - When --enable-command-header is combined with --http-headers or --http-query-parameters, the reproducibility command line embedded in generated files now writes <redacted> in place of those values instead of the literal arguments. Generated file headers change for these flag combinations, so committed output or snapshot tests will differ. (Fix generation reliability edge cases #3561)
  • RootModel config rendering for config objects - Pydantic v2 RootModel now synchronizes and renders model_config derived from config objects (e.g. regex_engine, frozen) that were previously dropped, and non-dict config objects are now applied in the base model. Generated output for affected pydantic v2 root models may now include a model_config = ConfigDict(...) that was not emitted before. (Fix generation reliability edge cases #3561)

Default Behavior Changes

  • generate() reads existing-path string inputs as files - The generate() Python API now coerces a str input_ into a Path and reads it as a local schema file when the string resolves to an existing filesystem path. Strings starting with {, [, <, containing ://, or containing newlines are still treated as inline source text, but a single-line string that happens to match an existing file/path is now loaded from disk rather than parsed as inline content, changing how ambiguous string inputs are interpreted. (Fix generation reliability edge cases #3561)

This analysis was performed by Claude Code Action

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🎉 Released in 0.68.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.

Bug: Path Handling Error - Schema File Paths as Strings - Pydantic

2 participants