datamodel-code-generator 0.21.2__tar.gz → 0.21.4__tar.gz

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.

Files changed (53) hide show
  1. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/PKG-INFO +3 -3
  2. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/README.md +1 -1
  3. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/__init__.py +1 -1
  4. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/__main__.py +23 -24
  5. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/__init__.py +1 -1
  6. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/base.py +27 -10
  7. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/dataclass.py +1 -1
  8. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic/types.py +14 -3
  9. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic_v2/__init__.py +12 -2
  10. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic_v2/base_model.py +11 -0
  11. datamodel_code_generator-0.21.4/datamodel_code_generator/model/pydantic_v2/root_model.py +21 -0
  12. datamodel_code_generator-0.21.4/datamodel_code_generator/model/pydantic_v2/types.py +30 -0
  13. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/typed_dict.py +5 -1
  14. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/parser/base.py +18 -7
  15. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/parser/jsonschema.py +5 -1
  16. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/parser/openapi.py +5 -1
  17. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/types.py +9 -1
  18. datamodel_code_generator-0.21.4/datamodel_code_generator/version.py +1 -0
  19. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/pyproject.toml +2 -2
  20. datamodel_code_generator-0.21.2/datamodel_code_generator/model/pydantic_v2/root_model.py +0 -10
  21. datamodel_code_generator-0.21.2/datamodel_code_generator/model/pydantic_v2/types.py +0 -9
  22. datamodel_code_generator-0.21.2/datamodel_code_generator/version.py +0 -1
  23. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/LICENSE +0 -0
  24. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/format.py +0 -0
  25. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/http.py +0 -0
  26. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/imports.py +0 -0
  27. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/enum.py +0 -0
  28. /datamodel_code_generator-0.21.2/datamodel_code_generator/model/improts.py → /datamodel_code_generator-0.21.4/datamodel_code_generator/model/imports.py +0 -0
  29. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic/__init__.py +0 -0
  30. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic/base_model.py +0 -0
  31. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic/custom_root_type.py +0 -0
  32. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic/dataclass.py +0 -0
  33. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic/imports.py +0 -0
  34. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/pydantic_v2/imports.py +0 -0
  35. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/rootmodel.py +0 -0
  36. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/Enum.jinja2 +0 -0
  37. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/TypedDict.jinja2 +0 -0
  38. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/TypedDictClass.jinja2 +0 -0
  39. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/TypedDictFunction.jinja2 +0 -0
  40. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/dataclass.jinja2 +0 -0
  41. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/pydantic/BaseModel.jinja2 +0 -0
  42. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/pydantic/BaseModel_root.jinja2 +0 -0
  43. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/pydantic/Config.jinja2 +0 -0
  44. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/pydantic/dataclass.jinja2 +0 -0
  45. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 +0 -0
  46. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/pydantic_v2/ConfigDict.jinja2 +0 -0
  47. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 +0 -0
  48. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/template/root.jinja2 +0 -0
  49. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/model/types.py +0 -0
  50. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/parser/__init__.py +0 -0
  51. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/py.typed +0 -0
  52. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/reference.py +0 -0
  53. {datamodel_code_generator-0.21.2 → datamodel_code_generator-0.21.4}/datamodel_code_generator/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: datamodel-code-generator
3
- Version: 0.21.2
3
+ Version: 0.21.4
4
4
  Summary: Datamodel Code Generator
5
5
  Home-page: https://github.com/koxudaxi/datamodel-code-generator
6
6
  License: MIT
@@ -26,7 +26,7 @@ Requires-Dist: httpx ; extra == "http"
26
26
  Requires-Dist: inflect (>=4.1.0,<6.0)
27
27
  Requires-Dist: isort (>=4.3.21,<6.0)
28
28
  Requires-Dist: jinja2 (>=2.10.1,<4.0)
29
- Requires-Dist: openapi-spec-validator (>=0.2.8,<=0.5.2)
29
+ Requires-Dist: openapi-spec-validator (>=0.2.8,<=0.5.7)
30
30
  Requires-Dist: packaging
