Skip to content

Commit b760b64

Browse files
authored
Merge branch 'main' into required-nullable-annotated
2 parents c23fa2f + 94b081c commit b760b64

324 files changed

Lines changed: 10700 additions & 274 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/readme.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Update README
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'src/datamodel_code_generator/**'
8+
pull_request:
9+
branches: [main]
10+
paths:
11+
- 'src/datamodel_code_generator/**'
12+
13+
permissions:
14+
contents: write
15+
16+
jobs:
17+
update-readme:
18+
if: github.event_name == 'push' || !github.event.pull_request.head.repo.fork
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
ref: ${{ github.head_ref || github.ref }}
25+
token: ${{ secrets.PAT }}
26+
- name: Install the latest version of uv
27+
uses: astral-sh/setup-uv@v5
28+
- name: Install tox
29+
run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv
30+
- name: Setup environment
31+
run: tox run -vv --notest --skip-missing-interpreters false -e readme
32+
env:
33+
UV_PYTHON_PREFERENCE: "only-managed"
34+
- name: Update README
35+
run: .tox/readme/bin/python scripts/update_command_help_on_markdown.py
36+
- name: Commit and push if changed
37+
run: |
38+
git config user.name "github-actions[bot]"
39+
git config user.email "github-actions[bot]@users.noreply.github.com"
40+
git add README.md docs/index.md
41+
git diff --staged --quiet || git commit -m "docs: update command help in README
42+
43+
🤖 Generated by GitHub Actions"
44+
git push

.github/workflows/test.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ jobs:
127127
- dev
128128
- docs
129129
- pkg_meta
130-
- readme
131130
steps:
132131
- uses: actions/checkout@v4
133132
with:

.pre-commit-config.yaml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
ci:
2+
skip: [readme]
3+
14
repos:
25
- repo: https://github.com/python-jsonschema/check-jsonschema
36
rev: 0.35.0
@@ -15,7 +18,7 @@ repos:
1518
- id: pyproject-fmt
1619
args: ["--max-supported-python=3.14"]
1720
- repo: https://github.com/astral-sh/ruff-pre-commit
18-
rev: 'v0.14.6'
21+
rev: 'v0.14.7'
1922
hooks:
2023
- id: ruff-format
2124
exclude: "^tests/data"
@@ -29,3 +32,11 @@ repos:
2932
additional_dependencies:
3033
- tomli
3134
exclude: "^tests/|^CODE_OF_CONDUCT.md"
35+
- repo: local
36+
hooks:
37+
- id: readme
38+
name: Update README command help
39+
entry: bash -c 'test -x .tox/fix/bin/python || tox run -e fix --notest -qq; .tox/fix/bin/python scripts/update_command_help_on_markdown.py'
40+
language: system
41+
files: ^(src/datamodel_code_generator/arguments\.py|README\.md|docs/index\.md)$
42+
pass_filenames: false

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ Typing customization:
381381
times.
382382
--use-annotated Use typing.Annotated for Field(). Also, `--field-constraints` option
383383
will be enabled.
384+
--use-enum-values-in-discriminator
385+
Use enum member literals in discriminator fields instead of string
386+
literals
384387
--use-generic-container-types
385388
Use generic container types for type hinting (typing.Sequence,
386389
typing.Mapping). If `--use-standard-collections` option is set, then
@@ -443,6 +446,15 @@ Field customization:
443446
docstring
444447

445448
Model customization:
449+
--all-exports-collision-strategy {error,minimal-prefix,full-prefix}
450+
Strategy for name collisions when using --all-exports-
451+
scope=recursive. ''error'': raise an error (default). ''minimal-
452+
prefix'': add module prefix only to colliding names. ''full-prefix'':
453+
add full module path prefix to colliding names.
454+
--all-exports-scope {children,recursive}
455+
Generate __all__ in __init__.py with re-exports. ''children'': export
456+
from direct child modules only. ''recursive'': export from all
457+
descendant modules.
446458
--allow-extra-fields Deprecated: Allow passing extra fields. This flag is deprecated. Use
447459
`--extra-fields=allow` instead.
448460
--allow-population-by-field-name
@@ -478,6 +490,14 @@ Model customization:
478490
Set name of models defined inline from the parent model
479491
--reuse-model Reuse models on the field when a module has the model with the same
480492
content
493+
--reuse-scope {module,tree}
494+
Scope for model reuse deduplication: module (per-file, default) or
495+
tree (cross-file with shared module). Only effective when --reuse-
496+
model is set.
497+
--shared-module-name SHARED_MODULE_NAME
498+
Name of the shared module for --reuse-scope=tree (default:
499+
"shared"). Use this option if your schema has a file named "shared".
500+
--skip-root-model Skip generating the model for the root schema element
481501
--target-python-version {3.9,3.10,3.11,3.12,3.13,3.14}
482502
target python version
483503
--treat-dot-as-module
@@ -490,7 +510,11 @@ Model customization:
490510
--use-title-as-name use titles as class names of models
491511

