Skip to content

Add --class-decorators option for custom model decorators#2760

Merged
koxudaxi merged 5 commits intomainfrom
feature/class-decorators
Dec 23, 2025
Merged

Add --class-decorators option for custom model decorators#2760
koxudaxi merged 5 commits intomainfrom
feature/class-decorators

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Dec 23, 2025

Fixes: #2358

Summary by CodeRabbit

  • New Features

    • Added a --class-decorators CLI option to apply custom decorators to generated model classes; accepts comma-separated lists and auto-adds a leading @ when omitted. Works across supported output model types and pairs with additional-imports.
  • Documentation

    • New docs and cross-references with examples, usage notes (multiple decorators, optional @ prefix), and integration guidance for various model targets.
  • Tests

    • Added comprehensive tests covering CLI, parsing, prefix normalization, empty-entry handling, and multiple output types.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 23, 2025

Walkthrough

Adds a new --class-decorators CLI option and corresponding API parameter that are validated, normalized, and threaded into the generation pipeline so parser implementations can apply one or more class decorators to generated model classes.

Changes

Cohort / File(s) Summary
Documentation
docs/class-decorators.md, docs/cli-reference/index.md, docs/cli-reference/quick-reference.md, docs/cli-reference/template-customization.md
New docs and cross-references documenting --class-decorators, usage examples (including dataclasses_json), --additional-imports notes, and index updates.
CLI & Config
src/datamodel_code_generator/arguments.py, src/datamodel_code_generator/cli_options.py, src/datamodel_code_generator/__main__.py
Added --class-decorators CLI argument, CLI metadata entry, new class_decorators: Optional[list[str]] on Config, and a pre-validation validate_class_decorators that splits, trims, filters empty items, and ensures @ prefix. Config wired into run/generation.
Public API
src/datamodel_code_generator/__init__.py
generate() signature extended with `class_decorators: list[str]
Parser base & subclasses
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/parser/openapi.py
Parser base accepts/stores class_decorators. GraphQL/JSON Schema/OpenAPI parsers accept and forward the parameter. _create_data_model now injects decorators from self.class_decorators when none provided in kwargs.
Tests / Fixtures
tests/main/test_main_general.py, tests/parser/test_graphql.py, tests/parser/test_jsonschema.py, tests/data/expected/main/*class_decorators*.py
Added unit and CLI tests covering decorator application, auto-@ prefixing, empty-entry filtering, multi-output types. New expected generated-file fixtures for dataclasses, pydantic (v1/v2), and msgspec outputs.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CLI as CLI (--class-decorators)
  participant Config as Config (validated)
  participant Generate as generate()
  participant Parser as Parser (base / subclass)
  participant DataModel as DataModelFactory/_create_data_model

  CLI->>Config: parse args (comma-separated string)
  Note right of Config `#DFF2E1`: validate_class_decorators\nsplit, trim, add '@'
  Config->>Generate: run_generate_from_config(config)
  Generate->>Parser: instantiate(..., class_decorators=list)
  Parser->>DataModel: _create_data_model(..., **kwargs)
  alt no explicit decorators in kwargs
    Parser->>DataModel: inject decorators=self.class_decorators
  end
  DataModel-->>Generate: DataModel source with decorators applied
  Generate-->>CLI: write generated files
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

safe-to-fix

Suggested reviewers

  • ilovelinux

Pre-merge checks and finishing touches

✅ 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 'Add --class-decorators option for custom model decorators' accurately reflects the main change: introducing a new CLI option for applying custom decorators to generated model classes.
Linked Issues check ✅ Passed The PR implements the feature requested in #2358: adding support for custom decorators (including dataclasses_json) to generated models to enable field casing transformations without manual post-processing.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the --class-decorators feature: CLI argument parsing, documentation, core generation logic, and comprehensive tests across multiple output types.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 feature/class-decorators

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.

🤖 Generated by GitHub Actions
Comment thread src/datamodel_code_generator/__main__.py Dismissed
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 23, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.47%. Comparing base (40cd8e2) to head (27a944a).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2760   +/-   ##
=======================================
  Coverage   99.47%   99.47%           
=======================================
  Files          85       85           
  Lines       12573    12627   +54     
  Branches     1500     1506    +6     
