Add Pydantic missing sentinel option#3510
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Changes--use-missing-sentinel feature
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 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 |
|
📚 Docs Preview: https://pr-3510.datamodel-code-generator.pages.dev |
Merging this PR will improve performance by ×2.2
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | test_perf_graphql_style_pydantic_v2 |
820.4 ms | 363.2 ms | ×2.3 |
| ⚡ | WallTime | test_perf_aws_style_openapi_pydantic_v2 |
1,957.7 ms | 873.6 ms | ×2.2 |
| ⚡ | WallTime | test_perf_all_options_enabled |
5.4 s | 2.4 s | ×2.2 |
| ⚡ | WallTime | test_perf_duplicate_names |
1,036.5 ms | 468.5 ms | ×2.2 |
| ⚡ | WallTime | test_perf_kubernetes_style_pydantic_v2 |
2.7 s | 1.2 s | ×2.2 |
| ⚡ | WallTime | test_perf_complex_refs |
2,015.1 ms | 916.1 ms | ×2.2 |
| ⚡ | WallTime | test_perf_large_models_pydantic_v2 |
3.5 s | 1.6 s | ×2.2 |
| ⚡ | WallTime | test_perf_openapi_large |
3 s | 1.4 s | ×2.2 |
| ⚡ | WallTime | test_perf_deep_nested |
5.1 s | 2.4 s | ×2.2 |
| ⚡ | WallTime | test_perf_multiple_files_input |
3.5 s | 1.6 s | ×2.2 |
| ⚡ | WallTime | test_perf_stripe_style_pydantic_v2 |
1,949.7 ms | 915.4 ms | ×2.1 |
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 pydantic-missing-sentinel (e76a8c3) with main (1870d87)
Footnotes
-
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. ↩
5589d32 to
1de6600
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3510 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 153 154 +1
Lines 33896 34018 +122
Branches 3967 3984 +17
==========================================
+ Hits 33896 34018 +122
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
36ccde0 to
938d291
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/model/pydantic_v2/test_config.py (1)
129-129: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAvoid deprecated
.dict()in new test code.
.dict()on a Pydantic v2 model is deprecated in favor ofmodel_dump(). The repo already has an open issue tracking migration off deprecated Pydantic v2 methods; adding new usages works against that effort and will emitPydanticDeprecatedSince20warnings during the test run.♻️ Suggested fix
- config = model.extra_template_data["config"].dict(exclude_unset=True) + config = model.extra_template_data["config"].model_dump(exclude_unset=True)🤖 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/model/pydantic_v2/test_config.py` at line 129, The test is still calling the deprecated Pydantic v2 .dict() method on model.extra_template_data["config"], which adds a new deprecated usage in test code. Update this assertion/setup in the pydantic_v2 config test to use model_dump() with the same exclude_unset behavior instead, and keep the change localized to the config-related test path.
🤖 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/model/pydantic_v2/test_config.py`:
- Line 129: The test is still calling the deprecated Pydantic v2 .dict() method
on model.extra_template_data["config"], which adds a new deprecated usage in
test code. Update this assertion/setup in the pydantic_v2 config test to use
model_dump() with the same exclude_unset behavior instead, and keep the change
localized to the config-related test path.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 15ea86c4-8c7f-4fdf-a3dd-4704ab9a4128
⛔ Files ignored due to path filters (12)
docs/llms-full.txtis excluded by none and included by noneskills/datamodel-code-generator/references/cli-options.mdis 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/json_output.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 nonetests/data/expected/prompt/default_parser_text.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/jsonschema/missing_sentinel.jsonis excluded by!tests/data/**/*.jsonand included by none
📒 Files selected for processing (31)
docs/architecture.mddocs/cli-reference/index.mddocs/cli-reference/model-customization.mddocs/cli-reference/quick-reference.mdsrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dicts.pysrc/datamodel_code_generator/arguments.pysrc/datamodel_code_generator/base_config.pysrc/datamodel_code_generator/cli_options.pysrc/datamodel_code_generator/config.pysrc/datamodel_code_generator/enums.pysrc/datamodel_code_generator/model/base.pysrc/datamodel_code_generator/model/pydantic_base.pysrc/datamodel_code_generator/model/pydantic_v2/_config.pysrc/datamodel_code_generator/model/pydantic_v2/base_model.pysrc/datamodel_code_generator/model/pydantic_v2/imports.pysrc/datamodel_code_generator/parser/base.pysrc/datamodel_code_generator/parser/graphql.pysrc/datamodel_code_generator/parser/jsonschema.pysrc/datamodel_code_generator/parser/openapi.pysrc/datamodel_code_generator/prompt_data.pytests/data/expected/main/input_model/config_class.pytests/data/expected/main/jsonschema/missing_sentinel.pytests/data/expected/main/jsonschema/missing_sentinel_no_union_operator.pytests/main/jsonschema/test_main_jsonschema.pytests/main/test_public_api_signature_baseline.pytests/model/pydantic_v2/test_config.pytests/model/test_base.pytests/test_enums.pytests/test_main_kr.py
✅ Files skipped from review due to trivial changes (7)
- src/datamodel_code_generator/model/pydantic_base.py
- docs/cli-reference/quick-reference.md
- tests/test_main_kr.py
- docs/architecture.md
- tests/data/expected/main/jsonschema/missing_sentinel.py
- docs/cli-reference/index.md
- docs/cli-reference/model-customization.md
🚧 Files skipped from review as they are similar to previous changes (22)
- src/datamodel_code_generator/_types/generate_config_dict.py
- src/datamodel_code_generator/model/base.py
- src/datamodel_code_generator/config.py
- src/datamodel_code_generator/model/pydantic_v2/imports.py
- tests/data/expected/main/jsonschema/missing_sentinel_no_union_operator.py
- src/datamodel_code_generator/_types/parser_config_dicts.py
- src/datamodel_code_generator/model/pydantic_v2/_config.py
- src/datamodel_code_generator/parser/openapi.py
- src/datamodel_code_generator/arguments.py
- src/datamodel_code_generator/cli_options.py
- src/datamodel_code_generator/parser/graphql.py
- src/datamodel_code_generator/prompt_data.py
- tests/model/test_base.py
- tests/main/test_public_api_signature_baseline.py
- src/datamodel_code_generator/parser/base.py
- tests/data/expected/main/input_model/config_class.py
- tests/main/jsonschema/test_main_jsonschema.py
- src/datamodel_code_generator/init.py
- src/datamodel_code_generator/enums.py
- src/datamodel_code_generator/base_config.py
- src/datamodel_code_generator/parser/jsonschema.py
- src/datamodel_code_generator/model/pydantic_v2/base_model.py
938d291 to
8eaaa14
Compare
There was a problem hiding this comment.
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/model/pydantic_v2/base_model.py`:
- Around line 253-258: The fall-back logic in the `fall_back_to_nullable`
property on `BaseModel` is dropping schema-level nullability when
`use_missing_sentinel_default` is enabled. Update this override so it still
honors `field.nullable` from `JsonSchemaParser.get_object_field()` (not just
`type_has_null`), preserving `None` in annotations for OpenAPI 3.0 nullable
fields while keeping the required-vs-optional distinction intact; use
`type_has_null` only as part of the nullable decision, not the sole condition.
🪄 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: 649afd50-1512-4c21-bd78-a5fd89822b59
⛔ Files ignored due to path filters (14)
docs/llms-full.txtis excluded by none and included by noneskills/datamodel-code-generator/references/cli-options.mdis excluded by none and included by nonetests/data/expected/enums/pydantic_version_at_least.txtis excluded by!tests/data/**/*.txtand 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/json_output.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 nonetests/data/expected/model/pydantic_v2/config_target_pydantic_future_version.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/expected/prompt/default_parser_text.txtis excluded by!tests/data/**/*.txtand included by nonetests/data/jsonschema/missing_sentinel.jsonis excluded by!tests/data/**/*.jsonand included by none
📒 Files selected for processing (31)
docs/architecture.mddocs/cli-reference/index.mddocs/cli-reference/model-customization.mddocs/cli-reference/quick-reference.mdsrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dicts.pysrc/datamodel_code_generator/arguments.pysrc/datamodel_code_generator/base_config.pysrc/datamodel_code_generator/cli_options.pysrc/datamodel_code_generator/config.pysrc/datamodel_code_generator/enums.pysrc/datamodel_code_generator/model/base.pysrc/datamodel_code_generator/model/pydantic_base.pysrc/datamodel_code_generator/model/pydantic_v2/_config.pysrc/datamodel_code_generator/model/pydantic_v2/base_model.pysrc/datamodel_code_generator/model/pydantic_v2/imports.pysrc/datamodel_code_generator/parser/base.pysrc/datamodel_code_generator/parser/graphql.pysrc/datamodel_code_generator/parser/jsonschema.pysrc/datamodel_code_generator/parser/openapi.pysrc/datamodel_code_generator/prompt_data.pytests/data/expected/main/input_model/config_class.pytests/data/expected/main/jsonschema/missing_sentinel.pytests/data/expected/main/jsonschema/missing_sentinel_no_union_operator.pytests/main/jsonschema/test_main_jsonschema.pytests/main/test_public_api_signature_baseline.pytests/model/pydantic_v2/test_config.pytests/model/test_base.pytests/test_enums.pytests/test_main_kr.py
✅ Files skipped from review due to trivial changes (11)
- tests/data/expected/main/jsonschema/missing_sentinel.py
- tests/test_main_kr.py
- src/datamodel_code_generator/prompt_data.py
- tests/data/expected/main/jsonschema/missing_sentinel_no_union_operator.py
- src/datamodel_code_generator/_types/parser_config_dicts.py
- src/datamodel_code_generator/base_config.py
- docs/cli-reference/index.md
- docs/cli-reference/quick-reference.md
- tests/data/expected/main/input_model/config_class.py
- docs/cli-reference/model-customization.md
- docs/architecture.md
🚧 Files skipped from review as they are similar to previous changes (17)
- src/datamodel_code_generator/cli_options.py
- src/datamodel_code_generator/model/pydantic_base.py
- src/datamodel_code_generator/_types/generate_config_dict.py
- src/datamodel_code_generator/model/pydantic_v2/imports.py
- src/datamodel_code_generator/config.py
- src/datamodel_code_generator/parser/openapi.py
- src/datamodel_code_generator/enums.py
- tests/model/test_base.py
- src/datamodel_code_generator/model/pydantic_v2/_config.py
- src/datamodel_code_generator/parser/graphql.py
- tests/main/jsonschema/test_main_jsonschema.py
- src/datamodel_code_generator/model/base.py
- src/datamodel_code_generator/arguments.py
- src/datamodel_code_generator/parser/base.py
- src/datamodel_code_generator/init.py
- tests/main/test_public_api_signature_baseline.py
- src/datamodel_code_generator/parser/jsonschema.py
8eaaa14 to
5253417
Compare
5253417 to
e76a8c3
Compare
Breaking Change AnalysisResult: No breaking changes detected Reasoning: This PR is purely additive. It introduces a new opt-in CLI flag This analysis was performed by Claude Code Action |
|
🎉 Released in 0.66.2 This PR is now available in the latest release. See the release notes for details. |
Fixes: #437
Summary by CodeRabbit
--use-missing-sentinelto generate Pydantic v2 models using Pydantic’sMISSINGsentinel for optional fields without defaults.--target-pydantic-versionto support 2.12+, including compatibility updates for newer Pydantic behaviors.