492512
Template customization:
493-
--aliases ALIASES Alias mapping file
513+
--aliases ALIASES Alias mapping file (JSON) for renaming fields. Supports hierarchical
514+
formats: Flat: {''field'': ''alias''} applies to all occurrences.
515+
Scoped: {''ClassName.field'': ''alias''} applies to specific class.
516+
Priority: scoped > flat. Example: {''User.name'': ''user_name'',
517+
''Address.name'': ''addr_name'', ''id'': ''id_''}
494518
--custom-file-header CUSTOM_FILE_HEADER
495519
Custom file header
496520
--custom-file-header-path CUSTOM_FILE_HEADER_PATH
@@ -520,16 +544,25 @@ OpenAPI-only options:
520544
query parameters (Only OpenAPI)
521545
--openapi-scopes {schemas,paths,tags,parameters,webhooks} [{schemas,paths,tags,parameters,webhooks} ...]
522546
Scopes of OpenAPI model generation (default: schemas)
547+
--read-only-write-only-model-type {request-response,all}
548+
Model generation for readOnly/writeOnly fields: ''request-response'' =
549+
Request/Response models only (no base model), ''all'' = Base + Request
550+
+ Response models.
523551
--strict-nullable Treat default field as a non-nullable field (Only OpenAPI)
524552
--use-operation-id-as-name
525553
use operation id of OpenAPI as class names of models
526554
--validation Deprecated: Enable validation (Only OpenAPI). this option is
527555
deprecated. it will be removed in future releases
528556

529557
General options:
558+
--check Verify generated files are up-to-date without modifying them. Exits
559+
with code 1 if differences found, 0 if up-to-date. Useful for CI to
560+
ensure generated code is committed.
530561
--debug show debug message (require "debug". `$ pip install ''datamodel-code-
531562
generator[debug]''`)
532563
--disable-warnings disable warnings
564+
--generate-cli-command
565+
Generate CLI command from pyproject.toml configuration and exit
533566
--generate-pyproject-config
534567
Generate pyproject.toml configuration from the provided CLI
535568
arguments and exit

docs/aliases.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Field Aliases
2+
3+
The `--aliases` option allows you to rename fields in the generated models. This is useful when you want to use different Python field names than those defined in the schema while preserving the original names as serialization aliases.
4+
5+
## Basic Usage
6+
7+
```bash
8+
datamodel-codegen --input schema.json --output model.py --aliases aliases.json
9+
```
10+
11+
## Alias File Format
12+
13+
The alias file is a JSON file that maps original field names to their Python aliases.
14+
15+
### Flat Format (Traditional)
16+
17+
The simplest format applies aliases to all fields with the matching name, regardless of which class they belong to:
18+
19+
```json
20+
{
21+
"id": "id_",
22+
"type": "type_",
23+
"class": "class_"
24+
}
25+
```
26+
27+
This will rename all fields named `id` to `id_`, all fields named `type` to `type_`, etc.
28+
29+
### Scoped Format (Class-Specific)
30+
31+
When you have the same field name in multiple classes but want different aliases for each, use the scoped format with `ClassName.field`:
32+
33+
```json
34+
{
35+
"User.name": "user_name",
36+
"Address.name": "address_name",
37+
"name": "default_name"
38+
}
39+
```
40+
41+
**Priority**: Scoped aliases take priority over flat aliases. In the example above:
42+
- `User.name` will be renamed to `user_name`
43+
- `Address.name` will be renamed to `address_name`
44+
- Any other class with a `name` field will use `default_name`
45+
46+
## Example
47+
48+
### Input Schema
49+
50+
```json
51+
{
52+
"type": "object",
53+
"title": "Root",
54+
"properties": {
55+
"name": {"type": "string"},
56+
"user": {
57+
"type": "object",
58+
"title": "User",
59+
"properties": {
60+
"name": {"type": "string"},
61+
"id": {"type": "integer"}
62+
}
63+
},
64+
"address": {
65+
"type": "object",
66+
"title": "Address",
67+
"properties": {
68+
"name": {"type": "string"},
69+
"city": {"type": "string"}
70+
}
71+
}
72+
}
73+
}
74+
```
75+
76+
### Alias File
77+
78+
```json
79+
{
80+
"Root.name": "root_name",
81+
"User.name": "user_name",
82+
"Address.name": "address_name"
83+
}
84+
```
85+
86+
### Generated Output
87+
88+
```python
89+
from pydantic import BaseModel, Field
90+
91+
class User(BaseModel):
92+
user_name: str | None = Field(None, alias='name')
93+
id: int | None = None
94+
95+
class Address(BaseModel):
96+
address_name: str | None = Field(None, alias='name')
97+
city: str | None = None
98+
99+
class Root(BaseModel):
100+
root_name: str | None = Field(None, alias='name')
101+
user: User | None = None
102+
address: Address | None = None
103+
```
104+
105+
## Notes
106+
107+
- The `ClassName` in scoped format must match the generated Python class name (after title conversion)
108+
- When using `--use-title-as-name`, the class name is derived from the `title` property in the schema
109+
- Aliases are applied during code generation, so the original field names are preserved as Pydantic `alias` values for proper serialization/deserialization