=======================================
+ Hits        12507    12561   +54     
  Misses         35       35           
  Partials       31       31           
Flag Coverage Δ
unittests 99.47% <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.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 23, 2025

CodSpeed Performance Report

Merging #2760 will not alter performance

Comparing feature/class-decorators (27a944a) with main (f9a185b)1

Summary

✅ 73 untouched
⏩ 10 skipped2

Footnotes

  1. No successful run was found on main (40cd8e2) during the generation of this report, so f9a185b was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 10 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

🧹 Nitpick comments (6)
src/datamodel_code_generator/arguments.py (1)

722-729: New --class-decorators CLI option definition looks consistent

Argument wiring (name, help text, type, default) matches existing patterns like --additional-imports and the docs description; no functional issues from this definition itself. If you ever reshuffle groups for CLI help readability, consider moving both --additional-imports and --class-decorators into template_options, but that’s purely cosmetic.

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

689-689: Parser now exposes class_decorators cleanly

Adding the class_decorators kw-only parameter and storing it on self is straightforward and keeps the API symmetric with additional_imports. One minor defensive improvement would be to copy the list to avoid accidental external mutation:

self.class_decorators: list[str] = list(class_decorators) if class_decorators else []

Not required, but reduces aliasing surprises if callers reuse the same list instance.

Also applies to: 808-809

docs/class-decorators.md (1)

1-116: Good end‑to‑end documentation of --class-decorators

The examples and usage notes (including @ prefix handling and --additional-imports interplay) accurately reflect the feature and tests.

You might optionally:

  • Rename the bold labels like **schema.json** / **Generated model.py** to proper sub‑headings to satisfy MD036.
  • Change “type checking decorators” to “type‑checking decorators” for the LanguageTool nit.
src/datamodel_code_generator/__main__.py (1)

241-255: Config normalization and wiring for class_decorators looks good; consider small robustness and lint tweaks

  • The validate_class_decorators root validator correctly:
    • Accepts a comma‑separated string.
    • Trims entries.
    • Skips empty entries.
    • Adds @ when missing, matching the CLI tests and docs.
  • The Config.class_decorators field and the run_generate_from_config call into generate(class_decorators=...) complete the CLI→Config→generate wiring.

Two minor follow‑ups you might consider:

  1. Handle list input defensively
    If someone sets class_decorators as a list in pyproject.toml or passes a dict into Config.parse_obj directly, class_decorators.split(",") will raise. You could mirror additional_imports but make it tolerant of both str and Sequence[str]:

    Suggested more robust validator
    @model_validator(mode="before")
    -def validate_class_decorators(cls, values: dict[str, Any]) -> dict[str, Any]:  # noqa: N805
    -    """Validate and split class decorators, adding @ prefix if missing."""
    -    class_decorators = values.get("class_decorators")
    -    if class_decorators is not None:
    -        decorators = []
    -        for raw_decorator in class_decorators.split(","):
    -            stripped = raw_decorator.strip()
    -            if stripped:
    -                if not stripped.startswith("@"):
    -                    stripped = f"@{stripped}"
    -                decorators.append(stripped)
    -        values["class_decorators"] = decorators
    -    return values
    +def validate_class_decorators(cls, values: dict[str, Any]) -> dict[str, Any]:
    +    """Normalize class_decorators to a list of '@'-prefixed strings."""
    +    raw = values.get("class_decorators")
    +    if raw is None:
    +        return values
    +
    +    if isinstance(raw, str):
    +        raw_items = raw.split(",")
    +    elif isinstance(raw, (list, tuple)):
    +        raw_items = raw
    +    else:
    +        # Leave unexpected types untouched and let pydantic report type errors.
    +        return values
    +
    +    decorators: list[str] = []
    +    for item in raw_items:
    +        stripped = str(item).strip()
    +        if not stripped:
    +            continue
    +        if not stripped.startswith("@"):
    +            stripped = f"@{stripped}"
    +        decorators.append(stripped)
    +
    +    values["class_decorators"] = decorators
    +    return values
  2. Clean up new unused noqa comments flagged by Ruff
    Since N805 / UP045 aren’t enabled, the new # noqa comments on the validator signature and class_decorators field can be dropped to satisfy RUF100, or you can enable those checks globally if you want to keep them.

