Skip to content

Fix title ignored when creating enums from merging allOf's or anyOf's objects#2975

Merged
koxudaxi merged 3 commits intokoxudaxi:mainfrom
ilovelinux:fix/2974-use-title-for-enum
Jan 31, 2026
Merged

Fix title ignored when creating enums from merging allOf's or anyOf's objects#2975
koxudaxi merged 3 commits intokoxudaxi:mainfrom
ilovelinux:fix/2974-use-title-for-enum

Conversation

@ilovelinux
Copy link
Copy Markdown
Collaborator

@ilovelinux ilovelinux commented Jan 31, 2026

Fixes: #2974

The issue:

  • x_enum_varnames was passed to JsonSchemaObject using the variable name instead of its alias.

The consequence:

  • x_enum_varnames was not correctly recognized, and therefore ignored

The solution:

  • x_enum_varnames is now passed as x-enum-varnames (its alias) and it's no longer ignored

The fix above unveiled an incorrect behavior when no title is set but type can be inferred and used as title. A fix has been applied about that.

Summary by CodeRabbit

  • Bug Fixes
    • Improved enum metadata and naming for schemas using const in oneOf/anyOf: enum members now get descriptive, conventional names instead of generic numeric identifiers.
    • Fixed const value extraction so generated enum names correctly match their underlying values.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 31, 2026

📝 Walkthrough

Walkthrough

The parser stops adding a generated varname when a title is absent during const-based oneOf/anyOf extraction, and synthetic enum objects now set x-enum-varnames and default via a merged metadata dictionary instead of passing varnames directly.

Changes

Cohort / File(s) Summary
Parser Logic Updates
src/datamodel_code_generator/parser/jsonschema.py
Removed automatic varname addition when no title is present in _extract_const_enum_from_combined; changed _create_synthetic_enum_obj to construct x-enum-varnames and conditional default via a merged dict.
Test Expectations
tests/data/expected/main/jsonschema/oneof_const_enum_int.py
Renamed StatusCode IntEnum members from integer_200, integer_404, integer_500 to OK, Not_Found, Server_Error to reflect updated naming logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

breaking-change-analyzed, breaking-change

Poem

🐰 I nibbled at enums through the night,
Titles kept if they shone so bright,
Numbers dressed up with names that sing,
Merged metadata, a tidy thing,
Hoppity-hop, the parser's light!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and specifically describes the main fix: addressing the issue where title values are ignored when creating enums from merged allOf/anyOf objects.
Linked Issues check ✅ Passed The changes directly address issue #2974 by fixing how x-enum-varnames is passed and handling cases where no title is set, enabling proper enum member naming from schema titles.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing title handling in enum generation from combined schemas; no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jan 31, 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 ilovelinux:fix/2974-use-title-for-enum (ce2d14d) with main (4661406)

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.

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

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/parser/jsonschema.py (1)

855-868: ⚠️ Potential issue | 🟠 Major

Mixed title/no-title enums can lose all titles.

Line 855-868: if any item lacks a title and inferred_type is set, varnames becomes shorter than enum_values, so all titles are dropped. This contradicts “use title when available” for mixed cases.

✅ Suggested fix (preserve titles when present, keep legacy behavior when none)
@@
-        inferred_type: str | None = None
+        inferred_type: str | None = None
+        has_title = False
@@
-            if item.title:
-                varnames.append(item.title)
-            elif inferred_type is None and const_value is not None:
-                match const_value:
-                    case str():
-                        inferred_type = "string"
-                    case bool():  # bool must come before int (bool is subclass of int)
-                        inferred_type = "boolean"
-                    case int():
-                        inferred_type = "integer"
-                    case float():
-                        inferred_type = "number"
-            else:
-                varnames.append(str(const_value))
+            if item.title:
+                has_title = True
+                varnames.append(item.title)
+            else:
+                if inferred_type is None and const_value is not None:
+                    match const_value:
+                        case str():
+                            inferred_type = "string"
+                        case bool():  # bool must come before int (bool is subclass of int)
+                            inferred_type = "boolean"
+                        case int():
+                            inferred_type = "integer"
+                        case float():
+                            inferred_type = "number"
+                varnames.append(str(const_value))
@@
-        if not enum_values:  # pragma: no cover
+        if not enum_values:  # pragma: no cover
             return None
+        if not has_title and inferred_type is not None:
+            varnames = []

@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 31, 2026

Codecov Report

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

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #2975   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           94        94           
  Lines        17781     17780    -1     
  Branches      2044      2044           
=========================================
- Hits         17781     17780    -1     
Flag Coverage Δ
unittests 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.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes enum member naming for enums synthesized from oneOf/anyOf const-combinations by correctly propagating x-enum-varnames into the synthetic JsonSchemaObject, allowing per-item title values to be used for enum member names.

Changes:

  • Update synthetic enum schema creation to populate x-enum-varnames via its alias so Pydantic recognizes it.
  • Adjust const-enum extraction logic around how varnames and inferred enum type are derived.
  • Update expected JSON Schema output for an integer const oneOf enum to use titles as member names.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
tests/data/expected/main/jsonschema/oneof_const_enum_int.py Updates expected enum member names to reflect per-item title usage.
src/datamodel_code_generator/parser/jsonschema.py Fixes passing x-enum-varnames into synthetic enum schema objects and tweaks const-enum extraction behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/datamodel_code_generator/parser/jsonschema.py
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@koxudaxi koxudaxi merged commit 365419e into koxudaxi:main Jan 31, 2026
37 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: Breaking changes detected

Reasoning: This PR fixes a bug where the title field in oneOf/anyOf const schema constructs was being ignored. While this is a bug fix (the tool now correctly respects user-specified titles), it changes the generated enum member names for any schema that had title fields in these constructs. Users who have code referencing the old enum member names (like StatusCode.integer_200) would need to update to use the new names (like StatusCode.OK). This constitutes a breaking change in generated code output, even though the new behavior is the correct/intended one.

Content for Release Notes

Code Generation Changes

  • Enum member names from oneOf/anyOf const constructs now use title field when provided - Previously, when creating enums from oneOf/anyOf constructs with const values, the title field was incorrectly ignored and enum member names were generated using the pattern {type}_{value} (e.g., integer_200). Now, when a title is specified, it is correctly used as the enum member name (e.g., OK instead of integer_200). Users who have code depending on the previously generated enum member names will need to update their references. (Fix title ignored when creating enums from merging allOf's or anyOf's objects #2975)

    Before:

    class StatusCode(IntEnum):
        integer_200 = 200
        integer_404 = 404
        integer_500 = 500

    After:

    class StatusCode(IntEnum):
        OK = 200
        Not_Found = 404
        Server_Error = 500

This analysis was performed by Claude Code Action

@github-actions
Copy link
Copy Markdown
Contributor

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

Use title for enum naming

3 participants