๐ ๏ธ Development¶
Install the package in editable mode:
$ git clone [email protected]:koxudaxi/datamodel-code-generator.git
$ pip install -e datamodel-code-generator
๐ค Contribute¶
We are waiting for your contributions to datamodel-code-generator.
๐ How to contribute¶
## 1. Clone your fork repository
$ git clone [email protected]:<your username>/datamodel-code-generator.git
$ cd datamodel-code-generator
## 2. Install [uv](https://docs.astral.sh/uv/getting-started/installation/)
$ curl -LsSf https://astral.sh/uv/install.sh | sh
## 3. Install tox with uv
$ uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv
## 4. Create developer environment
$ tox run -e dev
.tox/dev is a Python environment you can use for development purposes
## 5. Install pre-commit hooks
$ uv tool install prek
$ prek install
## 6. Create new branch and rewrite code.
$ git checkout -b new-branch
## 7. Run unittest under Python 3.13 (you should pass all test and coverage should be 100%)
$ tox run -e 3.13
## 8. Format and lint code (will print errors that cannot be automatically fixed)
$ tox run -e fix
## 9. Check README help text is up to date
$ tox run -e readme
## 10. Check CLI documentation is up to date
$ tox run -e cli-docs
## 11. Commit and Push...
๐งช E2E test assertions¶
E2E tests that validate generated output must use the shared assertion helpers
instead of direct assert statements. The helpers compare complete generated
files, generated modules, warnings, errors, and HTTP request behavior with
consistent diffs and update hints.
Use helpers such as run_main_and_assert, run_main_url_and_assert,
create_assert_file_content, assert_output, assert_directory_content,
assert_generated_modules_output, assert_generated_file_matches_output,
assert_httpx_get_kwargs, and assert_warnings_contain where they fit. Prefer
full expected-file or inline snapshot comparisons for generated output over
substring checks.
The file-output helpers use
inline-snapshot and
external_file() internally. When an expected output file is missing, the
failure message includes the command to create it, such as
tox run -e <version> -- --inline-snapshot=create. When an existing expected
file differs from the generated output, the failure includes a diff and the
command to update it, such as
tox run -e <version> -- --inline-snapshot=fix. Review the generated files and
the resulting git diff before committing. See the inline-snapshot
--inline-snapshot pytest options
for the meaning of create and fix.
Direct assert statements are blocked in guarded test modules by
tests/test_assert_helper_usage.py. New test files are guarded by default; add
legacy or unit-focused files to
assert_helper_direct_assert_exempt_files in pyproject.toml only when they
are intentionally outside the generated-output helper policy. Use
@pytest.mark.allow_direct_assert for narrow in-file exceptions that cannot
reasonably be expressed with the shared helpers, such as external-request mock
checks or intermediate-state checks.
Parser generation state¶
Parser code must keep generated output, naming order, parse order, and
canonical model selection compatible with existing releases. ModelResolver
remains the only authority for names. Do not move name generation or parser
dispatch into the generation index.
Use GenerationStore for parser-side mutations that affect generation facts:
- Register parsed models with
generation_store.register_model(model). - Replace references with
generation_store.replace_data_type_ref(...)orgeneration_store.detach_data_type_ref(...). - Replace field or nested data types with
replace_field_type(...),replace_nested_data_type(...), orset_nested_data_types(...). - Replace fields or base classes with
set_fields(...),append_field(...),insert_field(...),remove_field(...), orset_base_classes(...). - Move or rename generated models with
move_model(...),rename_model(...), orupdate_model_reference(...).
Parser code should not directly assign data_type.reference, model.fields,
model.base_classes, model.reference.name, or call reference child mutation
helpers. Read dependency information through GenerationIndex queries instead
of using Reference.children as a reverse index.
The local pre-commit hook generation-store-usage runs
scripts/check_generation_store_usage.py and rejects common parser mutations
that bypass the store. If a new mutation helper is needed, add the method to
GENERATION_STORE_MUTATION_METHODS and update the checker tests so contributors
get an actionable message.
โ Adding a New CLI Option¶
When adding a new CLI option to datamodel-code-generator, follow these steps:
Step 1: Implement the option (Required)¶
Add the option to src/datamodel_code_generator/arguments.py:
arg_parser.add_argument(
"--my-new-option",
help="Description of what this option does",
action="store_true", # or other action type
)
Step 2: Add a test with documentation marker (Required)¶
Create a test that demonstrates the option and add the @pytest.mark.cli_doc() marker:
@pytest.mark.cli_doc(
options=["--my-new-option"],
input_schema="jsonschema/example.json", # Path relative to tests/data/
cli_args=["--my-new-option"],
golden_output="jsonschema/example_with_my_option.py", # Expected output
)
def test_my_new_option(output_file: Path) -> None:
"""Short description of what the option does.
This docstring becomes the documentation for the option.
Explain when and why users would use this option.
"""
run_main_and_assert(
input_path=JSON_SCHEMA_DATA_PATH / "example.json",
output_path=output_file,
extra_args=["--my-new-option"],
...
)
Step 3: Categorize the option (Optional)¶
By default, new options appear in "General Options". To place in a specific category, add to src/datamodel_code_generator/cli_options.py:
CLI_OPTION_META: dict[str, CLIOptionMeta] = {
...
"--my-new-option": CLIOptionMeta(
name="--my-new-option",
category=OptionCategory.MODEL, # or FIELD, TYPING, TEMPLATE, etc.
),
}
Step 4: Generate and verify documentation¶
# Regenerate CLI docs
$ pytest --collect-cli-docs -p no:xdist -q
$ python scripts/build_cli_docs.py
# Verify docs are correct
$ tox run -e cli-docs
# If you modified config.py, regenerate config TypedDicts
$ tox run -e config-types
๐ง Troubleshooting¶
If tox run -e cli-docs fails:
- "No test found documenting option --xxx": Add
@pytest.mark.cli_doc(options=["--xxx"], ...)to a test - "File not found: ...": Check that
input_schemaandgolden_outputpaths are correct - "CLI docs are OUT OF DATE": Run
python scripts/build_cli_docs.pyto regenerate
๐ CLI Documentation Marker Reference¶
The cli_doc marker supports:
| Parameter | Required | Description |
|---|---|---|
options |
Yes | List of CLI options this test documents |
input_schema |
Yes | Input schema path (relative to tests/data/) |
cli_args |
Yes | CLI arguments used in the test |
golden_output |
Yes* | Expected output file path |
model_outputs |
No | Dict of model type โ output file (for multi-model tabs) |
version_outputs |
No | Dict of Python version โ output file |
comparison_output |
No | Baseline output without option (for before/after) |
primary |
No | Set True if this is the main example for the option |
*Either golden_output or model_outputs is required.
See existing tests in tests/main/ for examples.