If you want to double‑check how class_decorators is expected to be represented in pyproject.toml (string vs list), please confirm against your existing additional_imports / custom_formatters docs and usage.

Also applies to: 400-401, 710-712

tests/main/test_main_general.py (1)

191-285: Integration coverage for --class-decorators is solid

  • test_class_decorators verifies the programmatic generate(..., class_decorators=[...], additional_imports=[...]) path against the golden file.
  • CLI tests exercise:
    • Basic --class-decorators wiring,
    • Auto‑adding the @ prefix,
    • Ignoring empty entries in a comma‑separated list.

This gives good end‑to‑end confidence for both CLI and API usage. If you want even more assurance later, an additional CLI test with multiple decorators could validate ordering, but it’s not strictly necessary given current parser tests.

src/datamodel_code_generator/__init__.py (1)

417-417: Top‑level generate() API now correctly exposes class_decorators

Adding class_decorators as a kw‑only arg and threading it through to the parser constructor cleanly exposes the new feature to library users without breaking existing callers.

You might optionally mirror the CLI behavior by normalizing entries here as well (ensure leading @ and trim whitespace) so that programmatic callers can safely pass plain decorator names, but the current contract is clear and consistent if you document that generate() expects fully‑formed decorator strings.

Also applies to: 672-673

📜 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 7b5f08f and 5895823.

📒 Files selected for processing (16)
  • docs/class-decorators.md
  • docs/cli-reference/index.md
  • docs/cli-reference/quick-reference.md
  • docs/cli-reference/template-customization.md
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.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/parser/openapi.py
  • tests/data/expected/main/class_decorators_dataclass.py
  • tests/main/test_main_general.py
  • tests/parser/test_graphql.py
  • tests/parser/test_jsonschema.py
🧰 Additional context used
🧬 Code graph analysis (4)
tests/parser/test_graphql.py (2)
src/datamodel_code_generator/parser/graphql.py (1)
  • GraphQLParser (73-699)
src/datamodel_code_generator/model/dataclass.py (1)
  • DataClass (46-117)
tests/parser/test_jsonschema.py (2)
tests/main/test_main_general.py (1)
  • test_class_decorators (192-203)
src/datamodel_code_generator/parser/jsonschema.py (1)
  • JsonSchemaParser (518-3265)
tests/data/expected/main/class_decorators_dataclass.py (1)
src/datamodel_code_generator/model/base.py (1)
  • name (730-732)
src/datamodel_code_generator/__main__.py (1)
src/datamodel_code_generator/util.py (4)
  • model_validator (57-62)
  • model_validator (66-72)
  • model_validator (76-80)
  • model_validator (83-114)
🪛 LanguageTool
docs/class-decorators.md

[grammar] ~106-~106: Use a hyphen to join words.
Context: ...havior - TypedDict: Add runtime type checking decorators - msgspec.Struct...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
docs/class-decorators.md

15-15: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


37-37: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


65-65: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

242-242: Unused noqa directive (non-enabled: N805)

Remove unused noqa directive

(RUF100)


400-400: 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). (9)
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.10 on macOS
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.10 on Windows
  • GitHub Check: Analyze (python)
  • GitHub Check: benchmarks
🔇 Additional comments (12)
docs/cli-reference/quick-reference.md (1)

112-116: Quick-reference wiring for --class-decorators is consistent

The new entries under “Template Customization” and in the alphabetical index are correctly linked and categorized; they match the detailed template-customization docs and the CLI metadata.

Also applies to: 188-189

src/datamodel_code_generator/cli_options.py (1)

175-183: CLI metadata for --class-decorators is correctly registered

CLI_OPTION_META now includes --class-decorators under the TEMPLATE category, which aligns with how the docs present it and with the argparse definition; this should keep the sync tests and generated docs happy.

docs/cli-reference/template-customization.md (1)

5-9: --class-decorators documentation is clear and aligned with behavior

The new option row, cross-reference from --additional-imports, and the dedicated --class-decorators section (usage plus dataclasses_json example) accurately describe how to apply custom decorators and how it interacts with imports and --output-model-type. This should be sufficient for users to implement the Issue #2358 workflow without extra post-processing.

Also applies to: 36-37, 113-182

tests/parser/test_graphql.py (1)