31
31
  Requires-Dist: prance (>=0.18.2)
32
32
  Requires-Dist: pydantic[email] (>=1.10.0,<3.0) ; python_version >= "3.11" and python_version < "4.0"
@@ -321,7 +321,7 @@ $ docker pull koxudaxi/datamodel-code-generator
321
321
  ```
322
322
 
323
323
  ## Advanced Uses
324
- You can genearte models from a URL.
324
+ You can generate models from a URL.
325
325
  ```bash
326
326
  $ datamodel-codegen --url https://<INPUT FILE URL> --output model.py
327
327
  ```
@@ -283,7 +283,7 @@ $ docker pull koxudaxi/datamodel-code-generator
283
283
  ```
284
284
 
285
285
  ## Advanced Uses
286
- You can genearte models from a URL.
286
+ You can generate models from a URL.
287
287
  ```bash
288
288
  $ datamodel-codegen --url https://<INPUT FILE URL> --output model.py
289
289
  ```
@@ -224,7 +224,7 @@ def generate(
224
224
  output: Optional[Path] = None,
225
225
  output_model_type: DataModelType = DataModelType.PydanticBaseModel,
226
226
  target_python_version: PythonVersion = PythonVersion.PY_37,
227
- base_class: str = DEFAULT_BASE_CLASS,
227
+ base_class: str = '',
228
228
  additional_imports: Optional[List[str]] = None,
229
229
  custom_template_dir: Optional[Path] = None,
230
230
  extra_template_data: Optional[DefaultDict[str, Dict[str, Any]]] = None,
@@ -36,8 +36,10 @@ import black
36
36
  import toml
37
37
  from pydantic import BaseModel
38
38
 
39
+ if TYPE_CHECKING:
40
+ from typing_extensions import Self
41
+
39
42
  from datamodel_code_generator import (
40
- DEFAULT_BASE_CLASS,
41
43
  DataModelType,
42
44
  Error,
43
45
  InputFileType,
@@ -470,9 +472,6 @@ class Config(BaseModel):
470
472
  def __getitem__(self, item: str) -> Any:
471
473
  return self.get(item)
472
474
 
473
- def __setitem__(self, key: str, value: Any) -> None:
474
- setattr(self, key, value)
475
-
476
475
  if TYPE_CHECKING:
477
476
 
478
477
  @classmethod
@@ -580,23 +579,21 @@ class Config(BaseModel):
580
579
  return [validate_each_item(each_item) for each_item in value]
581
580
  return value # pragma: no cover
582
581
 
583
- @model_validator(mode='after')
584
- def validate_root(cls, values: Dict[str, Any]) -> Dict[str, Any]:
585
- values = cls._validate_use_annotated(values)
586
- return cls._validate_base_class(values)
587
-
588
- @classmethod
589
- def _validate_use_annotated(cls, values: Dict[str, Any]) -> Dict[str, Any]:
590
- if values.get('use_annotated'):
591
- values['field_constraints'] = True
592
- return values
582
+ if PYDANTIC_V2:
593
583
 
594
- @classmethod
595
- def _validate_base_class(cls, values: Dict[str, Any]) -> Dict[str, Any]:
596
- if 'base_class' not in values and 'output_model_type' in values:
597
- if values['output_model_type'] != DataModelType.PydanticBaseModel.value:
598
- values['base_class'] = ''
599
- return values
584
+ @model_validator(mode='after') # type: ignore
585
+ def validate_root(self: Self) -> Self:
586
+ if self.use_annotated:
587
+ self.field_constraints = True
588
+ return self
589
+
590
+ else:
591
+
592
+ @model_validator(mode='after')
593
+ def validate_root(cls, values: Any) -> Any:
594
+ if values.get('use_annotated'):
595
+ values['field_constraints'] = True
596
+ return values
600
597
 
601
598
  input: Optional[Union[Path, str]] = None
602
599
  input_file_type: InputFileType = InputFileType.Auto
@@ -605,7 +602,7 @@ class Config(BaseModel):
605
602
  debug: bool = False
606
603
  disable_warnings: bool = False
607
604
  target_python_version: PythonVersion = PythonVersion.PY_37
608
- base_class: str = DEFAULT_BASE_CLASS
605
+ base_class: str = ''
609
606
  custom_template_dir: Optional[Path] = None
610
607
  extra_template_data: Optional[TextIOBase] = None
611
608
  validation: bool = False
@@ -666,9 +663,11 @@ class Config(BaseModel):
666
663
  for f in self.get_fields()
667
664
  if getattr(args, f) is not None
668
665
  }
669
- set_args = self._validate_use_annotated(set_args)
670
- set_args = self._validate_base_class(set_args)
671
- parsed_args = self.parse_obj(set_args)
666
+
667
+ if set_args.get('use_annotated'):
668
+ set_args['field_constraints'] = True
669
+
670
+ parsed_args = Config.parse_obj(set_args)
672
671
  for field_name in set_args:
673
672
  setattr(self, field_name, getattr(parsed_args, field_name))
674
673
 
@@ -38,7 +38,7 @@ def get_data_model_types(
38
38
  root_model=pydantic_v2.RootModel,
39
39
  field_model=pydantic_v2.DataModelField,
40
40
  data_type_manager=pydantic_v2.DataTypeManager,
41
- dump_resolve_reference_action=pydantic.dump_resolve_reference_action,
41
+ dump_resolve_reference_action=pydantic_v2.dump_resolve_reference_action,
42
42
  )
43
43
  elif data_model_type == DataModelType.DataclassesDataclass:
44
44
  return DataModelSet(
@@ -92,11 +92,15 @@ class DataModelFieldBase(_BaseModel):
92
92
  super().__init__(**data)
93
93
  if self.data_type.reference or self.data_type.data_types:
94
94
  self.data_type.parent = self
95
- if 'const' in self.extras:
96
- self.default = self.extras['const']
97
- self.const = True
98
- self.required = False
99
- self.nullable = False
95
+ self.process_const()
96
+
97
+ def process_const(self) -> None:
98
+ if 'const' not in self.extras:
99
+ return None
100
+ self.default = self.extras['const']
101
+ self.const = True
102
+ self.required = False
103
+ self.nullable = False
100
104
 
101
105
  @property
102
106
  def type_hint(self) -> str:
@@ -114,7 +118,10 @@ class DataModelFieldBase(_BaseModel):
114
118
  return type_hint
115
119
  elif self.required:
116
120
  return type_hint
117
- return get_optional_type(type_hint, self.data_type.use_union_operator)
121
+ elif self.fall_back_to_nullable:
122
+ return get_optional_type(type_hint, self.data_type.use_union_operator)
123
+ else:
124
+ return type_hint
118
125
 
119
126
  @property
120
127
  def imports(self) -> Tuple[Import, ...]:
@@ -128,10 +135,16 @@ class DataModelFieldBase(_BaseModel):
128
135
  )
129
136
  ]
