Skip to content

Add --class-name-prefix, --class-name-suffix, and --class-name-affix-scope options#2885

Merged
koxudaxi merged 9 commits intomainfrom
feature/class-name-prefix-suffix
Jan 1, 2026
Merged

Add --class-name-prefix, --class-name-suffix, and --class-name-affix-scope options#2885
koxudaxi merged 9 commits intomainfrom
feature/class-name-prefix-suffix

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Dec 31, 2025

Summary by CodeRabbit

  • New Features

    • Class-name prefix/suffix customization with selectable affix scope (all/models/enums); new public enum and config fields exposed.
  • CLI

    • New options: --class-name-prefix, --class-name-suffix, --class-name-affix-scope.
  • Documentation

    • CLI reference, model customization, and quick-reference updated with usage and examples.
  • Tests

    • Added tests for prefix/suffix behavior, scope control, and invalid affix validation.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 31, 2025

📝 Walkthrough

Walkthrough

Expose ClassNameAffixScope and add configurable class-name affixing: prefix, suffix, and affix-scope options; wire new config/CLI fields through GenerateConfig, Parser, ModelResolver, and generators; update typing, tests, and docs.

Changes

Cohort / File(s) Summary
Core Enum Definition
src/datamodel_code_generator/enums.py
New public enum ClassNameAffixScope (All, Models, Enums) and updated __all__.
Public API & Entrypoints
src/datamodel_code_generator/__init__.py, src/datamodel_code_generator/__main__.py
Export ClassNameAffixScope; extend CLI/config wiring and run_generate_from_config to accept and forward class_name_prefix, class_name_suffix, class_name_affix_scope.
Configuration Types
src/datamodel_code_generator/config.py, src/datamodel_code_generator/_types/generate_config_dict.py, src/datamodel_code_generator/_types/parser_config_dicts.py
Add class_name_prefix, class_name_suffix, class_name_affix_scope to config classes and TypedDicts; update TYPE_CHECKING imports.
CLI, Arguments & Metadata
src/datamodel_code_generator/arguments.py, src/datamodel_code_generator/cli_options.py, src/datamodel_code_generator/prompt_data.py
New CLI options --class-name-prefix, --class-name-suffix, --class-name-affix-scope; metadata and option descriptions added.
Model Resolution & Naming
src/datamodel_code_generator/reference.py
ModelResolver accepts affix config, validates identifiers, defers/applies affixes by scope/root, adds _apply_class_name_affix() and get_affixed_name(); add(), add_ref(), get_class_name(), and uniqueness flows extended to carry model_type, is_root, skip_affix.
Parser Integration
src/datamodel_code_generator/parser/...
src/datamodel_code_generator/parser/base.py, src/datamodel_code_generator/parser/graphql.py, src/datamodel_code_generator/parser/jsonschema.py
Affix args passed to ModelResolver; parsers annotate references with model_type (e.g., "enum") and use affixed names where appropriate.
Public Types & Baselines
tests/main/test_public_api_signature_baseline.py, src/datamodel_code_generator/_types/generate_config_dict.py, tests/data/expected/...
Public API baseline updated for new enum and config params; expected generated outputs updated for affix scenarios.
Tests
tests/main/jsonschema/test_main_jsonschema.py, tests/.../expected/...
New tests for prefix/suffix/scope and invalid affix values; test outputs updated (note: duplicate test insertions present).
Documentation
docs/cli-reference/index.md, docs/cli-reference/model-customization.md, docs/cli-reference/quick-reference.md
Document three new CLI options and update counts and examples.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CLI
  participant Config
  participant Parser
  participant ModelResolver
  participant Generator
  Note over CLI,Config: User supplies --class-name-prefix/--class-name-suffix/--class-name-affix-scope
  CLI->>Config: parse options -> GenerateConfig
  Config->>Parser: init parser (with affix settings)
  Parser->>ModelResolver: init ModelResolver(class_name_prefix/suffix/affix_scope,...)
  Parser->>ModelResolver: add/create Reference (include model_type "model"|"enum")
  ModelResolver-->>ModelResolver: determine is_root & scope -> decide skip_affix
  alt affix applies
    ModelResolver->>ModelResolver: apply affix to name
  end
  ModelResolver->>Generator: provide resolved (affixed & unique) class names
  Generator->>Generator: emit generated files with affixed class names
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

breaking-change-analyzed

Poem

🐰 I nibble prefixes, I hop with a suffix,

Resolver stitches names by scope and root,
CLI hands the ribbon, configs set the cuffs,
Parsers call the tailor, generators don the suit,
Hooray — class names wear their fancy loot!

Pre-merge checks and finishing touches

✅ Passed checks (3 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 change: adding three new CLI options for class name customization (prefix, suffix, and scope control).
Docstring Coverage ✅ Passed Docstring coverage is 88.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a89147a and e313d9c.

📒 Files selected for processing (3)
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/parser/graphql.py
  • src/datamodel_code_generator/reference.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/datamodel_code_generator/parser/graphql.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:22.481Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43
Timestamp: 2025-12-25T09:22:22.481Z
Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.

Applied to files:

  • src/datamodel_code_generator/reference.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.

Applied to files:

  • src/datamodel_code_generator/reference.py
🧬 Code graph analysis (2)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/util.py (1)
  • field_validator (175-191)
src/datamodel_code_generator/reference.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

517-517: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)


518-518: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)

src/datamodel_code_generator/reference.py

549-549: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1036-1036: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1082-1082: Unused noqa directive (non-enabled: PLR0913, PLR0917)

Remove unused noqa directive

(RUF100)


1085-1085: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1087-1087: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1090-1090: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1091-1091: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: combine coverage
🔇 Additional comments (13)
src/datamodel_code_generator/__main__.py (5)

57-57: LGTM!

The ClassNameAffixScope import aligns with the new affix configuration feature.


399-407: LGTM!

The Pydantic v2 validator correctly handles the conversion from string to ClassNameAffixScope enum with a sensible default of All.


475-483: LGTM!

The Pydantic v1 validator mirrors the v2 implementation for consistent behavior across versions.


517-519: New config fields are correctly defined.

The three new fields support the class name affix feature with appropriate types and defaults. The class_name_affix_scope correctly defaults to ClassNameAffixScope.All to maintain backward compatibility.


896-898: LGTM!

The new parameters are correctly wired through to the generate() function.

src/datamodel_code_generator/reference.py (8)

38-38: LGTM!

Import of ClassNameAffixScope enables the scope-based affix feature.


546-549: LGTM!

New constructor parameters for affix configuration are well-defined with sensible defaults.


596-605: Proper validation of affix configuration.

The validation correctly ensures:

  • class_name_prefix is a valid Python identifier
  • class_name_suffix can be appended to a name (checked via f"A{suffix}".isidentifier())

This prevents runtime errors from invalid class names being generated.


834-837: Correct deferral of affix application.

When class_name_affix_scope is not All, the model type is needed to determine whether to apply affixes. Since add_ref doesn't know the model type yet, this correctly skips affix application to defer it until add() is called with the full context.


