|
7 | 7 |
|
8 | 8 | from __future__ import annotations |
9 | 9 |
|
| 10 | +import json |
10 | 11 | import locale |
11 | | -from argparse import ArgumentParser, BooleanOptionalAction, HelpFormatter, Namespace |
| 12 | +from argparse import ArgumentParser, ArgumentTypeError, BooleanOptionalAction, HelpFormatter, Namespace |
12 | 13 | from operator import attrgetter |
13 | 14 | from pathlib import Path |
14 | | -from typing import TYPE_CHECKING |
| 15 | +from typing import TYPE_CHECKING, cast |
15 | 16 |
|
16 | | -from datamodel_code_generator import DataModelType, InputFileType, OpenAPIScope |
| 17 | +from datamodel_code_generator import DataclassArguments, DataModelType, InputFileType, OpenAPIScope |
17 | 18 | from datamodel_code_generator.format import DatetimeClassType, Formatter, PythonVersion |
18 | 19 | from datamodel_code_generator.model.pydantic_v2 import UnionMode |
19 | 20 | from datamodel_code_generator.parser import LiteralType |
|
28 | 29 | namespace = Namespace(no_color=False) |
29 | 30 |
|
30 | 31 |
|
| 32 | +def _dataclass_arguments(value: str) -> DataclassArguments: |
| 33 | + """Parse JSON string and validate it as DataclassArguments.""" |
| 34 | + try: |
| 35 | + result = json.loads(value) |
| 36 | + except json.JSONDecodeError as e: |
| 37 | + msg = f"Invalid JSON: {e}" |
| 38 | + raise ArgumentTypeError(msg) from e |
| 39 | + if not isinstance(result, dict): |
| 40 | + msg = f"Expected a JSON dictionary, got {type(result).__name__}" |
| 41 | + raise ArgumentTypeError(msg) |
| 42 | + valid_keys = set(DataclassArguments.__annotations__.keys()) |
| 43 | + invalid_keys = set(result.keys()) - valid_keys |
| 44 | + if invalid_keys: |
| 45 | + msg = f"Invalid keys: {invalid_keys}. Valid keys are: {valid_keys}" |
| 46 | + raise ArgumentTypeError(msg) |
| 47 | + for key, val in result.items(): |
| 48 | + if not isinstance(val, bool): |
| 49 | + msg = f"Expected bool for '{key}', got {type(val).__name__}" |
| 50 | + raise ArgumentTypeError(msg) |
| 51 | + return cast("DataclassArguments", result) |
| 52 | + |
| 53 | + |
31 | 54 | class SortingHelpFormatter(HelpFormatter): |
32 | 55 | """Help formatter that sorts arguments and adds color to section headers.""" |
33 | 56 |
|
@@ -179,6 +202,16 @@ def start_section(self, heading: str | None) -> None: |
179 | 202 | action="store_true", |
180 | 203 | default=None, |
181 | 204 | ) |
| 205 | +model_options.add_argument( |
| 206 | + "--dataclass-arguments", |
| 207 | + type=_dataclass_arguments, |
| 208 | + default=None, |
| 209 | + help=( |
| 210 | + "Custom dataclass arguments as a JSON dictionary, " |
| 211 | + 'e.g. \'{"frozen": true, "kw_only": true}\'. ' |
| 212 | + "Overrides --frozen-dataclasses and similar flags." |
| 213 | + ), |
| 214 | +) |
182 | 215 | model_options.add_argument( |
183 | 216 | "--reuse-model", |
184 | 217 | help="Reuse models on the field when a module has the model with the same content", |
|
0 commit comments