95-106: GraphQL parser test appropriately covers class_decorators propagation

The new test mirrors the existing _create_data_model dataclass-arguments test and cleanly verifies that parser-level class_decorators are applied to the resulting DataClass. This gives good, focused coverage of the new behavior with minimal coupling.

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

15-15: CLI index wiring for --class-decorators looks consistent

Template Customization count and the new --class-decorators entry/anchor are correctly updated and aligned with existing patterns.

Also applies to: 43-43

tests/data/expected/main/class_decorators_dataclass.py (1)

1-17: Golden dataclass fixture matches intended decorator output

Import and decorator ordering (@dataclass_json above @dataclass) look correct and are consistent with the new tests.

tests/parser/test_jsonschema.py (1)

474-489: Parser tests correctly pin class_decorators behavior

These tests clearly establish that:

  • class_decorators is stored as‑is when provided.
  • The default is an empty list rather than None when omitted.

That matches the intended parser API and will catch regressions in base‐parser initialization.

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

192-193: OpenAPI parser now correctly participates in class_decorators flow

Adding class_decorators to the OpenAPIParser constructor and forwarding it to super().__init__ is consistent with the other parsers and keeps the signature backward‑compatible.

Also applies to: 298-299

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

112-112: LGTM! Clean parameter propagation.

The class_decorators parameter is correctly added to the __init__ signature and properly forwarded to the base class. The type annotation list[str] | None = None is appropriate, and this follows the standard pattern used by other parameters in this parser.

Also applies to: 214-214


361-363: LGTM! Solid decorator injection logic.

The implementation correctly:

  • Checks if decorators aren't already provided in kwargs (respecting explicit parameters)
  • Verifies self.class_decorators is truthy (handles both None and empty list cases)
  • Creates a defensive copy with list(self.class_decorators) to prevent mutation issues

This ensures that class-level decorators from the parser configuration are applied to generated models when no explicit decorators are specified.

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

534-534: LGTM! Consistent with GraphQL parser.

The class_decorators parameter follows the same pattern as the GraphQL parser implementation, maintaining consistency across the codebase. Parameter addition and forwarding to the base class are implemented correctly.

Also applies to: 637-637


1755-1757: LGTM! Decorator injection mirrors GraphQL parser implementation.

The _create_data_model method correctly injects decorators using the same defensive pattern as the GraphQL parser:

  • Respects explicit decorators in kwargs (explicit trumps implicit)
  • Guards against None and empty list with the truthy check
  • Creates a protective copy to prevent shared mutable state

The consistency between parsers ensures uniform behavior when applying class decorators across different schema types.

@koxudaxi koxudaxi force-pushed the feature/class-decorators branch from 548df39 to bf60ea8 Compare December 23, 2025 14:31
@koxudaxi koxudaxi force-pushed the feature/class-decorators branch from bf60ea8 to e5bc109 Compare December 23, 2025 14:35
@koxudaxi koxudaxi enabled auto-merge (squash) December 23, 2025 14:39
@koxudaxi koxudaxi merged commit 419b1c2 into main Dec 23, 2025
33 of 35 checks passed
@koxudaxi koxudaxi deleted the feature/class-decorators branch December 23, 2025 14:42
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 (2)
src/datamodel_code_generator/__main__.py (2)

241-254: Consider removing unused noqa directive.

The static analysis tool indicates that the noqa: N805 directive on line 242 is unused. This suggests the linting rule it's meant to suppress is not enabled in your configuration.

🔎 Suggested cleanup
     @model_validator(mode="before")
-    def validate_class_decorators(cls, values: dict[str, Any]) -> dict[str, Any]:  # noqa: N805
+    def validate_class_decorators(cls, values: dict[str, Any]) -> dict[str, Any]:
         """Validate and split class decorators, adding @ prefix if missing."""

401-401: Consider removing unused noqa directive.

The static analysis tool indicates that the noqa: UP045 directive on line 401 is unused. This suggests the rule it's meant to suppress is not enabled in your configuration.

🔎 Suggested cleanup
-    class_decorators: Optional[list[str]] = None  # noqa: UP045
+    class_decorators: Optional[list[str]] = 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 5895823 and 27a944a.