935-952: Correct reprocessing logic for scope-dependent affixes.

The logic properly handles the case where a reference was initially created via add_ref (without affix due to unknown model type) and later needs reprocessing via add() when the model type becomes known.

The is_root calculation on line 939 correctly identifies root schemas:

  • joined_path == "#" for the main root
  • joined_path.endswith("#") with no / in the fragment for file roots

1064-1080: Well-documented public API for GraphQL parser.

The get_affixed_name method provides a clean interface for the GraphQL parser with explicit documentation about what it does and doesn't do (no singularization, no uniqueness checks, no dot-splitting).


1082-1124: Clean integration of affix logic into get_class_name.

The method now:

  1. Applies singularization first (line 1109-1110)
  2. Then applies affix based on scope (lines 1112-1113)
  3. Finally handles uniqueness (lines 1118-1123)

This ordering ensures affixes are considered in the unique name calculation.


1126-1126: LGTM!

The model_type parameter enables type-specific suffix handling during unique name generation.


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.

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: 1

🧹 Nitpick comments (4)
tests/data/expected/main/jsonschema/class_name_affix_scope_models/output.py (1)

22-24: Consider detecting and avoiding redundant affixes.

The generated class name ModelSchemaSchema results from applying the suffix "Schema" to a base name that already contains "Schema". While this is technically correct behavior, it creates awkward naming that could confuse users.

Consider enhancing the generator to detect when an affix is already present in the class name and skip application or emit a warning. This would improve the user experience and prevent naming like ModelSchemaSchema.

Would you like me to open an issue to track this enhancement, or would you prefer to implement smarter affix detection logic in the current PR?

tests/main/jsonschema/test_main_jsonschema.py (1)

707-768: Suffix and affix-scope=models tests are correctly wired; consider enums scope coverage

The --class-name-suffix and --class-name-affix-scope models tests mirror established patterns (cli_doc metadata, fixtures, and arguments) and should robustly cover model-only affix behavior.

If enums-only behavior (--class-name-affix-scope enums) isn’t exercised elsewhere, consider adding a small JSON Schema test for that mode to catch regressions in enum naming.

src/datamodel_code_generator/reference.py (2)

1040-1096: Clean implementation of affix application logic.

The scope-based affix application is well-structured:

  • _apply_class_name_affix correctly checks scope conditions
  • get_affixed_name provides a clean API for GraphQL with appropriate documentation

The is_enum = model_type == "enum" check relies on string comparison. Consider using an enum or constant for model_type values to prevent typos and improve type safety.

🔎 Optional: Use constants or enum for model_type values
# At module level or in a constants file
MODEL_TYPE_MODEL = "model"
MODEL_TYPE_ENUM = "enum"

# Then in _apply_class_name_affix:
is_enum = model_type == MODEL_TYPE_ENUM

This would prevent potential typos like "models" or "Model" from silently failing.


1098-1151: Well-structured transformation pipeline with clear ordering.

The transformation order (generator → singularization → affix → uniqueness) is correct, and the skip_affix parameter properly supports deferred affix application.

The inline comments explaining reserved_name behavior in the skip_generator_and_affix branch are helpful for maintainability.

Regarding static analysis hints: multiple noqa directives are flagged as unused (lines 1098, 1101, 1103, 1106, 1107). Consider removing them if the corresponding rules aren't enabled.

#!/bin/bash
# Verify if PLR0913, PLR0917, FBT001, FBT002 rules are enabled
fd -t f '(pyproject\.toml|ruff\.toml|\.ruff\.toml)$' --exec grep -l 'select\|extend-select' {} \; | xargs cat 2>/dev/null | grep -E '(PLR|FBT)'
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f06fa4 and f8ec8af.

⛔ Files ignored due to path filters (1)
  • tests/data/jsonschema/class_name_affix.json is excluded by !tests/data/**/*.json and included by none
📒 Files selected for processing (22)
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/_types/generate_config_dict.py
  • src/datamodel_code_generator/_types/graphql_parser_config_dict.py
  • src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py
  • src/datamodel_code_generator/_types/openapi_parser_config_dict.py
  • src/datamodel_code_generator/_types/parser_config_dict.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/config.py
  • src/datamodel_code_generator/enums.py
  • src/datamodel_code_generator/parser/base.py
  • src/datamodel_code_generator/parser/graphql.py
  • src/datamodel_code_generator/parser/jsonschema.py
  • src/datamodel_code_generator/reference.py
  • tests/data/expected/main/input_model/config_class.py
  • tests/data/expected/main/jsonschema/class_name_affix_scope_models/output.py
  • tests/data/expected/main/jsonschema/class_name_prefix/output.py
  • tests/data/expected/main/jsonschema/class_name_suffix/output.py
  • tests/data/expected/main/jsonschema/class_name_suffix_with_class_name/output.py
  • tests/main/jsonschema/test_main_jsonschema.py
  • tests/main/test_public_api_signature_baseline.py
🧰 Additional context used
🧬 Code graph analysis (17)
src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/_types/graphql_parser_config_dict.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/parser/graphql.py (1)
src/datamodel_code_generator/reference.py (2)
  • get_affixed_name (1074-1096)
  • Reference (142-201)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
tests/main/test_public_api_signature_baseline.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
tests/data/expected/main/jsonschema/class_name_affix_scope_models/output.py (2)
tests/data/expected/main/jsonschema/class_name_suffix/output.py (1)
  • ItemSchema (17-19)
tests/data/expected/main/jsonschema/class_name_suffix_with_class_name/output.py (1)
  • ItemSchema (17-19)
tests/data/expected/main/input_model/config_class.py (2)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/model/type_alias.py (1)
  • TypeAlias (37-42)
src/datamodel_code_generator/_types/openapi_parser_config_dict.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
tests/data/expected/main/jsonschema/class_name_prefix/output.py (2)
src/datamodel_code_generator/model/enum.py (1)
  • Enum (39-121)
src/datamodel_code_generator/model/base.py (1)
  • name (827-829)
tests/main/jsonschema/test_main_jsonschema.py (3)
tests/conftest.py (1)
  • freeze_time (352-355)
tests/test_main_kr.py (1)
  • output_file (44-46)
tests/main/conftest.py (2)
  • output_file (98-100)
  • run_main_and_assert (244-408)
src/datamodel_code_generator/parser/base.py (1)
src/datamodel_code_generator/model/base.py (2)
  • class_name (848-850)
  • class_name (853-857)
src/datamodel_code_generator/__init__.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/arguments.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/reference.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/util.py (1)
  • field_validator (175-191)
src/datamodel_code_generator/config.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/reference.py

549-549: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


550-550: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1044-1044: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1098-1098: Unused noqa directive (non-enabled: PLR0913, PLR0917)

Remove unused noqa directive

(RUF100)


1101-1101: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1103-1103: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1106-1106: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1107-1107: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)

src/datamodel_code_generator/__main__.py

517-517: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)


518-518: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)

