Skip to content

Fix extra underscore on enum members like replace with --capitalise-enum-members#2999

Merged
koxudaxi merged 1 commit intomainfrom
fix/enum-member-replace-underscore
Feb 14, 2026
Merged

Fix extra underscore on enum members like replace with --capitalise-enum-members#2999
koxudaxi merged 1 commit intomainfrom
fix/enum-member-replace-underscore

Conversation

@koxudaxi
Copy link
Owner

@koxudaxi koxudaxi commented Feb 14, 2026

Fixes: #2970

Summary by CodeRabbit

  • New Features

    • Added options to control subclassed enums and target Python version for generation.
  • Bug Fixes

    • Improved handling of builtin type attribute conflicts in enum member naming with subclass enums.
    • Made enum name validation version-aware to respect Python-version differences.
  • Tests

    • Added tests covering enum naming, builtin conflicts, and capitalisation options.

@coderabbitai
Copy link

coderabbitai bot commented Feb 14, 2026

📝 Walkthrough

Walkthrough

Adds version-aware handling for builtin-type attribute conflicts in enums by exposing a numeric version_key on PythonVersion, propagating use_subclass_enum and target_python_version through resolver construction, and computing applicable builtin attributes at runtime for enum name validation.

Changes

Cohort / File(s) Summary
PythonVersion Enhancement
src/datamodel_code_generator/format.py
Added version_key cached property to PythonVersion returning a (major, minor) tuple for numeric comparisons.
Parser changes
src/datamodel_code_generator/parser/base.py
Removed private _python_version_key; updated _get_builtin_names_for_target() to use target_python_version.version_key; Parser now constructs ModelResolver with use_subclass_enum and target_python_version from config.
Name-resolution & runtime logic
src/datamodel_code_generator/reference.py
Made field-name validators instance methods; added use_subclass_enum and target_python_version options to FieldNameResolver/ModelResolver; replaced static builtin-attribute set with version-aware runtime mapping and helper _get_builtin_type_attributes_for_target; EnumFieldNameResolver now uses per-instance builtin attributes.
Tests / Golden files
tests/test_main_kr.py, tests/data/expected/main_kr/...
Added four CLI tests covering combinations of --capitalise-enum-members and --use-subclass-enum with builtin-name conflicts; added/updated expected generated files for those scenarios.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI
  participant Parser as Parser
  participant Resolver as ModelResolver
  participant FieldResolver as EnumFieldNameResolver
  participant PyVer as PythonVersion

  CLI->>Parser: parse args (use_subclass_enum, target_python_version)
  Parser->>Resolver: new ModelResolver(..., use_subclass_enum, target_python_version)
  Resolver->>FieldResolver: construct resolver for ENUM (passes use_subclass_enum, target_python_version)
  FieldResolver->>PyVer: request _get_builtin_type_attributes_for_target(target)
  PyVer-->>FieldResolver: return version-specific attribute set (via version_key)
  FieldResolver->>Resolver: validate/generate enum member names
  Resolver-->>Parser: resolved model names
  Parser-->>CLI: emit generated code / tests compare outputs
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested labels

breaking-change-analyzed

Poem

🐰 I hopped through code with care,

replace no longer wears a spare,
Version keys align the race,
Enum names find their rightful place,
Hooray — no extra underscore to bear! 🥕

🚥 Pre-merge checks | ✅ 5 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (5 files):

⚔️ src/datamodel_code_generator/format.py (content)
⚔️ src/datamodel_code_generator/parser/base.py (content)
⚔️ src/datamodel_code_generator/reference.py (content)
⚔️ tests/main/openapi/test_main_openapi.py (content)
⚔️ tests/test_main_kr.py (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ 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 accurately describes the main fix: removing the extra underscore appended to enum members like 'replace' when using --capitalise-enum-members flag.
Linked Issues check ✅ Passed The PR successfully addresses issue #2970 by making Python version-aware the builtin type attributes used in enum name validation, ensuring capitalised enum members no longer receive erroneous underscores.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the enum member underscore issue: refactoring version-key handling, updating field name resolution with runtime version awareness, and adding comprehensive test coverage.
Docstring Coverage ✅ Passed Docstring coverage is 89.47% 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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/enum-member-replace-underscore
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch fix/enum-member-replace-underscore
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/datamodel_code_generator/reference.py (1)

259-260: Stale noqa directives on changed lines.

Static analysis (Ruff) flags unused noqa directives on these changed lines:

  • Line 259: # noqa: FBT001, FBT002
  • Line 276: # noqa: ARG002, PLR6301
  • Line 386: # noqa: PLR6301
  • Line 495: # noqa: FBT001, FBT002

These are non-blocking but worth cleaning up since they're on lines you're already touching. Specifically, ARG002 on line 276 may also be stale now that field_name is actually used in the base class (it was previously unused in the base, hence the suppression, but it's still unused here via self—so it might still be valid depending on how Ruff resolves it).

Also applies to: 276-276, 386-386, 495-496


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
Contributor

github-actions bot commented Feb 14, 2026

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

@codecov
Copy link

codecov bot commented Feb 14, 2026

Codecov Report

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

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #2999   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           94        94           
  Lines        18075     18106   +31     
  Branches      2090      2093    +3     
=========================================
+ Hits         18075     18106   +31     
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 force-pushed the fix/enum-member-replace-underscore branch from 5c8595b to 709b9f6 Compare February 14, 2026 15:18
@koxudaxi koxudaxi merged commit 5011903 into main Feb 14, 2026
36 of 37 checks passed
@koxudaxi koxudaxi deleted the fix/enum-member-replace-underscore branch February 14, 2026 15:41
@github-actions
Copy link
Contributor

Breaking Change Analysis

Result: Breaking changes detected

Reasoning: This PR fixes a bug where the EnumFieldNameResolver was incorrectly adding underscore suffixes to capitalized enum members. The fix changes generated output in two ways: (1) Without --use-subclass-enum, enum members like 'replace' now become 'REPLACE' instead of 'REPLACE_' because the builtin type attribute check is skipped when subclass enums aren't used. (2) With --capitalise-enum-members, validation now checks the uppercased name ('REPLACE') instead of lowercase ('replace'), so it no longer conflicts with builtin methods like str.replace. While this is a bug fix, it changes the generated code output which could break existing users who depend on the previous (incorrect) naming convention.

Content for Release Notes

Code Generation Changes

  • Enum member names no longer get underscore suffix with --capitalise-enum-members - Previously, enum values like replace, count, index would generate REPLACE_, COUNT_, INDEX_ when using --capitalise-enum-members. Now they correctly generate REPLACE, COUNT, INDEX. The underscore suffix is only added when --use-subclass-enum is also used AND the lowercase name conflicts with builtin type methods. Users relying on the previous naming (e.g., referencing MyEnum.REPLACE_ in code) will need to update to use the new names without trailing underscores. (Fix extra underscore on enum members like replace with --capitalise-enum-members #2999)

This analysis was performed by Claude Code Action

@github-actions
Copy link
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.

Extra underscore for an enum variant named replace

1 participant