130
137
 
131
- if (
132
- self.nullable or (self.nullable is None and not self.required)
133
- ) and not self.data_type.use_union_operator:
134
- imports.append((IMPORT_OPTIONAL,))
138
+ if self.fall_back_to_nullable:
139
+ if (
140
+ self.nullable or (self.nullable is None and not self.required)
141
+ ) and not self.data_type.use_union_operator:
142
+ imports.append((IMPORT_OPTIONAL,))
143
+ else:
144
+ if (
145
+ self.nullable and not self.data_type.use_union_operator
146
+ ): # pragma: no cover
147
+ imports.append((IMPORT_OPTIONAL,))
135
148
  if self.use_annotated:
136
149
  import_annotated = (
137
150
  IMPORT_ANNOTATED
@@ -174,6 +187,10 @@ class DataModelFieldBase(_BaseModel):
174
187
  def has_default_factory(self) -> bool:
175
188
  return 'default_factory' in self.extras
176
189
 
190
+ @property
191
+ def fall_back_to_nullable(self) -> bool:
192
+ return True
193
+
177
194
 
178
195
  @lru_cache()
179
196
  def get_template(template_file_path: Path) -> Template:
@@ -6,7 +6,7 @@ from typing import Any, ClassVar, DefaultDict, Dict, List, Optional, Set, Tuple
6
6
  from datamodel_code_generator.imports import Import
7
7
  from datamodel_code_generator.model import DataModel, DataModelFieldBase
8
8
  from datamodel_code_generator.model.base import UNDEFINED
9
- from datamodel_code_generator.model.improts import IMPORT_DATACLASS, IMPORT_FIELD
9
+ from datamodel_code_generator.model.imports import IMPORT_DATACLASS, IMPORT_FIELD
10
10
  from datamodel_code_generator.model.pydantic.base_model import Constraints
11
11
  from datamodel_code_generator.reference import Reference
12
12
  from datamodel_code_generator.types import chain_as_tuple
@@ -44,7 +44,7 @@ from datamodel_code_generator.model.pydantic.imports import (
44
44
  IMPORT_UUID4,
45
45
  IMPORT_UUID5,
46
46
  )
47
- from datamodel_code_generator.types import DataType, StrictTypes, Types
47
+ from datamodel_code_generator.types import DataType, StrictTypes, Types, UnionIntFloat
48
48
  from datamodel_code_generator.types import DataTypeManager as _DataTypeManager
49
49
 
50
50
 
@@ -155,7 +155,7 @@ class DataTypeManager(_DataTypeManager):
155
155
  use_union_operator,
156
156
  )