docs/index.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,9 @@ Typing customization:
373373
times.
374374
--use-annotated Use typing.Annotated for Field(). Also, `--field-constraints` option
375375
will be enabled.
376+
--use-enum-values-in-discriminator
377+
Use enum member literals in discriminator fields instead of string
378+
literals
376379
--use-generic-container-types
377380
Use generic container types for type hinting (typing.Sequence,
378381
typing.Mapping). If `--use-standard-collections` option is set, then
@@ -435,6 +438,15 @@ Field customization:
435438
docstring
436439

437440
Model customization:
441+
--all-exports-collision-strategy {error,minimal-prefix,full-prefix}
442+
Strategy for name collisions when using --all-exports-
443+
scope=recursive. ''error'': raise an error (default). ''minimal-
444+
prefix'': add module prefix only to colliding names. ''full-prefix'':
445+
add full module path prefix to colliding names.
446+
--all-exports-scope {children,recursive}
447+
Generate __all__ in __init__.py with re-exports. ''children'': export
448+
from direct child modules only. ''recursive'': export from all
449+
descendant modules.
438450
--allow-extra-fields Deprecated: Allow passing extra fields. This flag is deprecated. Use
439451
`--extra-fields=allow` instead.
440452
--allow-population-by-field-name
@@ -470,6 +482,14 @@ Model customization:
470482
Set name of models defined inline from the parent model
471483
--reuse-model Reuse models on the field when a module has the model with the same
472484
content
485+
--reuse-scope {module,tree}
486+
Scope for model reuse deduplication: module (per-file, default) or
487+
tree (cross-file with shared module). Only effective when --reuse-
488+
model is set.
489+
--shared-module-name SHARED_MODULE_NAME
490+
Name of the shared module for --reuse-scope=tree (default:
491+
"shared"). Use this option if your schema has a file named "shared".
492+
--skip-root-model Skip generating the model for the root schema element
473493
--target-python-version {3.9,3.10,3.11,3.12,3.13,3.14}
474494
target python version
475495
--treat-dot-as-module
@@ -482,7 +502,11 @@ Model customization:
482502
--use-title-as-name use titles as class names of models
483503

484504
Template customization:
485-
--aliases ALIASES Alias mapping file
505+
--aliases ALIASES Alias mapping file (JSON) for renaming fields. Supports hierarchical
506+
formats: Flat: {''field'': ''alias''} applies to all occurrences.
507+
Scoped: {''ClassName.field'': ''alias''} applies to specific class.
508+
Priority: scoped > flat. Example: {''User.name'': ''user_name'',
509+
''Address.name'': ''addr_name'', ''id'': ''id_''}
486510
--custom-file-header CUSTOM_FILE_HEADER
487511
Custom file header
488512
--custom-file-header-path CUSTOM_FILE_HEADER_PATH
@@ -512,16 +536,25 @@ OpenAPI-only options:
512536
query parameters (Only OpenAPI)
513537
--openapi-scopes {schemas,paths,tags,parameters,webhooks} [{schemas,paths,tags,parameters,webhooks} ...]
514538
Scopes of OpenAPI model generation (default: schemas)
539+
--read-only-write-only-model-type {request-response,all}
540+
Model generation for readOnly/writeOnly fields: ''request-response'' =
541+
Request/Response models only (no base model), ''all'' = Base + Request
542+
+ Response models.
515543
--strict-nullable Treat default field as a non-nullable field (Only OpenAPI)
516544
--use-operation-id-as-name
517545
use operation id of OpenAPI as class names of models
518546
--validation Deprecated: Enable validation (Only OpenAPI). this option is
519547
deprecated. it will be removed in future releases
520548

521549
General options:
550+
--check Verify generated files are up-to-date without modifying them. Exits
551+
with code 1 if differences found, 0 if up-to-date. Useful for CI to
552+
ensure generated code is committed.
522553
--debug show debug message (require "debug". `$ pip install ''datamodel-code-
523554
generator[debug]''`)
524555
--disable-warnings disable warnings
556+
--generate-cli-command
557+
Generate CLI command from pyproject.toml configuration and exit
525558
--generate-pyproject-config
526559
Generate pyproject.toml configuration from the provided CLI
527560
arguments and exit

0 commit comments

Comments
 (0)