datamodel-code-generator 0.26.2__tar.gz → 0.26.3__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 (60) hide show
  1. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/PKG-INFO +2 -2
  2. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/README.md +1 -1
  3. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/__init__.py +1 -1
  4. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/imports.py +1 -0
  5. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/msgspec.py +72 -4
  6. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic_v2/__init__.py +1 -0
  7. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/msgspec.jinja2 +3 -1
  8. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/parser/base.py +48 -17
  9. datamodel_code_generator-0.26.3/datamodel_code_generator/version.py +1 -0
  10. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/pyproject.toml +3 -3
  11. datamodel_code_generator-0.26.2/datamodel_code_generator/version.py +0 -1
  12. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/LICENSE +0 -0
  13. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/__init__.py +0 -0
  14. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/__main__.py +0 -0
  15. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/arguments.py +0 -0
  16. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/format.py +0 -0
  17. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/http.py +0 -0
  18. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/imports.py +0 -0
  19. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/base.py +0 -0
  20. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/dataclass.py +0 -0
  21. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/enum.py +0 -0
  22. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic/__init__.py +0 -0
  23. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic/base_model.py +0 -0
  24. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic/custom_root_type.py +0 -0
  25. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic/dataclass.py +0 -0
  26. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic/imports.py +0 -0
  27. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic/types.py +0 -0
  28. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic_v2/base_model.py +0 -0
  29. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic_v2/imports.py +0 -0
  30. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic_v2/root_model.py +0 -0
  31. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/pydantic_v2/types.py +0 -0
  32. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/rootmodel.py +0 -0
  33. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/scalar.py +0 -0
  34. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/Enum.jinja2 +0 -0
  35. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/Scalar.jinja2 +0 -0
  36. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/TypedDict.jinja2 +0 -0
  37. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/TypedDictClass.jinja2 +0 -0
  38. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/TypedDictFunction.jinja2 +0 -0
  39. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/Union.jinja2 +0 -0
  40. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/dataclass.jinja2 +0 -0
  41. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/pydantic/BaseModel.jinja2 +0 -0
  42. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/pydantic/BaseModel_root.jinja2 +0 -0
  43. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/pydantic/Config.jinja2 +0 -0
  44. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/pydantic/dataclass.jinja2 +0 -0
  45. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 +0 -0
  46. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/pydantic_v2/ConfigDict.jinja2 +0 -0
  47. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 +0 -0
  48. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/template/root.jinja2 +0 -0
  49. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/typed_dict.py +0 -0
  50. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/types.py +0 -0
  51. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/model/union.py +0 -0
  52. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/parser/__init__.py +0 -0
  53. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/parser/graphql.py +0 -0
  54. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/parser/jsonschema.py +0 -0
  55. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/parser/openapi.py +0 -0
  56. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/py.typed +0 -0
  57. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/pydantic_patch.py +0 -0
  58. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/reference.py +0 -0
  59. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/datamodel_code_generator/types.py +0 -0
  60. {datamodel_code_generator-0.26.2 → datamodel_code_generator-0.26.3}/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.26.2
3
+ Version: 0.26.3
4
4
  Summary: Datamodel Code Generator
5
5
  Home-page: https://github.com/koxudaxi/datamodel-code-generator
6
6
  License: MIT
@@ -500,7 +500,7 @@ Model customization:
500
500
  --output-datetime-class {datetime,AwareDatetime,NaiveDatetime}
501
501
  Choose Datetime class between AwareDatetime, NaiveDatetime or
502
502
  datetime. Each output model has its default mapping, and only
503
- pydantic and dataclass support this override"
503
+ pydantic, dataclass, and msgspec support this override"
504
504
  --reuse-model Reuse models on the field when a module has the model with the same
505
505
  content
506
506
  --target-python-version {3.6,3.7,3.8,3.9,3.10,3.11,3.12}
@@ -455,7 +455,7 @@ Model customization:
455
455
  --output-datetime-class {datetime,AwareDatetime,NaiveDatetime}
456
456
  Choose Datetime class between AwareDatetime, NaiveDatetime or
457
457
  datetime. Each output model has its default mapping, and only
458
- pydantic and dataclass support this override"
458
+ pydantic, dataclass, and msgspec support this override"
459
459
  --reuse-model Reuse models on the field when a module has the model with the same
460
460
  content
461
461
  --target-python-version {3.6,3.7,3.8,3.9,3.10,3.11,3.12}