🔇 Additional comments (43)
src/datamodel_code_generator/enums.py (1)

131-142: LGTM! Clear and well-documented enum.

The ClassNameAffixScope enum is well-structured with clear documentation explaining each scope option. The implementation follows existing patterns in the codebase.

tests/data/expected/main/jsonschema/class_name_suffix_with_class_name/output.py (1)

1-24: LGTM! Test expectation correctly demonstrates suffix behavior with explicit root name.

The generated output correctly shows that when an explicit root class name (MyRootModel) is provided, the suffix is applied to non-root classes (StatusSchema, ItemSchema) but not to the explicitly named root model.

tests/data/expected/main/jsonschema/class_name_suffix/output.py (1)

1-24: LGTM! Test expectation correctly demonstrates consistent suffix application.

The generated output correctly shows the "Schema" suffix applied consistently to all classes (enum and models) when using the default affix scope.

tests/data/expected/main/jsonschema/class_name_affix_scope_models/output.py (1)

12-14: LGTM! Enum correctly excludes suffix with "models" scope.

The Status enum correctly has no suffix applied, demonstrating that the class_name_affix_scope="models" setting properly excludes enum classes.

tests/data/expected/main/jsonschema/class_name_prefix/output.py (1)

1-24: LGTM! Test expectation correctly demonstrates prefix application.

The generated output correctly shows the "Api" prefix applied consistently to all classes (enums and models), demonstrating the class name prefix feature working as intended.

src/datamodel_code_generator/parser/jsonschema.py (3)

3152-3152: LGTM!

Correctly passes model_type="enum" to enable scope-based affix application for enum references. This aligns with the new ClassNameAffixScope feature that distinguishes between model and enum classes.


3223-3223: LGTM!

Consistent with the other enum reference creation sites in this method.


3237-3237: LGTM!

Correctly handles the nullable enum wrapper case with the same model_type="enum" parameter.

src/datamodel_code_generator/_types/jsonschema_parser_config_dict.py (2)

18-18: LGTM!

Import correctly placed within the TYPE_CHECKING block alongside other enum imports from datamodel_code_generator.enums.


59-61: LGTM!

New configuration fields are appropriately typed and placed logically after class_name. The typing is consistent with other parser config TypedDicts mentioned in the AI summary.

tests/main/test_public_api_signature_baseline.py (3)

19-19: LGTM!

Import correctly placed at module level (not under TYPE_CHECKING) since ClassNameAffixScope.All is used as a runtime default value.


88-90: LGTM!

Baseline parameters correctly reflect the new public API surface. The default ClassNameAffixScope.All matches the expected behavior documented in the enum definition.


217-219: LGTM!

Parser baseline signature is consistent with the generate function baseline, ensuring API parity is tested correctly.

src/datamodel_code_generator/parser/graphql.py (1)

150-158: LGTM!

The implementation correctly:

  1. Determines model_type based on GraphQL TypeKind for scope-aware affixing
  2. Uses get_affixed_name() which is the dedicated GraphQL API per the relevant code snippet (no uniqueness checks, no singularization)
  3. Preserves original_name=type_.name for internal lookups while exposing the affixed name via Reference.name
  4. Keys self.references by type_.name (original name), which is correct since all lookups (e.g., line 370) use original GraphQL type names

This cleanly separates internal naming from generated output naming.

src/datamodel_code_generator/_types/generate_config_dict.py (1)

69-71: LGTM!

The new fields are properly typed with NotRequired for backward compatibility. Note that class_name_affix_scope is typed as NotRequired[ClassNameAffixScope] (without | None), which correctly requires a valid enum value when the field is provided.

src/datamodel_code_generator/__init__.py (1)

38-38: LGTM!

The ClassNameAffixScope enum is correctly imported and added to the public API exports.

src/datamodel_code_generator/cli_options.py (1)

81-83: LGTM!

The new CLI options are properly documented with appropriate metadata. The MODEL category placement is correct, and the positioning after --class-name is logical.

src/datamodel_code_generator/_types/graphql_parser_config_dict.py (1)

59-61: LGTM!

The new fields are consistent with the changes in generate_config_dict.py and properly extend the parser configuration for GraphQL.

src/datamodel_code_generator/arguments.py (2)

22-22: LGTM!

The import of ClassNameAffixScope is correctly placed and necessary for the new CLI option.


202-224: Well-documented CLI options with clear semantics.

The new arguments are properly structured with comprehensive help text. The documented behavior—"Does not apply to root model when --class-name is specified"—is correctly implemented: skip_affix_for_root is set to True when --class-name is provided, and the _apply_class_name_affix() method correctly skips affixing when both is_root and skip_affix_for_root are true.

tests/data/expected/main/input_model/config_class.py (2)

28-30: LGTM!

The ClassNameAffixScope TypeAlias correctly represents the enum values as a Literal type, consistent with the enum definition.


142-144: LGTM!

The new fields are correctly typed with NotRequired for backward compatibility and match the configuration schema.

src/datamodel_code_generator/_types/openapi_parser_config_dict.py (2)

18-18: LGTM!

The import is correctly placed within the TYPE_CHECKING block for type annotation purposes.


60-62: LGTM!

The new configuration fields are properly typed and consistent with other config definitions across the codebase.

src/datamodel_code_generator/_types/parser_config_dict.py (2)

18-18: LGTM!

Import is correctly placed in the TYPE_CHECKING block.


59-61: LGTM!

The configuration fields are properly defined with consistent typing across all parser config dictionaries.

src/datamodel_code_generator/config.py (3)

18-18: LGTM!

The import is correctly placed at runtime (not in TYPE_CHECKING) since it's used for the default value ClassNameAffixScope.All.


107-109: LGTM!

The fields are properly typed with sensible defaults. The default of ClassNameAffixScope.All aligns with the enum's documentation indicating "Apply to all classes including enums (default)."


242-244: LGTM!

The fields are consistently defined with the same defaults as in GenerateConfig, ensuring coherent configuration across the parser pipeline.

src/datamodel_code_generator/__main__.py (5)

57-57: LGTM!

The import of ClassNameAffixScope is correctly added and properly used throughout the file for configuration and validation.


399-407: LGTM!

The validator correctly handles type coercion for the class_name_affix_scope field, converting None to the default value and strings to the enum type. The implementation follows established patterns in this codebase.


475-483: LGTM!

The Pydantic v1 validator correctly mirrors the v2 implementation, ensuring consistent behavior across both Pydantic versions. The duplication is necessary for compatibility.


896-898: LGTM!

The new configuration fields are correctly passed through to the generate() function, completing the configuration pipeline. The placement next to the existing class_name parameter is logical and maintains good code organization.


517-519: Clean up unused noqa directives.

The new configuration fields are correctly added with appropriate types and defaults. However, the # noqa: UP045 directives on lines 517-518 are unused according to static analysis.

