datamodel-code-generator 0.30.1__py3-none-any.whl → 0.30.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of datamodel-code-generator might be problematic. Click here for more details.

@@ -285,6 +285,7 @@ def generate( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
285
285
  union_mode: UnionMode | None = None,
286
286
  output_datetime_class: DatetimeClassType | None = None,
287
287
  keyword_only: bool = False,
288
+ frozen_dataclasses: bool = False,
288
289
  no_alias: bool = False,
289
290
  formatters: list[Formatter] = DEFAULT_FORMATTERS,
290
291
  parent_scoped_naming: bool = False,
@@ -481,6 +482,7 @@ def generate( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
481
482
  default_field_extras=default_field_extras,
482
483
  target_datetime_class=output_datetime_class,
483
484
  keyword_only=keyword_only,
485
+ frozen_dataclasses=frozen_dataclasses,
484
486
  no_alias=no_alias,
485
487
  formatters=formatters,
486
488
  encoding=encoding,
@@ -312,6 +312,7 @@ class Config(BaseModel):
312
312
  union_mode: Optional[UnionMode] = None # noqa: UP045
313
313
  output_datetime_class: Optional[DatetimeClassType] = None # noqa: UP045
314
314
  keyword_only: bool = False
315
+ frozen_dataclasses: bool = False
315
316
  no_alias: bool = False
316
317
  formatters: list[Formatter] = DEFAULT_FORMATTERS
317
318
  parent_scoped_naming: bool = False
@@ -524,6 +525,7 @@ def main(args: Sequence[str] | None = None) -> Exit: # noqa: PLR0911, PLR0912,
524
525
  union_mode=config.union_mode,
525
526
  output_datetime_class=config.output_datetime_class,
526
527
  keyword_only=config.keyword_only,
528
+ frozen_dataclasses=config.frozen_dataclasses,
527
529
  no_alias=config.no_alias,
528
530
  formatters=config.formatters,
529
531
  parent_scoped_naming=config.parent_scoped_naming,
@@ -153,6 +153,12 @@ model_options.add_argument(
153
153
  action="store_true",
154
154
  default=None,
155
155
  )
156
+ model_options.add_argument(
157
+ "--frozen-dataclasses",
158
+ help="Generate frozen dataclasses (dataclass(frozen=True)). Only applies to dataclass output.",
159
+ action="store_true",
160
+ default=None,
161
+ )
156
162
  model_options.add_argument(
157
163
  "--reuse-model",
158
164
  help="Reuse models on the field when a module has the model with the same content",
@@ -222,7 +222,7 @@ class CodeFormatter:
222
222
  )
223
223
 
224
224
  def apply_ruff_lint(self, code: str) -> str:
225
- result = subprocess.run( # noqa: S603
225
+ result = subprocess.run(
226
226
  ("ruff", "check", "--fix", "-"),
227
227
  input=code.encode(self.encoding),
228
228
  capture_output=True,
@@ -231,7 +231,7 @@ class CodeFormatter:
231
231
  return result.stdout.decode(self.encoding)
232
232
 
233
233
  def apply_ruff_formatter(self, code: str) -> str:
234
- result = subprocess.run( # noqa: S603
234
+ result = subprocess.run(
235
235
  ("ruff", "format", "-"),
236
236
  input=code.encode(self.encoding),
237
237
  capture_output=True,
@@ -275,9 +275,11 @@ class DataModel(TemplateBase, Nullable, ABC):
275
275
  default: Any = UNDEFINED,
276
276
  nullable: bool = False,
277
277
  keyword_only: bool = False,
278
+ frozen: bool = False,
278
279
  treat_dot_as_module: bool = False,
279
280
  ) -> None:
280
281
  self.keyword_only = keyword_only
282
+ self.frozen = frozen
281
283
  if not self.TEMPLATE_FILE_PATH:
282
284
  msg = "TEMPLATE_FILE_PATH is undefined"
283
285
  raise Exception(msg) # noqa: TRY002
@@ -434,5 +436,6 @@ class DataModel(TemplateBase, Nullable, ABC):
434
436
  methods=self.methods,
435
437
  description=self.description,
436
438
  keyword_only=self.keyword_only,
439
+ frozen=self.frozen,
437
440
  **self.extra_template_data,
438
441
  )
@@ -53,6 +53,7 @@ class DataClass(DataModel):
53
53
  default: Any = UNDEFINED,
54
54
  nullable: bool = False,
55
55
  keyword_only: bool = False,
56
+ frozen: bool = False,
56
57
  treat_dot_as_module: bool = False,
57
58
  ) -> None:
58
59
  super().__init__(
@@ -69,6 +70,7 @@ class DataClass(DataModel):
69
70
  default=default,
70
71
  nullable=nullable,
71
72
  keyword_only=keyword_only,
73
+ frozen=frozen,
72
74
  treat_dot_as_module=treat_dot_as_module,
73
75
  )
74
76
 
@@ -27,6 +27,7 @@ class ConfigDict(_BaseModel):
27
27
  protected_namespaces: Optional[tuple[str, ...]] = None # noqa: UP045
28
28
  regex_engine: Optional[str] = None # noqa: UP045
29
29
  use_enum_values: Optional[bool] = None # noqa: UP045
30
+ coerce_numbers_to_str: Optional[bool] = None # noqa: UP045
30
31
 
31
32
 
32
33
  __all__ = [
@@ -1,7 +1,14 @@
1
1
  {% for decorator in decorators -%}
2
2
  {{ decorator }}
3
3
  {% endfor -%}
4
- @dataclass{%- if keyword_only -%}(kw_only=True){%- endif %}
4
+ @dataclass
5
+ {%- if keyword_only or frozen -%}
6
+ (
7
+ {%- if keyword_only -%}kw_only=True{%- endif -%}
8
+ {%- if keyword_only and frozen -%}, {% endif -%}
9
+ {%- if frozen -%}frozen=True{%- endif -%}
10
+ )
11
+ {%- endif %}
5
12
  {%- if base_class %}
6
13
  class {{ class_name }}({{ base_class }}):
7
14
  {%- else %}
@@ -377,11 +377,13 @@ class Parser(ABC):
377
377
  default_field_extras: dict[str, Any] | None = None,
378
378
  target_datetime_class: DatetimeClassType | None = DatetimeClassType.Datetime,
379
379
  keyword_only: bool = False,
380
+ frozen_dataclasses: bool = False,
380
381
  no_alias: bool = False,
381
382
  formatters: list[Formatter] = DEFAULT_FORMATTERS,
382
383
  parent_scoped_naming: bool = False,
383
384
  ) -> None:
384
385
  self.keyword_only = keyword_only
386
+ self.frozen_dataclasses = frozen_dataclasses
385
387
  self.data_type_manager: DataTypeManager = data_type_manager_type(
386
388
  python_version=target_python_version,
387
389
  use_standard_collections=use_standard_collections,
@@ -770,19 +772,31 @@ class Parser(ABC):
770
772
  continue
771
773
  type_names.append(name)
772
774
 
773
- # Check the main discriminator model path
774
- if mapping:
775
- check_paths(discriminator_model, mapping) # pyright: ignore[reportArgumentType]
775
+ # First try to get the discriminator value from the const field
776
+ for discriminator_field in discriminator_model.fields:
777
+ if field_name not in {discriminator_field.original_name, discriminator_field.name}:
778
+ continue
779
+ if discriminator_field.extras.get("const"):
780
+ type_names = [discriminator_field.extras["const"]]
781
+ break
782
+
783
+ # If no const value found, try to get it from the mapping
784
+ if not type_names:
785
+ # Check the main discriminator model path
786
+ if mapping:
787
+ check_paths(discriminator_model, mapping) # pyright: ignore[reportArgumentType]
788
+
789
+ # Check the base_classes if they exist
790
+ if len(type_names) == 0:
791
+ for base_class in discriminator_model.base_classes:
792
+ check_paths(base_class.reference, mapping) # pyright: ignore[reportArgumentType]
793
+ else:
794
+ type_names = [discriminator_model.path.split("/")[-1]]
776
795
 
777
- # Check the base_classes if they exist
778
- if len(type_names) == 0:
779
- for base_class in discriminator_model.base_classes:
780
- check_paths(base_class.reference, mapping) # pyright: ignore[reportArgumentType]
781
- else:
782
- type_names = [discriminator_model.path.split("/")[-1]]
783
796
  if not type_names: # pragma: no cover
784
797
  msg = f"Discriminator type is not found. {data_type.reference.path}"
785
798
  raise RuntimeError(msg)
799
+
786
800
  has_one_literal = False
787
801
  for discriminator_field in discriminator_model.fields:
788
802
  if field_name not in {discriminator_field.original_name, discriminator_field.name}:
@@ -1202,7 +1216,10 @@ class Parser(ABC):
1202
1216
  ) -> None:
1203
1217
  for model in models:
1204
1218
  for model_field in model.fields:
1205
- if model_field.data_type.type in all_model_field_names:
1219
+ if (
1220
+ model_field.data_type.type in all_model_field_names
1221
+ and model_field.data_type.type == model_field.name
1222
+ ):
1206
1223
  alias = model_field.data_type.type + "_aliased"
1207
1224
  model_field.data_type.type = alias
1208
1225
  if model_field.data_type.import_: # pragma: no cover
@@ -17,6 +17,7 @@ from datamodel_code_generator import (
17
17
  )
18
18
  from datamodel_code_generator.model import DataModel, DataModelFieldBase
19
19
  from datamodel_code_generator.model import pydantic as pydantic_model
20
+ from datamodel_code_generator.model.dataclass import DataClass
20
21
  from datamodel_code_generator.model.enum import Enum
21
22
  from datamodel_code_generator.model.scalar import DataTypeScalar
22
23
  from datamodel_code_generator.model.union import DataTypeUnion
@@ -152,6 +153,7 @@ class GraphQLParser(Parser):
152
153
  default_field_extras: dict[str, Any] | None = None,
153
154
  target_datetime_class: DatetimeClassType = DatetimeClassType.Datetime,
154
155
  keyword_only: bool = False,
156
+ frozen_dataclasses: bool = False,
155
157
  no_alias: bool = False,
156
158
  formatters: list[Formatter] = DEFAULT_FORMATTERS,
157
159
  parent_scoped_naming: bool = False,
@@ -227,6 +229,7 @@ class GraphQLParser(Parser):
227
229
  default_field_extras=default_field_extras,
228
230
  target_datetime_class=target_datetime_class,
229
231
  keyword_only=keyword_only,
232
+ frozen_dataclasses=frozen_dataclasses,
230
233
  no_alias=no_alias,
231
234
  formatters=formatters,
232
235
  parent_scoped_naming=parent_scoped_naming,
@@ -283,6 +286,13 @@ class GraphQLParser(Parser):
283
286
 
284
287
  self.support_graphql_types[resolved_type].append(type_)
285
288
 
289
+ def _create_data_model(self, model_type: type[DataModel] | None = None, **kwargs: Any) -> DataModel:
290
+ """Create data model instance with conditional frozen parameter for DataClass."""
291
+ data_model_class = model_type or self.data_model_type
292
+ if issubclass(data_model_class, DataClass):
293
+ kwargs["frozen"] = self.frozen_dataclasses
294
+ return data_model_class(**kwargs)
295
+
286
296
  def _typename_field(self, name: str) -> DataModelFieldBase:
287
297
  return self.data_model_field_type(
288
298
  name="typename__",
@@ -445,7 +455,7 @@ class GraphQLParser(Parser):
445
455
  if hasattr(obj, "interfaces"): # pragma: no cover
446
456
  base_classes = [self.references[i.name] for i in obj.interfaces] # pyright: ignore[reportAttributeAccessIssue]
447
457
 
448
- data_model_type = self.data_model_type(
458
+ data_model_type = self._create_data_model(
449
459
  reference=self.references[obj.name],
450
460
  fields=fields,
451
461
  base_classes=base_classes,
@@ -6,7 +6,7 @@ from contextlib import contextmanager
6
6
  from functools import cached_property, lru_cache
7
7
  from pathlib import Path
8
8
  from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Union
9
- from urllib.parse import ParseResult
9
+ from urllib.parse import ParseResult, unquote
10
10
  from warnings import warn
11
11
 
12
12
  from pydantic import (
@@ -23,6 +23,7 @@ from datamodel_code_generator.format import DEFAULT_FORMATTERS, Formatter, Pytho
23
23
  from datamodel_code_generator.model import DataModel, DataModelFieldBase
24
24
  from datamodel_code_generator.model import pydantic as pydantic_model
25
25
  from datamodel_code_generator.model.base import UNDEFINED, get_module_name
26
+ from datamodel_code_generator.model.dataclass import DataClass
26
27
  from datamodel_code_generator.model.enum import Enum
27
28
  from datamodel_code_generator.parser import DefaultPutDict, LiteralType
28
29
  from datamodel_code_generator.parser.base import (
@@ -58,16 +59,26 @@ if TYPE_CHECKING:
58
59
  from collections.abc import Generator, Iterable, Iterator, Mapping, Sequence
59
60
 
60
61
 
62
+ def unescape_json_pointer_segment(segment: str) -> str:
63
+ # Unescape ~1, ~0, and percent-encoding
64
+ return unquote(segment.replace("~1", "/").replace("~0", "~"))
65
+
66
+
61
67
  def get_model_by_path(schema: dict[str, Any] | list[Any], keys: list[str] | list[int]) -> dict[Any, Any]:
62
68
  model: dict[Any, Any] | list[Any]
63
69
  if not keys:
64
70
  model = schema
65
- elif len(keys) == 1:
66
- model = schema.get(str(keys[0]), {}) if isinstance(schema, dict) else schema[int(keys[0])]
67
- elif isinstance(schema, dict):
68
- model = get_model_by_path(schema[str(keys[0])], keys[1:])
69
71
  else:
70
- model = get_model_by_path(schema[int(keys[0])], keys[1:])
72
+ # Unescape the key if it's a string (JSON pointer segment)
73
+ key = keys[0]
74
+ if isinstance(key, str):
75
+ key = unescape_json_pointer_segment(key)
76
+ if len(keys) == 1:
77
+ model = schema.get(str(key), {}) if isinstance(schema, dict) else schema[int(key)]
78
+ elif isinstance(schema, dict):
79
+ model = get_model_by_path(schema[str(key)], keys[1:])
80
+ else:
81
+ model = get_model_by_path(schema[int(key)], keys[1:])
71
82
  if isinstance(model, dict):
72
83
  return model
73
84
  msg = f"Does not support json pointer to array. schema={schema}, key={keys}"
@@ -421,6 +432,7 @@ class JsonSchemaParser(Parser):
421
432
  default_field_extras: dict[str, Any] | None = None,
422
433
  target_datetime_class: DatetimeClassType = DatetimeClassType.Datetime,
423
434
  keyword_only: bool = False,
435
+ frozen_dataclasses: bool = False,
424
436
  no_alias: bool = False,
425
437
  formatters: list[Formatter] = DEFAULT_FORMATTERS,
426
438
  parent_scoped_naming: bool = False,
@@ -496,6 +508,7 @@ class JsonSchemaParser(Parser):
496
508
  default_field_extras=default_field_extras,
497
509
  target_datetime_class=target_datetime_class,
498
510
  keyword_only=keyword_only,
511
+ frozen_dataclasses=frozen_dataclasses,
499
512
  no_alias=no_alias,
500
513
  formatters=formatters,
501
514
  parent_scoped_naming=parent_scoped_naming,
@@ -627,7 +640,7 @@ class JsonSchemaParser(Parser):
627
640
  result[key] = self._deep_merge(result[key], value)
628
641
  continue
629
642
  if isinstance(result[key], list) and isinstance(value, list):
630
- result[key] += value
643
+ result[key] = result[key] + value # noqa: PLR6104
631
644
  continue
632
645
  result[key] = value
633
646
  return result
@@ -686,6 +699,13 @@ class JsonSchemaParser(Parser):
686
699
  def parse_one_of(self, name: str, obj: JsonSchemaObject, path: list[str]) -> list[DataType]:
687
700
  return self.parse_combined_schema(name, obj, path, "oneOf")
688
701
 
702
+ def _create_data_model(self, model_type: type[DataModel] | None = None, **kwargs: Any) -> DataModel:
703
+ """Create data model instance with conditional frozen parameter for DataClass."""
704
+ data_model_class = model_type or self.data_model_type
705
+ if issubclass(data_model_class, DataClass):
706
+ kwargs["frozen"] = self.frozen_dataclasses
707
+ return data_model_class(**kwargs)
708
+
689
709
  def _parse_object_common_part( # noqa: PLR0913, PLR0917
690
710
  self,
691
711
  name: str,
@@ -733,7 +753,8 @@ class JsonSchemaParser(Parser):
733
753
  name = obj.title
734
754
  reference = self.model_resolver.add(path, name, class_name=True, loaded=True)
735
755
  self.set_additional_properties(reference.name, obj)
736
- data_model_type = self.data_model_type(
756
+
757
+ data_model_type = self._create_data_model(
737
758
  reference=reference,
738
759
  fields=fields,
739
760
  base_classes=base_classes,
@@ -874,7 +895,7 @@ class JsonSchemaParser(Parser):
874
895
  exclude_field_names: set[str] = set()
875
896
  for original_field_name, field in properties.items():
876
897
  field_name, alias = self.model_resolver.get_valid_field_name_and_alias(
877
- original_field_name, exclude_field_names
898
+ original_field_name, excludes=exclude_field_names
878
899
  )
879
900
  modular_name = f"{module_name}.{field_name}" if module_name else field_name
880
901
 
@@ -972,7 +993,9 @@ class JsonSchemaParser(Parser):
972
993
  data_model_type_class = self.data_model_root_type
973
994
 
974
995
  self.set_additional_properties(class_name, obj)
975
- data_model_type = data_model_type_class(
996
+
997
+ data_model_type = self._create_data_model(
998
+ model_type=data_model_type_class,
976
999
  reference=reference,
977
1000
  fields=fields,
978
1001
  custom_base_class=obj.custom_base_path or self.base_class,
@@ -42,6 +42,7 @@ if TYPE_CHECKING:
42
42
  from pathlib import Path
43
43
  from urllib.parse import ParseResult
44
44
 
45
+
45
46
  RE_APPLICATION_JSON_PATTERN: Pattern[str] = re.compile(r"^application/.*json$")
46
47
 
47
48
  OPERATION_NAMES: list[str] = [
@@ -214,6 +215,7 @@ class OpenAPIParser(JsonSchemaParser):
214
215
  default_field_extras: dict[str, Any] | None = None,
215
216
  target_datetime_class: DatetimeClassType = DatetimeClassType.Datetime,
216
217
  keyword_only: bool = False,
218
+ frozen_dataclasses: bool = False,
217
219
  no_alias: bool = False,
218
220
  formatters: list[Formatter] = DEFAULT_FORMATTERS,
219
221
  parent_scoped_naming: bool = False,
@@ -289,6 +291,7 @@ class OpenAPIParser(JsonSchemaParser):
289
291
  default_field_extras=default_field_extras,
290
292
  target_datetime_class=target_datetime_class,
291
293
  keyword_only=keyword_only,
294
+ frozen_dataclasses=frozen_dataclasses,
292
295
  no_alias=no_alias,
293
296
  formatters=formatters,
294
297
  parent_scoped_naming=parent_scoped_naming,
@@ -483,8 +486,10 @@ class OpenAPIParser(JsonSchemaParser):
483
486
  )
484
487
 
485
488
  if OpenAPIScope.Parameters in self.open_api_scopes and fields:
489
+ # Using _create_data_model from parent class JsonSchemaParser
490
+ # This method automatically adds frozen=True for DataClass types
486
491
  self.results.append(
487
- self.data_model_type(
492
+ self._create_data_model(
488
493
  fields=fields,
489
494
  reference=reference,
490
495
  custom_base_class=self.base_class,
@@ -6,13 +6,27 @@ from enum import Enum, auto
6
6
  from functools import lru_cache
7
7
  from itertools import chain
8
8
  from re import Pattern
9
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Protocol, TypeVar, Union, runtime_checkable
9
+ from typing import (
10
+ TYPE_CHECKING,
11
+ Any,
12
+ Callable,
13
+ ClassVar,
14
+ Optional,
15
+ Protocol,
16
+ TypeVar,
17
+ Union,
18
+ runtime_checkable,
19
+ )
10
20
 
11
21
  import pydantic
12
22
  from packaging import version
13
23
  from pydantic import StrictBool, StrictInt, StrictStr, create_model
14
24
 
15
- from datamodel_code_generator.format import DatetimeClassType, PythonVersion, PythonVersionMin
25
+ from datamodel_code_generator.format import (
26
+ DatetimeClassType,
27
+ PythonVersion,
28
+ PythonVersionMin,
29
+ )
16
30
  from datamodel_code_generator.imports import (
17
31
  IMPORT_ABC_MAPPING,
18
32
  IMPORT_ABC_SEQUENCE,
@@ -167,53 +181,57 @@ def _remove_none_from_type(type_: str, split_pattern: Pattern[str], delimiter: s
167
181
  return types
168
182
 
169
183
 
170
- def _remove_none_from_union(type_: str, *, use_union_operator: bool) -> str: # noqa: PLR0911, PLR0912
184
+ def _remove_none_from_union(type_: str, *, use_union_operator: bool) -> str: # noqa: PLR0912
171
185
  if use_union_operator:
172
186
  if " | " not in type_:
173
187
  return type_
188
+ separator = "|"
189
+ inner_text = type_
190
+ else:
191
+ if not type_.startswith(UNION_PREFIX):
192
+ return type_
193
+ separator = ","
194
+ inner_text = type_[len(UNION_PREFIX) : -1]
174
195
 
175
- # Process each part of the union
176
- parts = UNION_OPERATOR_PATTERN.split(type_)
177
- processed_parts = []
178
- for part in parts:
179
- if part == NONE:
180
- continue
181
-
182
- # Check if this part contains a nested union
183
- processed_part = _remove_none_from_union(part, use_union_operator=True) if " | " in part else part
184
- processed_parts.append(processed_part)
185
-
186
- if not processed_parts:
187
- return NONE
188
-
189
- return UNION_OPERATOR_DELIMITER.join(processed_parts)
190
- if not type_.startswith(UNION_PREFIX):
191
- return type_
192
-
193
- inner_text = type_[len(UNION_PREFIX) : -1]
194
196
  parts = []
195
197
  inner_count = 0
196
198
  current_part = ""
197
199
 
200
+ # With this variable we count any non-escaped round bracket, whenever we are inside a
201
+ # constraint string expression. Once found a part starting with `constr(`, we increment
202
+ # this counter for each non-escaped opening round bracket and decrement it for each
203
+ # non-escaped closing round bracket.
204
+ in_constr = 0
205
+
198
206
  # Parse union parts carefully to handle nested structures
199
207
  for char in inner_text:
200
208
  current_part += char
201
- if char == "[":
209
+ if char == "[" and in_constr == 0:
202
210
  inner_count += 1
203
- elif char == "]":
211
+ elif char == "]" and in_constr == 0:
204
212
  inner_count -= 1
205
- elif char == "," and inner_count == 0:
213
+ elif char == "(":
214
+ if current_part.strip().startswith("constr(") and current_part[-2] != "\\":
215
+ # non-escaped opening round bracket found inside constraint string expression
216
+ in_constr += 1
217
+ elif char == ")":
218
+ if in_constr > 0 and current_part[-2] != "\\":
219
+ # non-escaped closing round bracket found inside constraint string expression
220
+ in_constr -= 1
221
+ elif char == separator and inner_count == 0 and in_constr == 0:
206
222
  part = current_part[:-1].strip()
207
223
  if part != NONE:
208
224
  # Process nested unions recursively
209
- if part.startswith(UNION_PREFIX):
225
+ # only UNION_PREFIX might be nested but not union_operator
226
+ if not use_union_operator and part.startswith(UNION_PREFIX):
210
227
  part = _remove_none_from_union(part, use_union_operator=False)
211
228
  parts.append(part)
212
229
  current_part = ""
213
230
 
214
231
  part = current_part.strip()
215
232
  if current_part and part != NONE:
216
- if part.startswith(UNION_PREFIX):
233
+ # only UNION_PREFIX might be nested but not union_operator
234
+ if not use_union_operator and part.startswith(UNION_PREFIX):
217
235
  part = _remove_none_from_union(part, use_union_operator=False)
218
236
  parts.append(part)
219
237
 
@@ -222,6 +240,9 @@ def _remove_none_from_union(type_: str, *, use_union_operator: bool) -> str: #
222
240
  if len(parts) == 1:
223
241
  return parts[0]
224
242
 
243
+ if use_union_operator:
244
+ return UNION_OPERATOR_DELIMITER.join(parts)
245
+
225
246
  return f"{UNION_PREFIX}{UNION_DELIMITER.join(parts)}]"
226
247
 
227
248
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datamodel-code-generator
3
- Version: 0.30.1
3
+ Version: 0.30.2
4
4
  Summary: Datamodel Code Generator
5
5
  Project-URL: Homepage, https://github.com/koxudaxi/datamodel-code-generator
6
6
  Project-URL: Source, https://github.com/koxudaxi/datamodel-code-generator
@@ -505,6 +505,8 @@ Model customization:
505
505
  Enable faux immutability
506
506
  --enable-version-header
507
507
  Enable package version on file headers
508
+ --frozen-dataclasses Generate frozen dataclasses (dataclass(frozen=True)). Only applies
509
+ to dataclass output.
508
510
  --keep-model-order Keep generated models'' order
509
511
  --keyword-only Defined models as keyword only (for example
510
512
  dataclass(kw_only=True)).
@@ -1,17 +1,17 @@
1
- datamodel_code_generator/__init__.py,sha256=2h8FA8O_x1VGRVlXKJHt3jwuC34MIEnmHwHv-zGuF_I,20445
2
- datamodel_code_generator/__main__.py,sha256=rF1Se8R0rfqDmJ4_INBdOYlU7G4XIthPCe3ldDwtgQI,22608
3
- datamodel_code_generator/arguments.py,sha256=xPAnid2-dC_Hj4o1hY9fL13NMJl5wCPphTsCHZ3QeNQ,16637
4
- datamodel_code_generator/format.py,sha256=zvX0KH1uWwGnTYoVM4KhAuKZn5erjkH5eyi4t3leirw,8962
1
+ datamodel_code_generator/__init__.py,sha256=h0yxjBBK7_RJdAqUVimMfSqsq0tXqH_nzcNZRgL3Yrs,20530
2
+ datamodel_code_generator/__main__.py,sha256=Sl3ch890tr6J8voedlz8nyCq2QYLZDtibFa3o2SfQ_k,22703
3
+ datamodel_code_generator/arguments.py,sha256=T8iPrqTq9MJLJyi4PHB3_JQC2PgfLpYNmXpDFZWsXAs,16838
4
+ datamodel_code_generator/format.py,sha256=ZlnTCAl1H4og685smvCBSzexgpYbZtyYLIrt7lwUNcY,8934
5
5
  datamodel_code_generator/http.py,sha256=LE94GC7I9D8lWIg_YAGWedfy0XNxOXTmiYKuNMTwouo,887
6
6
  datamodel_code_generator/imports.py,sha256=Nq83WbEGCegntg3WX4VbKfzAIs84alZ7IrYyNPrlUbc,5517
7
7
  datamodel_code_generator/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  datamodel_code_generator/pydantic_patch.py,sha256=co1IUDvZqQ-xEZ3C9gbV-BVm2Cin1vfyZNr2Dr0LdHY,718
9
9
  datamodel_code_generator/reference.py,sha256=OobfjN5hWaKzv4ECdCPc9Q3ODkoG93B4qaKlzDEcDrY,26748
10
- datamodel_code_generator/types.py,sha256=fobUZnNTOGpzF4qZMraoLogVkAU7zBdFVG-8SOFoDD4,21163
10
+ datamodel_code_generator/types.py,sha256=1g4RZZ1e5oC4EHaNyyDmsIfF4o1WAjQ2KaLjwc9mYss,21883
11
11
  datamodel_code_generator/util.py,sha256=mZW8-6CbFe6T4IY5OM9Av6cH-0VknQGe2eIKjTM6Jzo,2729
12
12
  datamodel_code_generator/model/__init__.py,sha256=pJlJ1juQ-Gv17ZKXy6OAfJSSoOAmYQ7QCbdneu1BENU,3594
13
- datamodel_code_generator/model/base.py,sha256=Ma28Vx1p5zsFt23BMCs1UNDXuBq_USEhuPUvaeFLkS4,14959
14
- datamodel_code_generator/model/dataclass.py,sha256=t4NtgVhopTtEDUJCqijJheVlewSt8IJzQhQb8gXspfs,6252
13
+ datamodel_code_generator/model/base.py,sha256=ZQ3Xy4Fs_I8M01tk1ps0EhWJM9vR-n7umPkz5NmHTjw,15050
14
+ datamodel_code_generator/model/dataclass.py,sha256=8Z02XY3S6byNe9Pb46LisE5opQcvpx8FVvPjUrlAacE,6309
15
15
  datamodel_code_generator/model/enum.py,sha256=yriQslY1hag_Qk-Xv3vl_LkPnbmMZ3iRTAGiiyMN0Io,4003
16
16
  datamodel_code_generator/model/imports.py,sha256=PTc09UzIBSsa5yAPoieb6hCGIohU2T1Y7igNy_pYarg,820
17
17
  datamodel_code_generator/model/msgspec.py,sha256=qL2DIEwBfpn-vd8p8KEmUViMUce6RgI4Ql-drOmPR7M,11845
@@ -26,7 +26,7 @@ datamodel_code_generator/model/pydantic/custom_root_type.py,sha256=VJpEAmGFe3TzM
26
26
  datamodel_code_generator/model/pydantic/dataclass.py,sha256=jgjkqQk71CQP4RbTcPGSEOQDNqjTQnzFavvl5LjWTBw,455
27
27
  datamodel_code_generator/model/pydantic/imports.py,sha256=nWPiLgDeYNPHcAs8M-gaUUZg1daQRHdBPpjYuX3b5u4,2225
28
28
  datamodel_code_generator/model/pydantic/types.py,sha256=ttTiDsQ6FV3h4C_NTEhvPUmUpeqxBNQt-DJJFpKZS8s,13356
29
- datamodel_code_generator/model/pydantic_v2/__init__.py,sha256=xsfYcIUA2S8XzPIsYQSzDuBYZ1XRicfhGLHlQBlZwsg,1226
29
+ datamodel_code_generator/model/pydantic_v2/__init__.py,sha256=6liTgL3VeH4ohYXkRoiCSafEc0nHxgbnYO3Rl2iQDx8,1290
30
30
  datamodel_code_generator/model/pydantic_v2/base_model.py,sha256=J_DxR6Auw0L-zHn0F5l9K8XtSmfEvDT26Bj-VZxihiE,8353
31
31
  datamodel_code_generator/model/pydantic_v2/imports.py,sha256=K3XD2kF9YCKmo5_7b2ipV5bGUrjz0avS-SiyDMVIpF0,299
32
32
  datamodel_code_generator/model/pydantic_v2/root_model.py,sha256=H4rwtg56N65-I3QHlPvlNhDcSPV0m56KSAgfGmxYXAQ,888
@@ -37,7 +37,7 @@ datamodel_code_generator/model/template/TypedDict.jinja2,sha256=J_Pe_CiuvTOb-EUC
37
37
  datamodel_code_generator/model/template/TypedDictClass.jinja2,sha256=URwp5__WyR8G21Hoyc17aMzoast-NppXnXe19VFi5wQ,377
38
38
  datamodel_code_generator/model/template/TypedDictFunction.jinja2,sha256=KjSij5_w4ow4a12SR3orYOndmXGkIvJBBUN735bQ6G0,321
39
39
  datamodel_code_generator/model/template/Union.jinja2,sha256=sq7o--2ESUSfIL4kCfgnr5ZXPFa_VeioqbATTY-N-5I,258
40
- datamodel_code_generator/model/template/dataclass.jinja2,sha256=wRSy2g11Dr1GN9YUl13OZt2xg37bQyFwKn2wEsQIndE,865
40
+ datamodel_code_generator/model/template/dataclass.jinja2,sha256=c3gs1ZwDEwLpmZ2PpOEWjHjfdl6kPP64xm18mt9lZMk,1007
41
41
  datamodel_code_generator/model/template/msgspec.jinja2,sha256=qMuFOH6SFFh558wImdI6uIjG4Mtam3J_ox8Hmgqkv0g,1174
42
42
  datamodel_code_generator/model/template/root.jinja2,sha256=3OTtibxLcGA-FMdR0QDCJUJQgf_kRW0OafeCTPFSFFo,162
43
43
  datamodel_code_generator/model/template/pydantic/BaseModel.jinja2,sha256=sYZa-47YAXqZrd5cYKVnPrsbDvLkHEJOUd7M0nAosP8,1084
@@ -48,12 +48,12 @@ datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2,sha256=i1Wg
48
48
  datamodel_code_generator/model/template/pydantic_v2/ConfigDict.jinja2,sha256=xHvBYrh__32O1xRCSl6_u5zbyYIjB8a5k8fZiTo0spY,149
49
49
  datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2,sha256=XQBlML7Hm5hN6_AExENNvVc_yxNWijcIfTTbbmegCpE,1223
50
50
  datamodel_code_generator/parser/__init__.py,sha256=3XtFcDPocaetfjmWFqj_CubqNCDipb7vXZHsYKdJXXU,851
51
- datamodel_code_generator/parser/base.py,sha256=h2YD0aRtGiW3jBBbJ-bx3YjBb9NTF1TBj51JxZnZcxQ,61947
52
- datamodel_code_generator/parser/graphql.py,sha256=scotG-q8zTS40i5rP9HfhriSVhXVnxEKtuBoXvbzECg,22684
53
- datamodel_code_generator/parser/jsonschema.py,sha256=bwXNvXjG8tiUPCNZsEXbo2TlCYJVKIzeYWEKfvlPzo8,70011
54
- datamodel_code_generator/parser/openapi.py,sha256=3IWF40DK0a710rVqXCod7Hi3Fh9u7neD4YR_kn_6VD4,27279
55
- datamodel_code_generator-0.30.1.dist-info/METADATA,sha256=9YcS5FD4-A9Dk96eQsagXfsuPAQs0qidE_szFAPChKs,25294
56
- datamodel_code_generator-0.30.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
57
- datamodel_code_generator-0.30.1.dist-info/entry_points.txt,sha256=cJVcHiEViQMANaoM5C1xR5hzmyCqH6hHHMpV8W00in8,77
58
- datamodel_code_generator-0.30.1.dist-info/licenses/LICENSE,sha256=K54Lwc6_jduycsy8oFFjQEeSSuEiqvVIjCGIXOMnuTQ,1068
59
- datamodel_code_generator-0.30.1.dist-info/RECORD,,
51
+ datamodel_code_generator/parser/base.py,sha256=2rNtyo9Gcu4lSihbQKtawL6W7KD4keM2CR1KHgnrNso,62794
52
+ datamodel_code_generator/parser/graphql.py,sha256=w4rnPXxQWGluG9dKlfv9XG1sv8T7HJOq9wySd-EsfDs,23250
53
+ datamodel_code_generator/parser/jsonschema.py,sha256=cjxYs2vQ2aka5YpqagDkNhyhvBwNXz7YOrdsJz7bVeQ,71034
54
+ datamodel_code_generator/parser/openapi.py,sha256=oY_qOngrxr4fHk9b6YUNI2IQCWkUeAJ9-CvTCTym8WM,27527
55
+ datamodel_code_generator-0.30.2.dist-info/METADATA,sha256=AXlPlc6b1QyG1ylx4pUj6NZqLI-P59K3QZw4e2vSjlY,25430
56
+ datamodel_code_generator-0.30.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
57
+ datamodel_code_generator-0.30.2.dist-info/entry_points.txt,sha256=cJVcHiEViQMANaoM5C1xR5hzmyCqH6hHHMpV8W00in8,77
58
+ datamodel_code_generator-0.30.2.dist-info/licenses/LICENSE,sha256=K54Lwc6_jduycsy8oFFjQEeSSuEiqvVIjCGIXOMnuTQ,1068
59
+ datamodel_code_generator-0.30.2.dist-info/RECORD,,