Skip to content

Fix non-string OpenAPI discriminator literals#3070

Merged
koxudaxi merged 2 commits intomainfrom
feature/openapi-discriminator-non-string
Apr 4, 2026
Merged

Fix non-string OpenAPI discriminator literals#3070
koxudaxi merged 2 commits intomainfrom
feature/openapi-discriminator-non-string

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Apr 4, 2026

Fixes: #3062

Summary by CodeRabbit

  • Bug Fixes

    • Improved discriminator extraction and resolution logic, including better handling of integer discriminator values, enum-derived defaults, and fallbacks when mappings are partial or missing.
  • Tests

    • Added new tests and expected fixtures covering integer-based discriminator scenarios, partial mappings, and cases where enums collapse to literal discriminator values.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1e2c41ca-0b39-4f84-8f92-ce03fb621ee9

📥 Commits

Reviewing files that changed from the base of the PR and between b2090c5 and 4c24677.

📒 Files selected for processing (1)
  • src/datamodel_code_generator/parser/base.py

📝 Walkthrough

Walkthrough

Refactors discriminator extraction in the OpenAPI parser to preserve non-string discriminator types (int/bool) by introducing DiscriminatorValue and changing discriminator candidate derivation and data-type creation logic.

Changes

Cohort / File(s) Summary
Parser: discriminator logic
src/datamodel_code_generator/parser/base.py
Added `DiscriminatorValue: TypeAlias = str
Generated discriminator fixtures
tests/data/expected/main/openapi/discriminator/integer_mapping.py, tests/data/expected/main/openapi/discriminator/integer_no_mapping.py, tests/data/expected/main/openapi/discriminator/integer_no_mapping_literal.py, tests/data/expected/main/openapi/discriminator/partial_mapping.py
Added four expected output modules demonstrating integer discriminator handling: IntEnum usage, Literal[int] fields, and union RootModel fields with Field(..., discriminator='...').
OpenAPI tests
tests/main/openapi/test_main_openapi.py
Added test cases covering integer discriminator mapping, no-mapping, literal conversion mode, and partial mapping; three tests skip conditionally for Black v19.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Suggested labels

safe-to-fix

Suggested reviewers

  • ilovelinux

Poem

🐰 I hopped through schemas, numbers held tight,
No more string disguises in the night,
Enums, literals, consts in a row,
Discriminator values now rightly show,
Hooray — models match the spec just right! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix non-string OpenAPI discriminator literals' directly reflects the main change of preserving non-string types (like integers) in OpenAPI discriminators instead of coercing them to strings.
Linked Issues check ✅ Passed The PR successfully addresses issue #3062 by modifying discriminator value tracking to handle non-string types, generating correct integer literals instead of string literals for integer discriminators.
Out of Scope Changes check ✅ Passed All changes are directly within scope: core discriminator logic refactoring in base.py and new test fixtures validating integer discriminator generation across mapping, no-mapping, and partial-mapping scenarios.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/openapi-discriminator-non-string

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 4, 2026

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 4, 2026

Merging this PR will not alter performance

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

✅ 11 untouched benchmarks
⏩ 98 skipped benchmarks1


Comparing feature/openapi-discriminator-non-string (4c24677) with main (5dcbc09)

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
Copy link
Copy Markdown

codecov Bot commented Apr 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (5dcbc09) to head (4c24677).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #3070   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           87        87           
  Lines        18168     18185   +17     
  Branches      2081      2085    +4     
=========================================
+ Hits         18168     18185   +17     
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 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.

@koxudaxi koxudaxi merged commit 5a8cd0d into main Apr 4, 2026
38 checks passed
@koxudaxi koxudaxi deleted the feature/openapi-discriminator-non-string branch April 4, 2026 07:15
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 4, 2026

Breaking Change Analysis

Result: Breaking changes detected

Reasoning: This PR contains multiple breaking changes beyond the titular discriminator fix:

  1. Code generation output changed significantly: The entire default-value strategy for fields referencing models shifted from default_factory=lambda:... patterns (using model_validate, TypeAdapter, or direct constructors) to raw default values with validate_default=True. This produces different generated Python code text even though the runtime semantics are equivalent under Pydantic v2.

  2. Templates modified: All 6 type alias Jinja2 templates now have {% if fields %} guards with an {% else %} fallback to {{ base_class }}, which custom template users need to mirror.

  3. Internal API removed: ValidatedDefault, WrappedDefault types and SUPPORTS_WRAPPED_DEFAULT/SUPPORTS_VALIDATED_DEFAULT class variables deleted. While these were somewhat internal, they were exported via __all__ in model.base.

  4. New remote refs deprecation: A FutureWarning is emitted for remote $ref fetching without explicit --allow-remote-refs, signaling a future default behavior change.

Content for Release Notes

Code Generation Changes

  • Default value handling for model-referencing fields rewritten - Fields with defaults referencing Pydantic models (BaseModel, RootModel, type aliases) now generate Field(<raw_value>, validate_default=True) instead of default_factory=lambda: Model.model_validate(...), default_factory=lambda: TypeAdapter(...).validate_python(...), or default_factory=lambda: Model(...). Empty collection defaults changed from default_factory=list/default_factory=dict to Field([], validate_default=True)/Field({}, validate_default=True). The generated code is semantically equivalent under Pydantic v2 but textually different, which will break snapshot tests or tooling that matches exact output. pydantic.TypeAdapter is no longer imported in generated code. (Fix non-string OpenAPI discriminator literals #3070)

Custom Template Update Required

  • Type alias templates updated with fields guard - All six type alias templates (TypeAliasAnnotation.jinja2, TypeAliasType.jinja2, TypeStatement.jinja2, UnionTypeAliasAnnotation.jinja2, UnionTypeAliasType.jinja2, UnionTypeStatement.jinja2) now wrap the main body in {% if fields %}...{% else %} blocks that fall back to {{ base_class }} when no fields are present. Users with custom copies of these templates must add the same guard or handle the empty-fields case. (Fix non-string OpenAPI discriminator literals #3070)

API/CLI Changes

  • Internal types ValidatedDefault and WrappedDefault removed - The datamodel_code_generator.model._types module was deleted and ValidatedDefault/WrappedDefault are no longer exported from datamodel_code_generator.model.base. Code that imports or subclasses these types will break. The SUPPORTS_WRAPPED_DEFAULT and SUPPORTS_VALIDATED_DEFAULT class variables were removed from DataModel and its subclasses; custom model classes referencing these attributes will need updating. (Fix non-string OpenAPI discriminator literals #3070)

Default Behavior Changes

  • Remote $ref fetching now emits a FutureWarning - When the parser encounters an HTTP/HTTPS $ref without --allow-remote-refs being explicitly set, a FutureWarning is emitted warning that remote fetching will be disabled by default in a future version. Pass --allow-remote-refs to silence the warning, or --no-allow-remote-refs to block remote fetching immediately. (Fix non-string OpenAPI discriminator literals #3070)

This analysis was performed by Claude Code Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 4, 2026

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

OpenAPI integer discriminator is generated as string type

1 participant