🔎 Suggested cleanup
-    class_name_prefix: Optional[str] = None  # noqa: UP045
-    class_name_suffix: Optional[str] = None  # noqa: UP045
+    class_name_prefix: Optional[str] = None
+    class_name_suffix: Optional[str] = None
     class_name_affix_scope: ClassNameAffixScope = ClassNameAffixScope.All
⛔ Skipped due to learnings
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43
Timestamp: 2025-12-25T09:22:22.481Z
Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.
tests/main/jsonschema/test_main_jsonschema.py (2)

677-705: Prefix option CLI doc and test wiring look consistent

The --class-name-prefix cli_doc metadata, use of freeze_time, and run_main_and_assert arguments (schema path, expected fixture path, and extra_args) all match existing JSON Schema tests in this module. No changes needed here.


771-785: Root-model override behavior with --class-name is clearly specified and tested

This test precisely captures the contract that an explicit --class-name prevents the suffix from being applied to the root model, using a dedicated expected fixture and frozen timestamp. The setup is consistent with surrounding tests.

src/datamodel_code_generator/reference.py (7)

38-38: LGTM!

Import of ClassNameAffixScope is correctly placed with other imports from the same package.


597-602: LGTM!

Configuration storage is clean with sensible defaults. Empty strings for prefix/suffix and ClassNameAffixScope.All as the default scope are appropriate.


831-837: LGTM!

The deferred affix logic is correct. Since add_ref doesn't know the model_type yet, it appropriately skips affix application when scope-dependent, delegating it to add() where the type is known.


939-958: Well-designed deferred affix reprocessing logic.

The is_root detection and needs_reprocess logic correctly handle the case where add_ref() created a reference without affix (due to unknown model_type), and now add() can apply the correct affix.

One edge case to consider: a path like "file.json#/" would have split("#")[-1] return "/", and "/" not in "/" is False, so it wouldn't be detected as root. This seems intentional (trailing slash indicates a path), but worth confirming this matches expected behavior.


974-992: LGTM!

Both code paths consistently pass model_type and is_root to get_class_name().


1147-1147: LGTM!

Passing model_type to _get_unique_name enables type-specific duplicate name suffixes, which integrates well with the overall affix feature.


546-551: The noqa: FBT001, FBT002 directives on lines 549-550 are necessary and should be kept.

The project's linter configuration enables FBT rules for non-test files (via lint.select = ["ALL"] with no global FBT ignore, only per-file ignores for tests/**/*.py). The noqa directives suppress legitimate FBT001/FBT002 warnings for boolean parameters with default values—a consistent pattern throughout this file and the codebase.

Likely an incorrect or invalid review comment.

Comment thread src/datamodel_code_generator/parser/base.py
@koxudaxi koxudaxi force-pushed the feature/class-name-prefix-suffix branch from 9d1c3fb to 7038df8 Compare December 31, 2025 23:53
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 31, 2025

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: 1

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

1105-1158: Remove unused noqa directives; transformation order is correct.

The logic correctly handles:

  1. Transformation order: generator → singularization → affix → reserved name check → uniqueness
  2. Proper separation of skip_generator_and_affix path (no reserved_name check) vs. normal path
  3. Conditional affix application with skip_affix parameter

However, multiple unused noqa directives should be removed (lines 1105, 1108, 1110, 1113, 1114).

🔎 Proposed fix
-    def get_class_name(  # noqa: PLR0913, PLR0917
+    def get_class_name(
         self,
         name: str,
-        unique: bool = True,  # noqa: FBT001, FBT002
+        unique: bool = True,
         reserved_name: str | None = None,
-        singular_name: bool = False,  # noqa: FBT001, FBT002
+        singular_name: bool = False,
         singular_name_suffix: str | None = None,
         model_type: str = "model",
-        is_root: bool = False,  # noqa: FBT001, FBT002
-        skip_affix: bool = False,  # noqa: FBT001, FBT002
+        is_root: bool = False,
+        skip_affix: bool = False,
     ) -> ClassName:
🧹 Nitpick comments (3)
tests/main/jsonschema/test_main_jsonschema.py (2)

738-769: Consider adding explicit coverage for --class-name-affix-scope=enums

You exercise the default all scope (prefix/suffix tests) and models scope here; the new enums scope is only verified implicitly via implementation. A small additional golden-output test with --class-name-affix-scope enums (showing only enums renamed while models stay unchanged) would close the matrix and protect against regressions in scope handling.


771-812: Tighten invalid prefix/suffix tests by asserting error messages / using shared helper

The invalid prefix/suffix tests correctly assert Exit.ERROR, but they don't validate the error message or reuse run_main_and_assert like the nearby invalid model name tests. To make these failures more robust and consistent, consider either:

  • switching to run_main_and_assert(..., expected_exit=Exit.ERROR, expected_stderr_contains=...), or
  • capturing capsys and asserting the specific validation message.
    This keeps the tests resilient to unrelated exit paths that might also return Exit.ERROR.
src/datamodel_code_generator/reference.py (1)

597-610: Consider validating before assignment for cleaner initialization.

The validation logic is correct, but prefix/suffix are assigned to instance variables (lines 598-599) before validation (lines 601-606). If validation fails, the instance is briefly in an inconsistent state. While this doesn't cause issues in practice (since __init__ raises and the instance is discarded), validating before assignment is cleaner.

🔎 Proposed refactor
-        # Class name affix configuration with validation
-        self.class_name_prefix: str = class_name_prefix or ""
-        self.class_name_suffix: str = class_name_suffix or ""
-        # Validate prefix/suffix are valid identifier components
-        if self.class_name_prefix and not self.class_name_prefix.isidentifier():
-            msg = f"--class-name-prefix '{self.class_name_prefix}' is not a valid Python identifier"
+        # Class name affix configuration with validation
+        prefix = class_name_prefix or ""
+        suffix = class_name_suffix or ""
+        # Validate prefix/suffix are valid identifier components
+        if prefix and not prefix.isidentifier():
+            msg = f"--class-name-prefix '{prefix}' is not a valid Python identifier"
             raise ValueError(msg)
-        if self.class_name_suffix and not (f"A{self.class_name_suffix}").isidentifier():
-            msg = f"--class-name-suffix '{self.class_name_suffix}' is not a valid Python identifier component"
+        if suffix and not (f"A{suffix}").isidentifier():
+            msg = f"--class-name-suffix '{suffix}' is not a valid Python identifier component"
             raise ValueError(msg)
+        self.class_name_prefix: str = prefix
+        self.class_name_suffix: str = suffix
         self.class_name_affix_scope: ClassNameAffixScope = class_name_affix_scope or ClassNameAffixScope.All
         self.skip_affix_for_root: bool = skip_affix_for_root
         self.skip_generator_and_affix: bool = skip_generator_and_affix
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8ec8af and 9d1c3fb.

📒 Files selected for processing (2)
  • src/datamodel_code_generator/reference.py
  • tests/main/jsonschema/test_main_jsonschema.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/datamodel_code_generator/reference.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/reference.py

549-549: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


550-550: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1051-1051: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1105-1105: Unused noqa directive (non-enabled: PLR0913, PLR0917)

Remove unused noqa directive

(RUF100)


1108-1108: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1110-1110: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1113-1113: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1114-1114: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)