📒 Files selected for processing (17)
  • docs/cli-reference/index.md
  • docs/cli-reference/quick-reference.md
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/__main__.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/cli_options.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/parser/openapi.py
  • tests/data/expected/main/class_decorators_dataclasses_dataclass.py
  • tests/data/expected/main/class_decorators_msgspec_Struct.py
  • tests/data/expected/main/class_decorators_pydantic_BaseModel.py
  • tests/data/expected/main/class_decorators_pydantic_v2_BaseModel.py
  • tests/data/expected/main/class_decorators_pydantic_v2_dataclass.py
  • tests/main/test_main_general.py
  • tests/parser/test_jsonschema.py
🚧 Files skipped from review as they are similar to previous changes (8)
  • docs/cli-reference/quick-reference.md
  • tests/parser/test_jsonschema.py
  • tests/main/test_main_general.py
  • src/datamodel_code_generator/parser/base.py
  • src/datamodel_code_generator/parser/openapi.py
  • src/datamodel_code_generator/cli_options.py
  • src/datamodel_code_generator/arguments.py
  • src/datamodel_code_generator/init.py
🧰 Additional context used
🧬 Code graph analysis (5)
tests/data/expected/main/class_decorators_pydantic_BaseModel.py (2)
tests/data/expected/main/class_decorators_dataclasses_dataclass.py (1)
  • User (14-17)
tests/data/expected/main/class_decorators_pydantic_v2_BaseModel.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_v2_dataclass.py (5)
tests/data/expected/main/class_decorators_dataclasses_dataclass.py (1)
  • User (14-17)
tests/data/expected/main/class_decorators_msgspec_Struct.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_BaseModel.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_v2_BaseModel.py (1)
  • User (12-15)
src/datamodel_code_generator/model/base.py (1)
  • name (730-732)
tests/data/expected/main/class_decorators_msgspec_Struct.py (4)
tests/data/expected/main/class_decorators_dataclasses_dataclass.py (1)
  • User (14-17)
tests/data/expected/main/class_decorators_pydantic_BaseModel.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_v2_BaseModel.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_v2_dataclass.py (1)
  • User (14-17)
tests/data/expected/main/class_decorators_dataclasses_dataclass.py (4)
tests/data/expected/main/class_decorators_msgspec_Struct.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_BaseModel.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_v2_BaseModel.py (1)
  • User (12-15)
tests/data/expected/main/class_decorators_pydantic_v2_dataclass.py (1)
  • User (14-17)
src/datamodel_code_generator/__main__.py (1)
src/datamodel_code_generator/util.py (4)
  • model_validator (57-62)
  • model_validator (66-72)
  • model_validator (76-80)
  • model_validator (83-114)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__main__.py

242-242: Unused noqa directive (non-enabled: N805)

Remove unused noqa directive

(RUF100)


401-401: 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). (12)
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.13 on Ubuntu
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.13 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: benchmarks
  • GitHub Check: Analyze (python)
🔇 Additional comments (12)
docs/cli-reference/index.md (2)

15-15: Template Customization option count correctly incremented.

The count has been properly updated from 16 to 17 to reflect the addition of the new --class-decorators option.


44-44: New option correctly positioned in alphabetical index.

The --class-decorators option is properly placed in alphabetical order between --check and --class-name, and the link format is consistent with all other options in the index. The #class-decorators anchor section exists in template-customization.md.

tests/data/expected/main/class_decorators_msgspec_Struct.py (1)

1-15: Test fixture looks correct for msgspec.Struct with decorator.

The expected output properly demonstrates the class decorator feature applied to msgspec models. The decorator placement and imports are correct.

tests/data/expected/main/class_decorators_dataclasses_dataclass.py (1)

1-17: Test fixture looks correct for standard dataclass with decorator.

The expected output properly demonstrates the class decorator feature applied to standard Python dataclasses. The decorator ordering (@my_decorator before @DataClass) is correct.

src/datamodel_code_generator/__main__.py (1)

695-817: Proper integration of class_decorators into generation pipeline.

The class_decorators configuration is correctly validated, stored, and propagated through to the generate() function. The validator properly handles comma-separated input, strips whitespace, filters empty entries, and ensures the @ prefix is present.

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

100-218: Clean integration of class_decorators parameter.

The class_decorators parameter is properly added to the GraphQLParser constructor and forwarded to the base class. The type hint and default value are appropriate.


