Add deprecation registry and docs#3188
Conversation
📝 WalkthroughWalkthroughAdds a central deprecation registry with rendering/warning helpers, a CLI flag ChangesDeprecation Infrastructure and CLI
Sequence DiagramsequenceDiagram
participant User
participant CLI as arguments.py/__main__.py
participant Registry as deprecations.py
participant Docs as scripts/build_deprecation_docs.py
User->>CLI: run --list-deprecations [format]
CLI->>Registry: render_deprecations(format)
Registry-->>CLI: formatted output
CLI-->>User: print output and exit
Docs->>Registry: render_release_note_deprecations(version)
Registry-->>Docs: release-note snippets
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Merging this PR will not alter performance
|
|
📚 Docs Preview: https://pr-3188.datamodel-code-generator.pages.dev |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3188 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 93 96 +3
Lines 20197 20365 +168
Branches 2364 2376 +12
==========================================
+ Hits 20197 20365 +168
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
scripts/build_deprecation_docs.py (1)
33-39: ⚡ Quick winNormalize content before check/write to avoid false mismatches.
Line 33 currently compares raw text, so newline-only differences can fail
--check. Normalize both sides (e.g.,rstrip() + "\n") before comparing/writing, similar to the approach inscripts/build_cli_docs.py.🤖 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 `@scripts/build_deprecation_docs.py` around lines 33 - 39, Normalize the content read from DOCS_PATH and the generated content before comparing and before writing to disk to avoid newline-only mismatches: when checking existence and equality use something like normalized_existing = DOCS_PATH.read_text(encoding="utf-8").rstrip() + "\n" and normalized_new = content.rstrip() + "\n" (same approach as scripts/build_cli_docs.py), compare those normalized strings for the if-check, and when writing call DOCS_PATH.write_text(normalized_new, encoding="utf-8") so the check and write use the same canonical form; keep using DOCS_PATH, content, read_text(), and write_text() from the diff.tests/main/test_main_general.py (1)
123-130: ⚡ Quick winParse
--list-deprecations jsonoutput before asserting content.Line 129 currently checks a raw substring only. Parsing first catches malformed/non-JSON output regressions.
✅ Proposed test hardening
+import json ... def test_list_deprecations_json(capsys: pytest.CaptureFixture[str]) -> None: """List registered deprecations as JSON.""" run_main_with_args(["--list-deprecations", "json"]) captured = capsys.readouterr() - assert '"id": "cli.parent-scoped-naming"' in captured.out + payload = json.loads(captured.out) + assert "cli.parent-scoped-naming" in json.dumps(payload) assert not captured.err🤖 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 123 - 130, The test_list_deprecations_json should parse the program output as JSON before asserting contents: after calling run_main_with_args(...) and capturing via capsys, call json.loads on captured.out (importing json at top if needed) to ensure valid JSON, then assert the presence of the deprecation id (e.g. check any(item.get("id") == "cli.parent-scoped-naming" for item in parsed) or access the expected key in the parsed dict/list) and still assert not captured.err; this will make the test fail on malformed/non-JSON output rather than silently passing on substring matches.
🤖 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 `@docs/cli-reference/openapi-only-options.md`:
- Line 1726: The deprecation note for the `--validation` CLI option is missing
the migration hint; update the sentence that currently reads "**Deprecated:**
The `--validation` option is deprecated and will be removed in a future
release." to append a replacement path so it becomes self-contained (e.g., add
"Use `--field-constraints` instead"), ensuring the detailed section includes the
actionable guidance about migrating from `--validation` to
`--field-constraints`.
In `@docs/cli-reference/utility-options.md`:
- Around line 117-121: Replace the fenced triple-backtick code block in the "new
usage" block with an indented code block to satisfy markdownlint MD046: remove
the ```bash fences and indent each command line (e.g., "datamodel-codegen
--list-deprecations", "datamodel-codegen --list-deprecations json",
"datamodel-codegen --list-deprecations markdown") with four spaces so the
commands remain shown but use the indented style expected by the docs linter.
---
Nitpick comments:
In `@scripts/build_deprecation_docs.py`:
- Around line 33-39: Normalize the content read from DOCS_PATH and the generated
content before comparing and before writing to disk to avoid newline-only
mismatches: when checking existence and equality use something like
normalized_existing = DOCS_PATH.read_text(encoding="utf-8").rstrip() + "\n" and
normalized_new = content.rstrip() + "\n" (same approach as
scripts/build_cli_docs.py), compare those normalized strings for the if-check,
and when writing call DOCS_PATH.write_text(normalized_new, encoding="utf-8") so
the check and write use the same canonical form; keep using DOCS_PATH, content,
read_text(), and write_text() from the diff.
In `@tests/main/test_main_general.py`:
- Around line 123-130: The test_list_deprecations_json should parse the program
output as JSON before asserting contents: after calling run_main_with_args(...)
and capturing via capsys, call json.loads on captured.out (importing json at top
if needed) to ensure valid JSON, then assert the presence of the deprecation id
(e.g. check any(item.get("id") == "cli.parent-scoped-naming" for item in parsed)
or access the expected key in the parsed dict/list) and still assert not
captured.err; this will make the test fail on malformed/non-JSON output rather
than silently passing on substring matches.
🪄 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: d5408a22-784e-403a-a29d-e0ce74bda783
⛔ Files ignored due to path filters (9)
docs/llms-full.txtis excluded by none and included by nonedocs/llms.txtis excluded by none and included by nonetests/data/expected/main/help/color.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main/help/no_color.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/generate_prompt/basic.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/generate_prompt/with_list_options.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/generate_prompt/with_options.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/generate_prompt/with_question.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/help_shows_new_options.txtis excluded by!tests/data/**/*.txtand included by none
📒 Files selected for processing (23)
docs/cli-reference/index.mddocs/cli-reference/manual/list-deprecations.mddocs/cli-reference/model-customization.mddocs/cli-reference/openapi-only-options.mddocs/cli-reference/quick-reference.mddocs/cli-reference/utility-options.mddocs/deprecations.mdpyproject.tomlscripts/build_cli_docs.pyscripts/build_deprecation_docs.pysrc/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/arguments.pysrc/datamodel_code_generator/cli_options.pysrc/datamodel_code_generator/deprecations.pysrc/datamodel_code_generator/format.pysrc/datamodel_code_generator/parser/jsonschema.pysrc/datamodel_code_generator/parser/openapi.pysrc/datamodel_code_generator/util.pytests/main/test_main_general.pytests/test_build_deprecation_docs_script.pytests/test_deprecations.pytox.inizensical.toml
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/datamodel_code_generator/deprecations.py (1)
245-253: ⚡ Quick winConsider escaping pipe characters in markdown table cells.
The table generation directly interpolates values that could theoretically contain pipe characters
|, which would break the markdown table structure. While the current data doesn't contain pipes, adding escaping would prevent future issues.🛡️ Proposed defensive escaping
+def _escape_markdown_pipe(text: str) -> str: + """Escape pipe characters for markdown table cells.""" + return text.replace("|", "\\|") + def render_deprecations_markdown(*, include_header: bool = True) -> str: """Render all deprecations as Markdown.""" lines: list[str] = [] # ... existing code ... for deprecation in iter_deprecations(): - replacement = deprecation.replacement or "-" + replacement = _escape_markdown_pipe(deprecation.replacement) if deprecation.replacement else "-" lines.append( f"| `{deprecation.id}` | {deprecation.kind} | `{deprecation.target}` | " f"{deprecation.warning_since} | {_format_removal_version(deprecation)} | {replacement} |" )Note: Values wrapped in backticks (like
deprecation.idanddeprecation.target) are already safe from pipe interpretation in most markdown renderers, so only the unwrappedreplacementfield needs escaping.🤖 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/deprecations.py` around lines 245 - 253, The markdown table generation in iter_deprecations() concatenates fields (notably deprecation.replacement and other unwrapped fields like deprecation.warning_since/_format_removal_version(...)) without escaping pipe characters, which can break the table; update the logic before lines.append in the loop to escape any '|' characters (e.g., replace '|' with '\|' or otherwise sanitize) for unwrapped cells (replacement, warning_since, removal text) while leaving backticked fields (deprecation.id, deprecation.target) unchanged, so the table remains valid even if future data contains pipes.
🤖 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 `@src/datamodel_code_generator/deprecations.py`:
- Around line 245-253: The markdown table generation in iter_deprecations()
concatenates fields (notably deprecation.replacement and other unwrapped fields
like deprecation.warning_since/_format_removal_version(...)) without escaping
pipe characters, which can break the table; update the logic before lines.append
in the loop to escape any '|' characters (e.g., replace '|' with '\|' or
otherwise sanitize) for unwrapped cells (replacement, warning_since, removal
text) while leaving backticked fields (deprecation.id, deprecation.target)
unchanged, so the table remains valid even if future data contains pipes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 93633ede-63ad-4fd6-9f85-b7f42dd48116
⛔ Files ignored due to path filters (5)
tests/data/expected/main_kr/generate_prompt/basic.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/generate_prompt/with_list_options.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/generate_prompt/with_options.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/generate_prompt/with_question.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/main_kr/help_shows_new_options.txtis excluded by!tests/data/**/*.txtand included by none
📒 Files selected for processing (1)
src/datamodel_code_generator/deprecations.py
Breaking Change AnalysisResult: No breaking changes detected Reasoning: This PR is a refactoring of deprecation warnings into a central registry with no breaking changes. It adds a new deprecations.py module and --list-deprecations CLI option (both purely additive). Existing deprecation warnings are re-routed through the new registry with the same warning categories and equivalent messages. No generated code output changes, no CLI options or Python API removed, no default behavior changes, no template updates required, and no Python version changes. This analysis was performed by Claude Code Action |
|
🎉 Released in 0.59.0 This PR is now available in the latest release. See the release notes for details. |
Summary by CodeRabbit
New Features
--list-deprecationsCLI option to list registered deprecations and scheduled breaking changes (table, JSON, or Markdown).Documentation
Tests
--list-deprecationsoutput and deprecation-docs/release-note generation.Chores