🔇 Additional comments (7)
tests/main/jsonschema/test_main_jsonschema.py (1)

677-769: Well-integrated CLI doc + golden-output coverage for new class-name affix options

The three tests for --class-name-prefix, --class-name-suffix, and --class-name-affix-scope=models follow existing patterns (cli_doc metadata, golden outputs under main/jsonschema/..., and @freeze_time for deterministic headers) and give solid end-to-end coverage of the new options, including interaction with enums via the shared class_name_affix.json fixture. Nice job threading these through the same harness used by other CLI options.

src/datamodel_code_generator/reference.py (6)

38-38: LGTM: Import is correctly placed.

The import of ClassNameAffixScope is necessary for the new affix scope functionality and is appropriately positioned with other package imports.


838-844: LGTM: Deferred affix logic is correct.

The logic to skip affix application in add_ref when scope is not All is correct. Since add_ref is called before the model type is known, deferring affix application until add() is called (with model_type) ensures correct scope-based filtering.


942-999: LGTM: Root detection and reprocessing logic are correct.

The changes to the add() method properly handle:

  1. Root path detection (lines 946-948) with correct logic for identifying root schemas
  2. Smart early return that reprocesses references when scope-dependent affixes need to be applied with the now-known model_type (lines 953-966)
  3. Consistent propagation of model_type and is_root to get_class_name() (lines 987-999)

1081-1103: LGTM: GraphQL-specific method is correctly implemented.

The get_affixed_name() method correctly provides a simplified path for GraphQL parser with appropriate handling:

  • Skips uniqueness and singularization (GraphQL manages its own naming)
  • Hardcodes is_root=False (appropriate since GraphQL types aren't JSON Schema roots)
  • Clear documentation of GraphQL-specific behavior

1160-1160: LGTM: Model type parameter enables type-specific duplicate suffixes.

Adding the model_type parameter to _get_unique_name() is necessary to support type-specific duplicate name suffixes via duplicate_name_suffix_map.


546-550: Remove unused noqa directives.

Static analysis correctly identifies that the # noqa: FBT001, FBT002 directives on lines 549-550 are unused and should be removed.

🔎 Proposed fix
         class_name_prefix: str | None = None,
         class_name_suffix: str | None = None,
         class_name_affix_scope: ClassNameAffixScope | None = None,
-        skip_affix_for_root: bool = False,  # noqa: FBT001, FBT002
-        skip_generator_and_affix: bool = False,  # noqa: FBT001, FBT002
+        skip_affix_for_root: bool = False,
+        skip_generator_and_affix: bool = False,
⛔ Skipped due to learnings
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43
Timestamp: 2025-12-25T09:22:22.481Z
Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.

Comment thread src/datamodel_code_generator/reference.py
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 31, 2025

CodSpeed Performance Report

Merging #2885 will not alter performance

Comparing feature/class-name-prefix-suffix (e313d9c) with main (6ab97df)

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

Summary

✅ 11 untouched
⏩ 98 skipped1

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 Dec 31, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.37%. Comparing base (74cd08b) to head (e313d9c).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2885   +/-   ##
=======================================
  Coverage   99.37%   99.37%           
=======================================
  Files          92       92           
  Lines       16046    16121   +75     
  Branches     1893     1898    +5     
=======================================
+ Hits        15945    16020   +75     
  Misses         52       52           
  Partials       49       49           
Flag Coverage Δ
unittests 99.37% <100.00%> (+<0.01%) ⬆️

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

@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: 1

♻️ Duplicate comments (1)
src/datamodel_code_generator/reference.py (1)

1047-1079: Scope-based affix logic is correct, but remove unused noqa directive.

The implementation correctly applies affixes based on scope and root status:

  • All: applies to both models and enums
  • Models: applies only to non-enum classes
  • Enums: applies only to enum classes
  • Root models respect skip_affix_for_root flag

However, the # noqa: FBT001, FBT002 directive on line 1051 is unused and should be removed.

🔎 Proposed fix
     def _apply_class_name_affix(
         self,
         name: str,
         model_type: str = "model",
-        is_root: bool = False,  # noqa: FBT001, FBT002
+        is_root: bool = False,
     ) -> str:
🧹 Nitpick comments (2)
src/datamodel_code_generator/parser/jsonschema.py (1)

3152-3152: LGTM! All enum reference creation paths correctly categorized.

The addition of model_type="enum" to all three enum reference creation paths ensures that enums can be properly identified for selective class name affixing based on the new ClassNameAffixScope feature. This covers:

  1. Empty nullable enums (line 3152)
  2. Standard enums (line 3223)
  3. Nullable enum wrappers (line 3237)

Consider extracting the string literal "enum" to a named constant to avoid magic strings and improve maintainability:

# At module or class level
MODEL_TYPE_ENUM = "enum"

# Then use:
model_type=MODEL_TYPE_ENUM

This would make the code more maintainable if model type categorization is expanded in the future.

Also applies to: 3223-3223, 3237-3237

tests/main/jsonschema/test_main_jsonschema.py (1)

677-811: New class-name affix tests are well-targeted; consider a bit more coverage.

The new tests cover prefix, suffix, scoped application to models, interaction with --class-name, and basic validation of invalid affixes, which should guard the new CLI surface well. Two small follow-ups you might consider (non-blocking):

  • Add a JSON Schema + test case for --class-name-affix-scope enums to exercise that branch explicitly, similar to test_main_class_name_affix_scope_models.
  • For the invalid prefix/suffix tests, optionally assert on stderr via run_main_and_assert(..., expected_exit=Exit.ERROR, expected_stderr_contains=...) for stronger guarantees about the user-facing error message, and to stay stylistically consistent with the nearby invalid --class-name tests.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d1c3fb and f220c81.

⛔ Files ignored due to path filters (1)
  • tests/data/jsonschema/class_name_affix.json is excluded by !tests/data/**/*.json and included by none
📒 Files selected for processing (23)
  • docs/cli-reference/index.md
  • docs/cli-reference/model-customization.md
  • docs/cli-reference/quick-reference.md
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/_types/generate_config_dict.py
  • src/datamodel_code_generator/_types/parser_config_dicts.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/config.py
  • src/datamodel_code_generator/enums.py
  • src/datamodel_code_generator/parser/base.py
  • src/datamodel_code_generator/parser/graphql.py
  • src/datamodel_code_generator/parser/jsonschema.py
  • src/datamodel_code_generator/prompt_data.py
  • src/datamodel_code_generator/reference.py
  • tests/data/expected/main/input_model/config_class.py
  • tests/data/expected/main/jsonschema/class_name_affix_scope_models/output.py
  • tests/data/expected/main/jsonschema/class_name_prefix/output.py
  • tests/data/expected/main/jsonschema/class_name_suffix/output.py
  • tests/data/expected/main/jsonschema/class_name_suffix_with_class_name/output.py
  • tests/main/jsonschema/test_main_jsonschema.py
  • tests/main/test_public_api_signature_baseline.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/arguments.py
  • tests/data/expected/main/jsonschema/class_name_prefix/output.py
  • src/datamodel_code_generator/enums.py
  • tests/data/expected/main/jsonschema/class_name_affix_scope_models/output.py
  • tests/data/expected/main/jsonschema/class_name_suffix_with_class_name/output.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:22.481Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43
Timestamp: 2025-12-25T09:22:22.481Z
Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.

Applied to files:

  • src/datamodel_code_generator/reference.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.

Applied to files:

  • src/datamodel_code_generator/reference.py
🧬 Code graph analysis (11)
src/datamodel_code_generator/_types/parser_config_dicts.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/parser/base.py (1)
src/datamodel_code_generator/model/base.py (2)
  • class_name (848-850)
  • class_name (853-857)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/util.py (1)
  • field_validator (175-191)
src/datamodel_code_generator/__init__.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
tests/data/expected/main/input_model/config_class.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/config.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
tests/main/jsonschema/test_main_jsonschema.py (2)
tests/main/conftest.py (2)
  • output_file (98-100)
  • run_main_and_assert (244-408)
src/datamodel_code_generator/__main__.py (2)
  • Exit (126-132)
  • main (1000-1310)
tests/main/test_public_api_signature_baseline.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/reference.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
tests/data/expected/main/jsonschema/class_name_suffix/output.py (3)
src/datamodel_code_generator/model/enum.py (1)
  • Enum (39-121)
tests/data/expected/main/jsonschema/class_name_suffix_with_class_name/output.py (2)
  • StatusSchema (12-14)
  • ItemSchema (17-19)
tests/data/expected/main/jsonschema/class_name_affix_scope_models/output.py (1)
  • ItemSchema (17-19)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

517-517: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)