365-389: Decorator injection logic is well-implemented.

The _create_data_model method correctly injects class decorators when not explicitly provided in kwargs. Creating a copy of the decorators list avoids potential mutation issues.

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

525-642: Clean integration of class_decorators parameter.

The class_decorators parameter is properly added to the JsonSchemaParser constructor and forwarded to the base class, consistent with the GraphQLParser implementation.


1763-1787: Decorator injection logic is consistent and correct.

The _create_data_model method follows the same pattern as GraphQLParser, ensuring consistent behavior across different parser implementations.

tests/data/expected/main/class_decorators_pydantic_v2_dataclass.py (1)

1-17: Test fixture looks correct for Pydantic v2 dataclass with decorator.

The expected output properly demonstrates the class decorator feature applied to Pydantic v2 dataclass models. The imports and decorator placement are correct.

tests/data/expected/main/class_decorators_pydantic_v2_BaseModel.py (1)

1-15: Test fixture looks correct for Pydantic v2 BaseModel with decorator.

The expected output properly demonstrates the class decorator feature applied to Pydantic v2 BaseModel classes. The decorator is correctly placed before the class definition.

tests/data/expected/main/class_decorators_pydantic_BaseModel.py (1)

1-15: Test fixture looks correct for Pydantic BaseModel with decorator.

The expected output properly demonstrates the class decorator feature applied to Pydantic BaseModel classes. This fixture complements the v2 variant to ensure compatibility across Pydantic versions.

@github-actions
Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: No breaking changes detected

Reasoning: This PR adds a new optional --class-decorators CLI option and corresponding class_decorators parameter to the Python API. The changes are purely additive:

  1. Code Generation Changes: No changes to existing generated code output. The new decorators are only added when the --class-decorators option is explicitly used. Existing users without this option will see no change in output.

  2. Custom Template Update Required: No template changes are required. The Jinja2 templates already support a decorators variable (e.g., {% for decorator in decorators %} exists in BaseModel.jinja2, dataclass.jinja2, msgspec.jinja2, etc.). The PR simply populates this existing variable when the new option is provided.

  3. API/CLI Changes: The new --class-decorators CLI option and class_decorators Python API parameter are purely additive. All existing parameters and behaviors remain unchanged. The new parameter is optional with a default value of None.

  4. Default Behavior Changes: No defaults are changed. When class_decorators is not specified, the behavior is identical to before (no decorators are added beyond existing behavior like @dataclass).

  5. Python Version Changes: No Python version support changes.

  6. Error Handling Changes: No changes to error handling behavior.

The PR follows proper additive patterns: new optional CLI argument, new optional Python API parameter with default None, and leverages existing template infrastructure without modification.


This analysis was performed by Claude Code Action

koxudaxi added a commit that referenced this pull request Dec 23, 2025
* Add --class-decorators option for custom model decorators

* docs: update CLI reference documentation

🤖 Generated by GitHub Actions

* Add test for empty entries in class-decorators

* Add parameterized e2e test for class-decorators across all output types

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
koxudaxi added a commit that referenced this pull request Dec 23, 2025
* Add --generate-prompt option for LLM consultation

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

* Add --class-decorators option for custom model decorators (#2760)

* Add --class-decorators option for custom model decorators

* docs: update CLI reference documentation

🤖 Generated by GitHub Actions

* Add test for empty entries in class-decorators

* Add parameterized e2e test for class-decorators across all output types

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Merge main and update expected files

* Replace expected file comparisons with structural assertions

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

* Add usage examples for --generate-prompt (pipe to LLM tools, clipboard)

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

* Fix escape sequence handling in truncation logic

* Add --generate-prompt manual docs with CLI tools and clipboard examples

* Add llm-integration.md with detailed docs, simplify cli-reference

* Fix CLI tool flags and link paths in LLM integration docs

* Add LLM Integration to navigation menu

* Remove redundant paste instructions

* Add LLM integration to Common Recipes section

* Move LLM recipe to top, remove snake-case recipe

* Update CI/CD recipe to show GitHub Action example

* Add script to update GitHub Action version in docs during CI build

* Fix grammar: type checking -> type-checking

* Fix ruff errors: remove shebang, fix line length

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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.

feature: adding dataclasses_json

2 participants