@@ -68,7 +68,7 @@ def get_data_model_types(
68
68
  data_model=msgspec.Struct,
69
69
  root_model=msgspec.RootModel,
70
70
  field_model=msgspec.DataModelField,
71
- data_type_manager=DataTypeManager,
71
+ data_type_manager=msgspec.DataTypeManager,
72
72
  dump_resolve_reference_action=None,
73
73
  known_third_party=['msgspec'],
74
74
  )
@@ -2,6 +2,7 @@ from datamodel_code_generator.imports import Import
2
2
 
3
3
  IMPORT_DATACLASS = Import.from_full_path('dataclasses.dataclass')
4
4
  IMPORT_FIELD = Import.from_full_path('dataclasses.field')
5
+ IMPORT_CLASSVAR = Import.from_full_path('typing.ClassVar')
5
6
  IMPORT_TYPED_DICT = Import.from_full_path('typing.TypedDict')
6
7
  IMPORT_TYPED_DICT_BACKPORT = Import.from_full_path('typing_extensions.TypedDict')
7
8
  IMPORT_NOT_REQUIRED = Import.from_full_path('typing.NotRequired')
@@ -7,6 +7,7 @@ from typing import (
7
7
  Dict,
8
8
  List,
9
9
  Optional,
10
+ Sequence,
10
11
  Set,
11
12
  Tuple,
12
13
  Type,
@@ -15,10 +16,18 @@ from typing import (
15
16
 
16
17
  from pydantic import Field
17
18
 
18
- from datamodel_code_generator.imports import Import
19
+ from datamodel_code_generator import DatetimeClassType, PythonVersion
20
+ from datamodel_code_generator.imports import (
21
+ IMPORT_DATE,
22
+ IMPORT_DATETIME,
23
+ IMPORT_TIME,
24
+ IMPORT_TIMEDELTA,
25
+ Import,
26
+ )
19
27
  from datamodel_code_generator.model import DataModel, DataModelFieldBase
20
28
  from datamodel_code_generator.model.base import UNDEFINED
21
29
  from datamodel_code_generator.model.imports import (
30
+ IMPORT_CLASSVAR,
22
31
  IMPORT_MSGSPEC_CONVERT,
23
32
  IMPORT_MSGSPEC_FIELD,
24
33
  IMPORT_MSGSPEC_META,
@@ -28,8 +37,16 @@ from datamodel_code_generator.model.pydantic.base_model import (
28
37
  Constraints as _Constraints,
29
38
  )
30
39
  from datamodel_code_generator.model.rootmodel import RootModel as _RootModel
40
+ from datamodel_code_generator.model.types import DataTypeManager as _DataTypeManager
41
+ from datamodel_code_generator.model.types import type_map_factory
31
42
  from datamodel_code_generator.reference import Reference
32
- from datamodel_code_generator.types import chain_as_tuple, get_optional_type
43
+ from datamodel_code_generator.types import (
44
+ DataType,
45
+ StrictTypes,
46
+ Types,
47
+ chain_as_tuple,
48
+ get_optional_type,
49
+ )
33
50
 
34
51
 
35
52
  def _has_field_assignment(field: DataModelFieldBase) -> bool:
@@ -56,6 +73,8 @@ def import_extender(cls: Type[DataModelFieldBaseT]) -> Type[DataModelFieldBaseT]
56
73
  extra_imports.append(IMPORT_MSGSPEC_CONVERT)
57
74
  if self.annotated:
58
75
  extra_imports.append(IMPORT_MSGSPEC_META)
76
+ if self.extras.get('is_classvar'):
77
+ extra_imports.append(IMPORT_CLASSVAR)
59
78
  return chain_as_tuple(original_imports.fget(self), extra_imports) # type: ignore
60
79
 
61
80
  setattr(cls, 'imports', property(new_imports))
@@ -103,6 +122,10 @@ class Struct(DataModel):
103
122
  nullable=nullable,
104
123
  keyword_only=keyword_only,
105
124
  )
125
+ self.extra_template_data.setdefault('base_class_kwargs', {})
126
+
127
+ def add_base_class_kwarg(self, name: str, value):
128
+ self.extra_template_data['base_class_kwargs'][name] = value
106
129
 
107
130
 
108
131
  class Constraints(_Constraints):
@@ -241,11 +264,16 @@ class DataModelField(DataModelFieldBase):
241
264
 
242
265
  meta = f'Meta({", ".join(meta_arguments)})'
243
266
 
244
- if not self.required:
267
+ if not self.required and not self.extras.get('is_classvar'):
245
268
  type_hint = self.data_type.type_hint
246
269
  annotated_type = f'Annotated[{type_hint}, {meta}]'
247
270
  return get_optional_type(annotated_type, self.data_type.use_union_operator)
248
- return f'Annotated[{self.type_hint}, {meta}]'
271
+
272
+ annotated_type = f'Annotated[{self.type_hint}, {meta}]'
273
+ if self.extras.get('is_classvar'):
274
+ annotated_type = f'ClassVar[{annotated_type}]'
275
+
276
+ return annotated_type
249
277
 
250
278
  def _get_default_as_struct_model(self) -> Optional[str]:
251
279
  for data_type in self.data_type.data_types or (self.data_type,):
@@ -267,3 +295,43 @@ class DataModelField(DataModelFieldBase):
267
295
  elif data_type.reference and isinstance(data_type.reference.source, Struct):
268
296
  return f'lambda: {self._PARSE_METHOD}({repr(self.default)}, type={data_type.alias or data_type.reference.source.class_name})'
269
297
  return None
298
+
299
+
300
+ class DataTypeManager(_DataTypeManager):
301
+ def __init__(
302
+ self,
303
+ python_version: PythonVersion = PythonVersion.PY_38,
304
+ use_standard_collections: bool = False,
305
+ use_generic_container_types: bool = False,
306
+ strict_types: Optional[Sequence[StrictTypes]] = None,
307
+ use_non_positive_negative_number_constrained_types: bool = False,
308
+ use_union_operator: bool = False,
309
+ use_pendulum: bool = False,
310
+ target_datetime_class: DatetimeClassType = DatetimeClassType.Datetime,
311
+ ):
312
+ super().__init__(
313
+ python_version,
314
+ use_standard_collections,
315
+ use_generic_container_types,
316
+ strict_types,
317
+ use_non_positive_negative_number_constrained_types,
318
+ use_union_operator,
319
+ use_pendulum,
320
+ target_datetime_class,
321
+ )
322
+
323
+ datetime_map = (
324
+ {
325
+ Types.time: self.data_type.from_import(IMPORT_TIME),
326
+ Types.date: self.data_type.from_import(IMPORT_DATE),
327
+ Types.date_time: self.data_type.from_import(IMPORT_DATETIME),
328
+ Types.timedelta: self.data_type.from_import(IMPORT_TIMEDELTA),
329
+ }
330
+ if target_datetime_class is DatetimeClassType.Datetime
331
+ else {}
332
+ )
333
+
334
+ self.type_map: Dict[Types, DataType] = {
335
+ **type_map_factory(self.data_type),
336
+ **datetime_map,
337
+ }
@@ -23,6 +23,7 @@ class ConfigDict(_BaseModel):
23
23
  arbitrary_types_allowed: Optional[bool] = None
24
24
  protected_namespaces: Optional[Tuple[str, ...]] = None
25
25
  regex_engine: Optional[str] = None
26
+ use_enum_values: Optional[bool] = None
26
27
 
27
28
 
28
29
  __all__ = [
@@ -2,7 +2,9 @@
2
2
  {{ decorator }}
3
3
  {% endfor -%}
4
4
  {%- if base_class %}
5
- class {{ class_name }}({{ base_class }}):
5
+ class {{ class_name }}({{ base_class }}{%- for key, value in (base_class_kwargs|default({})).items() -%}
6
+ , {{ key }}={{ value }}
7
+ {%- endfor -%}):
6
8
  {%- else %}
7
9
  class {{ class_name }}:
8
10
  {%- endif %}
@@ -39,6 +39,7 @@ from datamodel_code_generator.imports import (
39
39
  Imports,
40
40
  )
41
41
  from datamodel_code_generator.model import dataclass as dataclass_model
42
+ from datamodel_code_generator.model import msgspec as msgspec_model
42
43
  from datamodel_code_generator.model import pydantic as pydantic_model
43
44
  from datamodel_code_generator.model import pydantic_v2 as pydantic_model_v2
44
45
  from datamodel_code_generator.model.base import (
@@ -803,35 +804,54 @@ class Parser(ABC):
803
804
  if not data_type.reference: # pragma: no cover
804
805
  continue
805
806
  discriminator_model = data_type.reference.source
807
+
806
808
  if not isinstance( # pragma: no cover
807
809
  discriminator_model,
808
810
  (
809
811
  pydantic_model.BaseModel,
810
812
  pydantic_model_v2.BaseModel,
811
813
  dataclass_model.DataClass,
814
+ msgspec_model.Struct,
812
815
  ),
813
816
  ):
814
817
  continue # pragma: no cover
815
- type_names = []
816
- if mapping:
818
+
819
+ type_names: List[str] = []
820
+
821
+ def check_paths(
822
+ model: Union[
823
+ pydantic_model.BaseModel,
824
+ pydantic_model_v2.BaseModel,
825
+ Reference,
826
+ ],
827
+ mapping: Dict[str, str],
828
+ type_names: List[str] = type_names,
829
+ ) -> None:
830
+ """Helper function to validate paths for a given model."""
817
831
  for name, path in mapping.items():
818
832
  if (
819
- discriminator_model.path.split('#/')[-1]
820
- != path.split('#/')[-1]
833
+ model.path.split('#/')[-1] != path.split('#/')[-1]
834
+ ) and (
835
+ path.startswith('#/')
836
+ or model.path[:-1] != path.split('/')[-1]
821
837
  ):
822
- if (
823
- path.startswith('#/')
824
- or discriminator_model.path[:-1]
825
- != path.split('/')[-1]
826
- ):
827
- t_path = path[str(path).find('/') + 1 :]
828
- t_disc = discriminator_model.path[
829
- : str(discriminator_model.path).find('#')
830
- ].lstrip('../')
831
- t_disc_2 = '/'.join(t_disc.split('/')[1:])
832
- if t_path != t_disc and t_path != t_disc_2:
833
- continue
838
+ t_path = path[str(path).find('/') + 1 :]
839
+ t_disc = model.path[: str(model.path).find('#')].lstrip(
840
+ '../'
841
+ )
842
+ t_disc_2 = '/'.join(t_disc.split('/')[1:])
843
+ if t_path != t_disc and t_path != t_disc_2:
844
+ continue
834
845
  type_names.append(name)
846
+
847
+ # Check the main discriminator model path
848
+ if mapping:
849
+ check_paths(discriminator_model, mapping)
850
+
851
+ # Check the base_classes if they exist
852
+ if len(type_names) == 0:
853
+ for base_class in discriminator_model.base_classes:
854
+ check_paths(base_class.reference, mapping)
835
855
  else:
836
856
  type_names = [discriminator_model.path.split('/')[-1]]
837
857
  if not type_names: # pragma: no cover
@@ -852,6 +872,16 @@ class Parser(ABC):
852
872
  else None
853
873
  ):
854
874
  has_one_literal = True
875
+ if isinstance(
876
+ discriminator_model, msgspec_model.Struct
877
+ ): # pragma: no cover
878
+ discriminator_model.add_base_class_kwarg(
879
+ 'tag_field', f"'{property_name}'"
880
+ )
881
+ discriminator_model.add_base_class_kwarg(
882
+ 'tag', discriminator_field.represented_default
883
+ )
884
+ discriminator_field.extras['is_classvar'] = True
855
885
  continue
856
886
  for (
857
887
  field_data_type
@@ -879,7 +909,8 @@ class Parser(ABC):
879
909
  else IMPORT_LITERAL_BACKPORT
880
910
  )
881
911
  has_imported_literal = any(
882
- literal == import_ for import_ in imports
912
+ literal == import_ # type: ignore [comparison-overlap]
913
+ for import_ in imports
883
914
  )
884
915
  if has_imported_literal: # pragma: no cover
885
916
  imports.append(literal)
@@ -0,0 +1 @@
1
+ version: str = '0.26.3'
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "datamodel-code-generator"
3
- version = "0.26.2"
3
+ version = "0.26.3"
4
4
  description = "Datamodel Code Generator"
5
5
  authors = ["Koudai Aono <koxudaxi@gmail.com>"]
6
6
  readme = "README.md"
@@ -68,7 +68,7 @@ pytest-benchmark = "*"
68
68
  pytest-cov = ">=2.12.1"
69
69
  pytest-mock = "*"
70
70
  mypy = ">=1.4.1,<1.5.0"
71
- black = "^23.3.0"
71
+ black = ">=23.3,<25.0"
72
72
  freezegun = "*"
73
73
  types-Jinja2 = "*"
74
74
  types-PyYAML = "*"
@@ -77,7 +77,7 @@ types-setuptools = ">=67.6.0.5,<70.0.0.0"
77
77
  pydantic = "*"
78
78
  httpx = ">=0.24.1"
79
79
  PySnooper = "*"
80
- ruff = ">=0.0.290,<0.5.7"
80
+ ruff = ">=0.0.290,<0.6.10"
81
81
  ruff-lsp = ">=0.0.39,<0.0.41"
82
82
  pre-commit = "*"
83
83
  pytest-xdist = "^3.3.1"
@@ -1 +0,0 @@
1
- version: str = '0.26.2'