518-518: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)

src/datamodel_code_generator/reference.py

549-549: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


550-550: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1051-1051: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1105-1105: Unused noqa directive (non-enabled: PLR0913, PLR0917)

Remove unused noqa directive

(RUF100)


1108-1108: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1110-1110: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1113-1113: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1114-1114: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: combine coverage
🔇 Additional comments (27)
docs/cli-reference/quick-reference.md (2)

95-97: New options correctly integrated into Model Customization table.

The three options are properly placed in alphabetical order after --class-name and follow the table formatting convention. Descriptions are appropriately concise for the quick reference format.


215-217: New options correctly added to alphabetical index (section C).

The options are properly ordered and link to the correct anchors in model-customization.md.

docs/cli-reference/model-customization.md (4)

12-14: Three new options properly documented in options table.

The options are correctly placed between --class-name and --collapse-reuse-models in alphabetical order, maintaining table consistency.


1252-1332: --class-name-affix-scope documentation is comprehensive and clear.

The section includes proper markdown anchor, clear description of the three scopes (all/models/enums), related options cross-references, practical usage example, and example schema with output showing correct behavior (Status enum unchanged, ItemSchema model affected when scope='models').


1334-1412: --class-name-prefix documentation is comprehensive and well-structured.

The section includes all standard elements: anchor, description, related options, usage example, and input/output examples demonstrating prefix application to both models and enums. Examples show correct transformation (Item → ApiItem, Status → ApiStatus, Model → ApiModel).


1414-1492: --class-name-suffix documentation is comprehensive and well-structured.

The section follows the same pattern as prefix documentation, with clear examples showing suffix application to both models and enums (Item → ItemSchema, Status → StatusSchema, Model → ModelSchema).

docs/cli-reference/index.md (2)

14-14: Model Customization option count correctly updated.

The count has been increased from 38 to 39 options, properly reflecting the addition of three new options. This aligns with the actual documented options in the Model Customization section.


47-49: New options correctly added to alphabetical index section C.

The three options are properly ordered alphabetically and include correct links to the model-customization.md anchors.

src/datamodel_code_generator/parser/graphql.py (1)

148-158: Affixed GraphQL reference names wiring looks correct

Deriving "enum" vs "model" from resolved_type and using get_affixed_name solely for Reference.name keeps internal keys/original_name stable while honoring affix scope for generated class names. This is a clean integration with the new affix API.

src/datamodel_code_generator/__init__.py (1)

30-52: Public exposure of ClassNameAffixScope is consistent

Importing ClassNameAffixScope from enums and adding it to __all__ matches how other strategy enums are surfaced at the top level; no issues.

Also applies to: 921-954

tests/data/expected/main/input_model/config_class.py (1)

28-30: Typed config surface for affix options looks consistent

ClassNameAffixScope’s Literal values match the runtime enum, and the three new GenerateConfig fields mirror existing optional string/enum config keys. This keeps the generated config class in sync with the new feature.

Also applies to: 142-145

src/datamodel_code_generator/_types/generate_config_dict.py (1)

15-35: GenerateConfigDict extended correctly for affix options

Importing ClassNameAffixScope under TYPE_CHECKING and adding class_name_prefix, class_name_suffix, and class_name_affix_scope as optional fields is in line with existing config dict patterns and keeps the typed config dict aligned with the public options.

Also applies to: 69-71

src/datamodel_code_generator/parser/base.py (1)

879-901: ModelResolver wiring for affix configuration looks correct

Forwarding class_name_prefix, class_name_suffix, and class_name_affix_scope directly from config, and deriving skip_affix_for_root from config.class_name gives ModelResolver all it needs to honor both affix and explicit root-name semantics without changing other behavior.

tests/data/expected/main/jsonschema/class_name_suffix/output.py (1)

1-24: Expected output for --class-name-suffix scenario looks correct

Enum and model names consistently include the Schema suffix, and field types line up with the described JSON Schema structure, giving good coverage for the suffix behavior.

src/datamodel_code_generator/_types/parser_config_dicts.py (1)

15-28: ParserConfig wiring for class-name affix options looks consistent and correct.

Importing ClassNameAffixScope under TYPE_CHECKING and adding class_name_prefix, class_name_suffix, and class_name_affix_scope: NotRequired[ClassNameAffixScope] to ParserConfig aligns with how other enum-backed options are modeled here. I don’t see any typing or structural issues in this addition.

Also applies to: 60-63

tests/main/test_public_api_signature_baseline.py (1)

19-19: LGTM! Baseline signatures correctly extended.

The new class name affix parameters are properly added to both baseline function signatures with consistent defaults and type annotations.

Also applies to: 88-90, 217-219

src/datamodel_code_generator/config.py (1)

18-18: LGTM! Configuration fields properly added.

The new class name affix fields are correctly added to both GenerateConfig and ParserConfig with appropriate types and defaults.

Also applies to: 107-109, 242-244

src/datamodel_code_generator/__main__.py (4)

57-57: LGTM! Enum validator correctly implemented.

The validator properly converts string inputs to the ClassNameAffixScope enum and defaults None to All.

Also applies to: 399-407


475-483: LGTM! Pydantic v1 compatibility maintained.

The Pydantic v1 validator correctly mirrors the v2 implementation for backward compatibility.