157
157
 
158
- self.type_map: Dict[Types, DataType] = type_map_factory(
158
+ self.type_map: Dict[Types, DataType] = self.type_map_factory(
159
159
  self.data_type,
160
160
  strict_types=self.strict_types,
161
161
  pattern_key=self.PATTERN_KEY,
@@ -177,6 +177,14 @@ class DataTypeManager(_DataTypeManager):
177
177
  'pattern': self.PATTERN_KEY,
178
178
  }
179
179
 
180
+ def type_map_factory(
181
+ self,
182
+ data_type: Type[DataType],
183
+ strict_types: Sequence[StrictTypes],
184
+ pattern_key: str,
185
+ ) -> Dict[Types, DataType]:
186
+ return type_map_factory(data_type, strict_types, pattern_key)
187
+
180
188
  def transform_kwargs(
181
189
  self, kwargs: Dict[str, Any], filter_: Set[str]
182
190
  ) -> Dict[str, str]:
@@ -253,7 +261,10 @@ class DataTypeManager(_DataTypeManager):
253
261
  if data_type_kwargs:
254
262
  return self.data_type.from_import(
255
263
  IMPORT_CONDECIMAL,
256
- kwargs={k: Decimal(v) for k, v in data_type_kwargs.items()},
264
+ kwargs={
265
+ k: Decimal(str(v) if isinstance(v, UnionIntFloat) else v)
266
+ for k, v in data_type_kwargs.items()
267
+ },
257
268
  )
258
269
  return self.type_map[types]
259
270
 
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Optional
3
+ from typing import Iterable, Optional
4
4
 
5
5
  from pydantic import BaseModel as _BaseModel
6
6
 
@@ -9,6 +9,10 @@ from .root_model import RootModel
9
9
  from .types import DataTypeManager
10
10
 
11
11
 
12
+ def dump_resolve_reference_action(class_names: Iterable[str]) -> str:
13
+ return '\n'.join(f'{class_name}.model_rebuild()' for class_name in class_names)
14
+
15
+
12
16
  class ConfigDict(_BaseModel):
13
17
  extra: Optional[str] = None
14
18
  title: Optional[str] = None
@@ -18,4 +22,10 @@ class ConfigDict(_BaseModel):
18
22
  arbitrary_types_allowed: Optional[bool] = None
19
23
 
20
24
 
21
- __all__ = ['BaseModel', 'DataModelField', 'RootModel', 'DataTypeManager']
25
+ __all__ = [
26
+ 'BaseModel',
27
+ 'DataModelField',
28
+ 'RootModel',
29
+ 'dump_resolve_reference_action',
30
+ 'DataTypeManager',
31
+ ]
@@ -61,6 +61,17 @@ class DataModelField(DataModelFieldV1):
61
61
  constraints: Optional[Constraints] = None
62
62
  _PARSE_METHOD: ClassVar[str] = 'model_validate'
63
63
 
64
+ def process_const(self) -> None:
65
+ if 'const' not in self.extras:
66
+ return None
67
+ self.const = True
68
+ self.nullable = False
69
+ const = self.extras['const']
70
+ if self.data_type.type == 'str' and isinstance(
71
+ const, str
72
+ ): # pragma: no cover # Literal supports only str
73
+ self.data_type = self.data_type.__class__(literals=[const])
74
+
64
75
  def _process_data_in_str(self, data: Dict[str, Any]) -> None:
65
76
  if self.const:
66
77
  # const is removed in pydantic 2.0
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, ClassVar
4
+
5
+ from datamodel_code_generator.model.pydantic_v2.base_model import BaseModel
6
+
7
+
8
+ class RootModel(BaseModel):
9
+ TEMPLATE_FILE_PATH: ClassVar[str] = 'pydantic_v2/RootModel.jinja2'
10
+ BASE_CLASS: ClassVar[str] = 'pydantic.RootModel'
11
+
12
+ def __init__(
13
+ self,
14
+ **kwargs: Any,
15
+ ) -> None:
16
+ # Remove custom_base_class for Pydantic V2 models; behaviour is different from Pydantic V1 as it will not
17
+ # be treated as a root model. custom_base_class cannot both implement BaseModel and RootModel!
18
+ if 'custom_base_class' in kwargs:
19
+ kwargs.pop('custom_base_class')
20
+
21
+ super().__init__(**kwargs)
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import ClassVar, Dict, Sequence, Type
4
+
5
+ from datamodel_code_generator.model.pydantic import DataTypeManager as _DataTypeManager
6
+ from datamodel_code_generator.model.pydantic.imports import IMPORT_CONSTR
7
+ from datamodel_code_generator.types import DataType, StrictTypes, Types
8
+
9
+
10
+ class DataTypeManager(_DataTypeManager):
11
+ PATTERN_KEY: ClassVar[str] = 'pattern'
12
+
13
+ def type_map_factory(
14
+ self,
15
+ data_type: Type[DataType],
16
+ strict_types: Sequence[StrictTypes],
17
+ pattern_key: str,
18
+ ) -> Dict[Types, DataType]:
19
+ return {
20
+ **super().type_map_factory(data_type, strict_types, pattern_key),
21
+ Types.hostname: self.data_type.from_import(
22
+ IMPORT_CONSTR,
23
+ strict=StrictTypes.str in strict_types,
24
+ # https://github.com/horejsek/python-fastjsonschema/blob/61c6997a8348b8df9b22e029ca2ba35ef441fbb8/fastjsonschema/draft04.py#L31
25
+ kwargs={
26
+ pattern_key: r"r'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9])$'",
27
+ **({'strict': True} if StrictTypes.str in strict_types else {}),
28
+ },
29
+ ),
30
+ }
@@ -16,7 +16,7 @@ from typing import (
16
16
  from datamodel_code_generator.imports import Import
17
17
  from datamodel_code_generator.model import DataModel, DataModelFieldBase
18
18
  from datamodel_code_generator.model.base import UNDEFINED
19
- from datamodel_code_generator.model.improts import (
19
+ from datamodel_code_generator.model.imports import (
20
20
  IMPORT_NOT_REQUIRED,
21
21
  IMPORT_NOT_REQUIRED_BACKPORT,
22
22
  IMPORT_TYPED_DICT,
@@ -139,6 +139,10 @@ class DataModelField(DataModelFieldBase):
139
139
  def _not_required(self) -> bool:
140
140
  return not self.required and isinstance(self.parent, TypedDict)
141
141
 
142
+ @property
143
+ def fall_back_to_nullable(self) -> bool:
144
+ return not self._not_required
145
+
142
146
  @property
143
147
  def imports(self) -> Tuple[Import, ...]:
144
148
  return (
@@ -28,7 +28,6 @@ from pydantic import BaseModel
28
28
  from datamodel_code_generator.format import CodeFormatter, PythonVersion
29
29
  from datamodel_code_generator.imports import IMPORT_ANNOTATIONS, Import, Imports
30
30
  from datamodel_code_generator.model import pydantic as pydantic_model
31
- from datamodel_code_generator.model import pydantic_v2 as pydantic_v2_model
32
31
  from datamodel_code_generator.model.base import (
33
32
  ALL_MODEL,
34
33
  UNDEFINED,
@@ -38,6 +37,7 @@ from datamodel_code_generator.model.base import (
38
37
  DataModelFieldBase,
39
38
  )
40
39
  from datamodel_code_generator.model.enum import Enum, Member
40
+ from datamodel_code_generator.model.pydantic_v2 import RootModel
41
41
  from datamodel_code_generator.parser import DefaultPutDict, LiteralType
42
42
  from datamodel_code_generator.reference import ModelResolver, Reference
43
43
  from datamodel_code_generator.types import DataType, DataTypeManager, StrictTypes
@@ -723,10 +723,7 @@ class Parser(ABC):
723
723
  def __replace_unique_list_to_set(self, models: List[DataModel]) -> None:
724
724
  for model in models:
725
725
  for model_field in model.fields:
726
- if not (
727
- isinstance(model_field, pydantic_v2_model.DataModelField)
728
- or self.use_unique_items_as_set
729
- ):
726
+ if not self.use_unique_items_as_set:
730
727
  continue
731
728
 
732
729
  if not (
@@ -797,10 +794,11 @@ class Parser(ABC):
797
794
  models.remove(duplicate)
798
795
 
799
796
  def __collapse_root_models(
800
- self, models: List[DataModel], unused_models: List[DataModel]
797
+ self, models: List[DataModel], unused_models: List[DataModel], imports: Imports
801
798
  ) -> None:
802
799
  if not self.collapse_root_models:
803
800
  return None
801
+ unused_model_count = len(unused_models)
804
802
  for model in models:
805
803
  for model_field in model.fields:
806
804
  for data_type in model_field.data_type.all_data_types:
@@ -834,6 +832,8 @@ class Parser(ABC):
834
832
  model_field.extras = dict(
835
833
  root_type_field.extras, **model_field.extras
836
834
  )
835
+ model_field.process_const()
836
+
837
837
  if self.field_constraints:
838
838
  if isinstance(
839
839
  root_type_field.constraints, ConstraintsBase
@@ -876,6 +876,17 @@ class Parser(ABC):
876
876
  if not root_type_model.reference.children:
877
877
  unused_models.append(root_type_model)
878
878
 
879
+ if self.data_model_root_type == RootModel and unused_model_count != len(
880
+ unused_models
881
+ ):
882
+ if {m for m in models if isinstance(m, RootModel)} - { # pragma: no cover
883
+ m for m in unused_models if isinstance(m, RootModel)
884
+ }:
885
+ return None # pragma: no cover
886
+
887
+ if 'RootModel' in imports['pydantic']: # pragma: no cover
888
+ imports['pydantic'].remove('RootModel')
889
+
879
890
  def __set_default_enum_member(
880
891
  self,
881
892
  models: List[DataModel],
@@ -1096,7 +1107,7 @@ class Parser(ABC):
1096
1107
  self.__extract_inherited_enum(models)
1097
1108
  self.__set_reference_default_value_to_field(models)
1098
1109
  self.__reuse_model(models, require_update_action_models)
1099
- self.__collapse_root_models(models, unused_models)
1110
+ self.__collapse_root_models(models, unused_models, imports)
1100
1111
  self.__set_default_enum_member(models)
1101
1112
  self.__override_required_field(models)
1102
1113
  self.__sort_models(models, imports)
@@ -173,6 +173,10 @@ class JsonSchemaObject(BaseModel):
173
173
  def get_fields(cls) -> Dict[str, Any]:
174
174
  return cls.__fields__
175
175
 
176
+ @classmethod
177
+ def model_rebuild(cls) -> None:
178
+ cls.update_forward_refs()
179
+
176
180
  __constraint_fields__: Set[str] = {
177
181
  'exclusiveMinimum',
178
182
  'minimum',
@@ -339,7 +343,7 @@ def _get_type(type_: str, format__: Optional[str] = None) -> Types:
339
343
  return json_schema_data_formats[type_]['default']
340
344
 
341
345
 
342
- JsonSchemaObject.update_forward_refs()
346
+ JsonSchemaObject.model_rebuild()
343
347
 
344
348
  DEFAULT_FIELD_KEYS: Set[str] = {
345
349
  'example',
@@ -479,7 +479,11 @@ class OpenAPIParser(JsonSchemaParser):
479
479
 
480
480
  if OpenAPIScope.Parameters in self.open_api_scopes and fields:
481
481
  self.results.append(
482
- self.data_model_type(fields=fields, reference=reference)
482
+ self.data_model_type(
483
+ fields=fields,
484
+ reference=reference,
485
+ custom_base_class=self.base_class,
486
+ )
483
487
  )
484
488
 
485
489
  def parse_operation(
@@ -110,6 +110,9 @@ class UnionIntFloat:
110
110
  def __float__(self) -> float:
111
111
  return float(self.value)
112
112
 
113
+ def __str__(self) -> str:
114
+ return str(self.value)
115
+
113
116
  @classmethod
114
117
  def __get_validators__(cls) -> Iterator[Callable[[Any], Any]]:
115
118
  yield cls.validate
@@ -234,6 +237,11 @@ class DataType(_BaseModel):
234
237
  revalidate_instances='never',
235
238
  )
236
239
  else:
240
+ if not TYPE_CHECKING:
241
+
242
+ @classmethod
243
+ def model_rebuild(cls) -> None:
244
+ cls.update_forward_refs()
237
245
 
238
246
  class Config:
239
247
  extra = 'forbid'
@@ -498,7 +506,7 @@ class DataType(_BaseModel):
498
506
  return len(self.data_types) > 1
499
507
 
500
508
 
501
- DataType.update_forward_refs()
509
+ DataType.model_rebuild()
502
510
 
503
511
  DataTypeT = TypeVar('DataTypeT', bound=DataType)
504
512
 
@@ -0,0 +1 @@
1
+ version: str = '0.21.4'
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "datamodel-code-generator"
3
- version = "0.21.2"
3
+ version = "0.21.4"
4
4
  description = "Datamodel Code Generator"
5
5
  authors = ["Koudai Aono <koxudaxi@gmail.com>"]
6
6
  readme = "README.md"
@@ -48,7 +48,7 @@ pydantic = [
48
48
  ]
49
49
  argcomplete = ">=1.10,<4.0"
50
50
  prance = ">=0.18.2"
51
- openapi-spec-validator = ">=0.2.8,<=0.5.2"
51
+ openapi-spec-validator = ">=0.2.8,<=0.5.7"
52
52
  jinja2 = ">=2.10.1,<4.0"
53
53
  inflect = ">=4.1.0,<6.0"
54
54
  black = ">=19.10b0"
@@ -1,10 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import ClassVar
4
-
5
- from datamodel_code_generator.model.pydantic_v2.base_model import BaseModel
6
-
7
-
8
- class RootModel(BaseModel):
9
- TEMPLATE_FILE_PATH: ClassVar[str] = 'pydantic_v2/RootModel.jinja2'
10
- BASE_CLASS: ClassVar[str] = 'pydantic.RootModel'
@@ -1,9 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import ClassVar
4
-
5
- from datamodel_code_generator.model.pydantic import DataTypeManager as _DataTypeManager
6
-
7
-
8
- class DataTypeManager(_DataTypeManager):
9
- PATTERN_KEY: ClassVar[str] = 'pattern'
@@ -1 +0,0 @@
1
- version: str = '0.21.2'