517-519: LGTM! Config fields properly defined.

The new configuration fields are correctly typed and follow the project's existing patterns for optional fields.


896-898: LGTM! Parameters correctly propagated.

The new configuration options are properly passed through to the generate() function call.

src/datamodel_code_generator/reference.py (6)

546-609: LGTM! Initialization and validation are robust.

The class name affix configuration is properly initialized with thorough validation:

  • Prefix must be a valid Python identifier
  • Suffix must form valid identifier when combined
  • Clear error messages for invalid inputs
  • Appropriate default handling

838-844: LGTM! Deferred affix application is correctly implemented.

The logic properly defers affix application when scope is model-type dependent, applying it later when model_type is known. The comments clearly explain this design decision.


942-999: LGTM! Model type and root tracking correctly implemented.

The add method properly:

  • Determines root status based on path structure
  • Implements smart early-return logic to avoid redundant processing
  • Allows reprocessing when scope-dependent affix needs model_type
  • Consistently passes model_type and is_root to name generation

1081-1103: LGTM! GraphQL-specific naming method is well-designed.

The get_affixed_name method correctly provides a streamlined path for GraphQL naming:

  • Skips uniqueness checks (GraphQL maintains its own naming)
  • Applies generator and affix without singularization
  • Clear documentation of GraphQL-specific behavior

1105-1158: LGTM! Comprehensive class name generation with affix support.

The enhanced get_class_name method correctly implements:

  • Conditional transformation skipping via skip_generator_and_affix
  • Deferred affix application via skip_affix parameter
  • Proper placement of reserved name check (after transformations)
  • Consistent uniqueness handling for all code paths
  • Clear comments explaining the logic flow

The transformation pipeline is sound: dotted names → generator → singularization → affix → reserved name check → uniqueness.


1160-1183: LGTM! Model-type-specific duplicate name suffixes implemented.

The changes enable type-specific suffixes for duplicate name resolution while maintaining backward compatibility with the global duplicate_name_suffix.

Comment thread src/datamodel_code_generator/prompt_data.py
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

♻️ Duplicate comments (1)
src/datamodel_code_generator/reference.py (1)

1047-1079: Fix unused noqa directive; logic is correct.

The scope-based filtering logic correctly applies affixes according to the configuration. However, the # noqa: FBT001, FBT002 directive on line 1051 is unused and should be removed.

🔎 Proposed fix
     def _apply_class_name_affix(
         self,
         name: str,
         model_type: str = "model",
-        is_root: bool = False,  # noqa: FBT001, FBT002
+        is_root: bool = False,
     ) -> str:
🧹 Nitpick comments (2)
src/datamodel_code_generator/reference.py (2)

1101-1110: Remove unused noqa directives.

Multiple noqa directives for FBT001, FBT002, PLR0913, and PLR0917 are unused according to static analysis and should be removed for cleaner code.

🔎 Proposed fix
-    def get_class_name(  # noqa: PLR0913, PLR0917
+    def get_class_name(
         self,
         name: str,
-        unique: bool = True,  # noqa: FBT001, FBT002
+        unique: bool = True,
         reserved_name: str | None = None,
-        singular_name: bool = False,  # noqa: FBT001, FBT002
+        singular_name: bool = False,
         singular_name_suffix: str | None = None,
         model_type: str = "model",
-        is_root: bool = False,  # noqa: FBT001, FBT002
-        skip_affix: bool = False,  # noqa: FBT001, FBT002
+        is_root: bool = False,
+        skip_affix: bool = False,
     ) -> ClassName:

549-550: Remove unused noqa directives.

The # noqa: FBT001, FBT002 directives on lines 549-550 are unused and should be removed.

🔎 Proposed fix
-        skip_affix_for_root: bool = False,  # noqa: FBT001, FBT002
-        skip_generator_and_affix: bool = False,  # noqa: FBT001, FBT002
+        skip_affix_for_root: bool = False,
+        skip_generator_and_affix: bool = False,
     ) -> None:
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f220c81 and 3ccbe07.

📒 Files selected for processing (2)
  • src/datamodel_code_generator/parser/base.py
  • src/datamodel_code_generator/reference.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:22.481Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43
Timestamp: 2025-12-25T09:22:22.481Z
Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.

Applied to files:

  • src/datamodel_code_generator/reference.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.

Applied to files:

  • src/datamodel_code_generator/reference.py
🧬 Code graph analysis (2)
src/datamodel_code_generator/parser/base.py (1)
src/datamodel_code_generator/model/base.py (2)
  • class_name (848-850)
  • class_name (853-857)
src/datamodel_code_generator/reference.py (2)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/model/base.py (5)
  • name (827-829)
  • path (908-910)
  • class_name (848-850)
  • class_name (853-857)
  • duplicate_name (832-834)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/reference.py

549-549: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


550-550: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1051-1051: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1101-1101: Unused noqa directive (non-enabled: PLR0913, PLR0917)

Remove unused noqa directive

(RUF100)


1104-1104: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1106-1106: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1109-1109: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1110-1110: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.10 on macOS
  • GitHub Check: Analyze (python)
  • GitHub Check: benchmarks
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.13 on macOS
  • GitHub Check: 3.13 on Windows
🔇 Additional comments (6)
src/datamodel_code_generator/reference.py (4)

597-609: LGTM! Validation logic is sound.

The validation correctly ensures:

  • class_name_prefix is a complete valid Python identifier
  • class_name_suffix can be concatenated (tested with "A" prefix) to form a valid identifier
  • Clear error messages guide users to fix configuration issues

838-844: LGTM! Correct deferral of scope-dependent affixes.

The logic correctly defers affix application when the scope is not All, since add_ref() doesn't have access to model_type yet. The affix will be applied later in add() when the actual model type is known.


1081-1099: LGTM! Well-documented method for GraphQL parser.

The method correctly provides affix application without uniqueness checks, as needed by the GraphQL parser. The inline comments clearly document the intentional differences in behavior (no singularization, no dot-path splitting).


1156-1180: LGTM! Correct addition of model_type parameter.

The model_type parameter correctly enables type-specific suffix selection via _get_suffix_for_model_type(), supporting the configurable duplicate name suffix feature.

src/datamodel_code_generator/parser/base.py (2)

896-900: LGTM! Correct integration of affix configuration.

The affix-related parameters are correctly passed from config to ModelResolver. The derivation of skip_affix_for_root from config.class_name is not None is logical—when users specify an explicit root class name via --class-name, affixes should not be applied to that root model.


1131-1137: LGTM! Correct use of skip_generator_and_affix for duplicate resolution.

Setting skip_generator_and_affix=True is correct here. When resolving duplicate class names within a module (line 1142), only uniqueness transformations should be applied, not class name generation or affixes, to preserve the intended names.

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

♻️ Duplicate comments (1)
src/datamodel_code_generator/reference.py (1)

1045-1077: Scope-based filtering logic is correct.

The implementation correctly applies affixes according to the configured scope (All, Models, or Enums) and respects the root handling flag. The logic is sound and the filtering conditions are accurate.

Note: The unused noqa directive on line 1049 was already flagged in a previous review.

🧹 Nitpick comments (2)
src/datamodel_code_generator/reference.py (2)

546-607: Solid validation logic for affix configuration.

The initialization correctly validates that prefix/suffix are valid Python identifier components. The validation approach is sound:

  • Prefix must be a complete identifier
  • Suffix validation using f"A{self.class_name_suffix}" ensures it can be safely appended

One minor note: Line 549 has an unused noqa directive that could be removed.

🔎 Optional: Remove unused noqa directive
-        skip_affix_for_root: bool = False,  # noqa: FBT001, FBT002
+        skip_affix_for_root: bool = False,

1099-1144: Correct transformation order and control flow.

The updates properly integrate affix application into the class name generation pipeline with the correct ordering:

  1. Class name generator
  2. Singularization (if requested)
  3. Affix application (unless skipped)
  4. Reserved name check
  5. Uniqueness resolution

The logic correctly propagates model_type and is_root through the transformations.

Minor note: Several unused noqa directives could be cleaned up (lines 1099, 1102, 1104, 1107, 1108).

🔎 Optional: Remove unused noqa directives
-    def get_class_name(  # noqa: PLR0913, PLR0917
+    def get_class_name(
         self,
         name: str,
-        unique: bool = True,  # noqa: FBT001, FBT002
+        unique: bool = True,
         reserved_name: str | None = None,
-        singular_name: bool = False,  # noqa: FBT001, FBT002
+        singular_name: bool = False,
         singular_name_suffix: str | None = None,
         model_type: str = "model",
-        is_root: bool = False,  # noqa: FBT001, FBT002
-        skip_affix: bool = False,  # noqa: FBT001, FBT002
+        is_root: bool = False,
+        skip_affix: bool = False,
     ) -> ClassName:
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1252dfd and c0aad40.

📒 Files selected for processing (1)
  • src/datamodel_code_generator/reference.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:22.481Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43
Timestamp: 2025-12-25T09:22:22.481Z
Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.

Applied to files:

  • src/datamodel_code_generator/reference.py
📚 Learning: 2025-12-18T13:43:16.235Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:16.235Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.

Applied to files:

  • src/datamodel_code_generator/reference.py
🧬 Code graph analysis (1)
src/datamodel_code_generator/reference.py (2)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/model/base.py (5)
  • name (827-829)
  • path (908-910)
  • class_name (848-850)
  • class_name (853-857)
  • duplicate_name (832-834)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/reference.py

549-549: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1049-1049: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1099-1099: Unused noqa directive (non-enabled: PLR0913, PLR0917)

Remove unused noqa directive

(RUF100)


1102-1102: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1104-1104: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1107-1107: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)


1108-1108: Unused noqa directive (non-enabled: FBT001, FBT002)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: 3.13 on macOS
  • GitHub Check: 3.10 on macOS
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.13 on Windows
  • GitHub Check: Analyze (python)
  • GitHub Check: benchmarks
🔇 Additional comments (5)
src/datamodel_code_generator/reference.py (5)

38-38: LGTM: Import addition supports new affix scope feature.

The import of ClassNameAffixScope is correctly placed and necessary for the class name affix functionality.


836-842: Correct deferral of affix application when scope-dependent.

The logic correctly identifies when affix application must be deferred because the model_type is unknown at add_ref time but needed for scope-based filtering (Models vs Enums). The affix will be applied later during add() when the model_type is known.


940-997: Well-designed reprocessing logic for deferred affix application.

The changes correctly handle the two-phase affix application:

  1. add_ref() defers affix when scope-dependent and model_type is unknown
  2. add() applies the correct affix with the now-known model_type

The root detection logic (lines 944-946) correctly identifies root schemas, and the early-return conditions (lines 961-963) appropriately skip reprocessing when unnecessary.


1079-1097: Appropriate specialized method for GraphQL parser.

The get_affixed_name method provides a focused interface for applying class name transformations without uniqueness resolution or singularization. This design correctly serves the GraphQL parser's needs while keeping the more complex get_class_name method unchanged.

The docstring clearly documents the intentional limitations, which helps prevent misuse.


1146-1146: LGTM: Signature update supports type-specific suffixes.

The model_type parameter addition enables type-specific duplicate name resolution, correctly integrating with the existing suffix map functionality.

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

🧹 Nitpick comments (1)
src/datamodel_code_generator/__main__.py (1)

517-519: Clean up unused noqa directives.

The field declarations are correct, but the # noqa: UP045 directives on lines 517-518 are unnecessary and should be removed for cleaner code.

🔎 Proposed fix
-    class_name_prefix: Optional[str] = None  # noqa: UP007, UP045
-    class_name_suffix: Optional[str] = None  # noqa: UP007, UP045
+    class_name_prefix: Optional[str] = None  # noqa: UP007
+    class_name_suffix: Optional[str] = None  # noqa: UP007
     class_name_affix_scope: ClassNameAffixScope = ClassNameAffixScope.All
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0aad40 and a89147a.

📒 Files selected for processing (1)
  • src/datamodel_code_generator/__main__.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/enums.py (1)
  • ClassNameAffixScope (131-141)
src/datamodel_code_generator/util.py (1)
  • field_validator (175-191)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

517-517: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)


518-518: Unused noqa directive (non-enabled: UP045)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: 3.13 on Windows
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.14 on Windows
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: py312-black23 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: benchmarks
  • GitHub Check: Analyze (python)
🔇 Additional comments (4)
src/datamodel_code_generator/__main__.py (4)

57-57: LGTM!

The import of ClassNameAffixScope is correctly positioned and follows the existing import pattern.


399-407: LGTM!

The field validator correctly handles coercion from None and str to ClassNameAffixScope, with appropriate use of mode="before" for pre-validation transformation. The logic properly defaults None to ClassNameAffixScope.All, consistent with the field definition.


475-483: LGTM!

The Pydantic v1 field validator mirrors the v2 implementation correctly, ensuring consistent behavior across both Pydantic versions.


896-898: LGTM!

The new parameters are correctly passed to the generate() function, following the established pattern and logically grouped with the related class_name parameter.

@koxudaxi koxudaxi merged commit 0c3b510 into main Jan 1, 2026
39 checks passed
@koxudaxi koxudaxi deleted the feature/class-name-prefix-suffix branch January 1, 2026 15:14
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 1, 2026

Breaking Change Analysis

Result: No breaking changes detected

Reasoning: This PR adds three new CLI options (--class-name-prefix, --class-name-suffix, --class-name-affix-scope) and a new ClassNameAffixScope enum. All new features are opt-in with None/empty defaults. When the new options are not specified, the code behaves exactly as before: prefix and suffix default to empty strings, and _apply_class_name_affix() returns names unchanged. No Jinja2 templates were modified, no default behaviors were changed, and existing users will see identical generated output without any action required.


This analysis was performed by Claude Code Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 2, 2026

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

1 participant