datamodel-code-generator 0.25.4__tar.gz → 0.25.6__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 (59) hide show
  1. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/PKG-INFO +7 -1
  2. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/README.md +6 -0
  3. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/__init__.py +8 -3
  4. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/__main__.py +22 -2
  5. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/arguments.py +12 -0
  6. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/format.py +6 -9
  7. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/http.py +6 -1
  8. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/imports.py +4 -0
  9. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/base.py +1 -2
  10. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/msgspec.py +1 -0
  11. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic/types.py +16 -2
  12. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 +1 -1
  13. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/types.py +2 -0
  14. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/parser/base.py +45 -26
  15. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/parser/graphql.py +4 -0
  16. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/parser/jsonschema.py +8 -3
  17. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/parser/openapi.py +4 -0
  18. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/types.py +3 -0
  19. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/util.py +1 -2
  20. datamodel_code_generator-0.25.6/datamodel_code_generator/version.py +1 -0
  21. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/pyproject.toml +2 -2
  22. datamodel_code_generator-0.25.4/datamodel_code_generator/version.py +0 -1
  23. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/LICENSE +0 -0
  24. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/__init__.py +0 -0
  25. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/dataclass.py +0 -0
  26. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/enum.py +0 -0
  27. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/imports.py +0 -0
  28. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic/__init__.py +0 -0
  29. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic/base_model.py +0 -0
  30. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic/custom_root_type.py +0 -0
  31. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic/dataclass.py +0 -0
  32. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic/imports.py +0 -0
  33. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic_v2/__init__.py +0 -0
  34. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic_v2/base_model.py +0 -0
  35. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic_v2/imports.py +0 -0
  36. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic_v2/root_model.py +0 -0
  37. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/pydantic_v2/types.py +0 -0
  38. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/rootmodel.py +0 -0
  39. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/scalar.py +0 -0
  40. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/Enum.jinja2 +0 -0
  41. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/Scalar.jinja2 +0 -0
  42. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/TypedDict.jinja2 +0 -0
  43. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/TypedDictClass.jinja2 +0 -0
  44. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/TypedDictFunction.jinja2 +0 -0
  45. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/Union.jinja2 +0 -0
  46. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/dataclass.jinja2 +0 -0
  47. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/msgspec.jinja2 +0 -0
  48. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/pydantic/BaseModel.jinja2 +0 -0
  49. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/pydantic/BaseModel_root.jinja2 +0 -0
  50. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/pydantic/Config.jinja2 +0 -0
  51. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/pydantic/dataclass.jinja2 +0 -0
  52. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 +0 -0
  53. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/pydantic_v2/ConfigDict.jinja2 +0 -0
  54. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/template/root.jinja2 +0 -0
  55. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/typed_dict.py +0 -0
  56. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/model/union.py +0 -0
  57. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/parser/__init__.py +0 -0
  58. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/py.typed +0 -0
  59. {datamodel_code_generator-0.25.4 → datamodel_code_generator-0.25.6}/datamodel_code_generator/reference.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: datamodel-code-generator
3
- Version: 0.25.4
3
+ Version: 0.25.6
4
4
  Summary: Datamodel Code Generator
5
5
  Home-page: https://github.com/koxudaxi/datamodel-code-generator
6
6
  License: MIT
@@ -376,6 +376,9 @@ Options:
376
376
  (example: "Authorization: Basic dXNlcjpwYXNz")
377
377
  --http-ignore-tls Disable verification of the remote host's TLS
378
378
  certificate
379
+ --http-query-parameters QUERY_PARAMETER [QUERY_PARAMETER ...]
380
+ Set query parameters in HTTP requests to the remote host.
381
+ (example: "ref=branch")
379
382
  --input INPUT Input file/directory (default: stdin)
380
383
  --input-file-type {auto,openapi,graphql,jsonschema,json,yaml,dict,csv}
381
384
  Input file type (default: auto)
@@ -447,6 +450,9 @@ Field customization:
447
450
  Fields that have default values.
448
451
  --use-field-description
449
452
  Use schema description to populate field docstring
453
+ --use-pendulum
454
+ Use pendulum instead of `datetime` for `date`,
455
+ `datetime`, and `time` data types
450
456
 
451
457
  Model customization:
452
458
  --allow-extra-fields Allow to pass extra fields, if this flag is not
@@ -331,6 +331,9 @@ Options:
331
331
  (example: "Authorization: Basic dXNlcjpwYXNz")
332
332
  --http-ignore-tls Disable verification of the remote host's TLS
333
333
  certificate
334
+ --http-query-parameters QUERY_PARAMETER [QUERY_PARAMETER ...]
335
+ Set query parameters in HTTP requests to the remote host.
336
+ (example: "ref=branch")
334
337
  --input INPUT Input file/directory (default: stdin)
335
338
  --input-file-type {auto,openapi,graphql,jsonschema,json,yaml,dict,csv}
336
339
  Input file type (default: auto)
@@ -402,6 +405,9 @@ Field customization:
402
405
  Fields that have default values.
403
406
  --use-field-description
404
407
  Use schema description to populate field docstring
408
+ --use-pendulum
409
+ Use pendulum instead of `datetime` for `date`,
410
+ `datetime`, and `time` data types
405
411
 
406
412
  Model customization:
407
413
  --allow-extra-fields Allow to pass extra fields, if this flag is not
@@ -58,8 +58,7 @@ def load_yaml_from_path(path: Path, encoding: str) -> Any:
58
58
 
59
59
  if TYPE_CHECKING:
60
60
 
61
- def get_version() -> str:
62
- ...
61
+ def get_version() -> str: ...
63
62
 
64
63
  else:
65
64
 
@@ -300,6 +299,8 @@ def generate(
300
299
  custom_file_header_path: Optional[Path] = None,
301
300
  custom_formatters: Optional[List[str]] = None,
302
301
  custom_formatters_kwargs: Optional[Dict[str, Any]] = None,
302
+ use_pendulum: bool = False,
303
+ http_query_parameters: Optional[Sequence[Tuple[str, str]]] = None,
303
304
  ) -> None:
304
305
  remote_text_cache: DefaultPutDict[str, str] = DefaultPutDict()
305
306
  if isinstance(input_, str):
@@ -309,7 +310,9 @@ def generate(
309
310
 
310
311
  input_text = remote_text_cache.get_or_put(
311
312
  input_.geturl(),
312
- default_factory=lambda url: get_body(url, http_headers, http_ignore_tls),
313
+ default_factory=lambda url: get_body(
314
+ url, http_headers, http_ignore_tls, http_query_parameters
315
+ ),
313
316
  )
314
317
  else:
315
318
  input_text = None
@@ -456,6 +459,8 @@ def generate(
456
459
  known_third_party=data_model_types.known_third_party,
457
460
  custom_formatters=custom_formatters,
458
461
  custom_formatters_kwargs=custom_formatters_kwargs,
462
+ use_pendulum=use_pendulum,
463
+ http_query_parameters=http_query_parameters,
459
464
  **kwargs,
460
465
  )
461
466
 
@@ -94,8 +94,7 @@ class Config(BaseModel):
94
94
  if TYPE_CHECKING:
95
95
 
96
96
  @classmethod
97
- def get_fields(cls) -> Dict[str, Any]:
98
- ...
97
+ def get_fields(cls) -> Dict[str, Any]: ...
99
98
 
100
99
  else:
101
100
 
@@ -198,6 +197,23 @@ class Config(BaseModel):
198
197
  return [validate_each_item(each_item) for each_item in value]
199
198
  return value # pragma: no cover
200
199
 
200
+ @field_validator('http_query_parameters', mode='before')
201
+ def validate_http_query_parameters(
202
+ cls, value: Any
203
+ ) -> Optional[List[Tuple[str, str]]]:
204
+ def validate_each_item(each_item: Any) -> Tuple[str, str]:
205
+ if isinstance(each_item, str): # pragma: no cover
206
+ try:
207
+ field_name, field_value = each_item.split('=', maxsplit=1) # type: str, str
208
+ return field_name, field_value.lstrip()
209
+ except ValueError:
210
+ raise Error(f'Invalid http query parameter: {each_item!r}')
211
+ return each_item # pragma: no cover
212
+
213
+ if isinstance(value, list):
214
+ return [validate_each_item(each_item) for each_item in value]
215
+ return value # pragma: no cover
216
+
201
217
  @model_validator(mode='before')
202
218
  def validate_additional_imports(cls, values: Dict[str, Any]) -> Dict[str, Any]:
203
219
  if values.get('additional_imports') is not None:
@@ -294,6 +310,8 @@ class Config(BaseModel):
294
310
  custom_file_header_path: Optional[Path] = None
295
311
  custom_formatters: Optional[List[str]] = None
296
312
  custom_formatters_kwargs: Optional[TextIOBase] = None
313
+ use_pendulum: bool = False
314
+ http_query_parameters: Optional[Sequence[Tuple[str, str]]] = None
297
315
 
298
316
  def merge_args(self, args: Namespace) -> None:
299
317
  set_args = {
@@ -488,6 +506,8 @@ def main(args: Optional[Sequence[str]] = None) -> Exit:
488
506
  custom_file_header_path=config.custom_file_header_path,
489
507
  custom_formatters=config.custom_formatters,
490
508
  custom_formatters_kwargs=custom_formatters_kwargs,
509
+ use_pendulum=config.use_pendulum,
510
+ http_query_parameters=config.http_query_parameters,
491
511
  )
492
512
  return Exit.OK
493
513
  except InvalidClassNameError as e:
@@ -57,6 +57,12 @@ base_options.add_argument(
57
57
  metavar='HTTP_HEADER',
58
58
  help='Set headers in HTTP requests to the remote host. (example: "Authorization: Basic dXNlcjpwYXNz")',
59
59
  )
60
+ base_options.add_argument(
61
+ '--http-query-parameters',
62
+ nargs='+',
63
+ metavar='HTTP_QUERY_PARAMETERS',
64
+ help='Set query parameters in HTTP requests to the remote host. (example: "ref=branch")',
65
+ )
60
66
  base_options.add_argument(
61
67
  '--http-ignore-tls',
62
68
  help="Disable verification of the remote host's TLS certificate",
@@ -166,6 +172,12 @@ model_options.add_argument(
166
172
  action='store_true',
167
173
  default=None,
168
174
  )
175
+ model_options.add_argument(
176
+ '--use-pendulum',
177
+ help='use pendulum instead of datetime',
178
+ action='store_true',
179
+ default=False,
180
+ )
169
181
 
170
182
  # ======================================================================================
171
183
  # Typing options for generated models
@@ -76,8 +76,7 @@ class PythonVersion(Enum):
76
76
 
77
77
  if TYPE_CHECKING:
78
78
 
79
- class _TargetVersion(Enum):
80
- ...
79
+ class _TargetVersion(Enum): ...
81
80
 
82
81
  BLACK_PYTHON_VERSION: Dict[PythonVersion, _TargetVersion]
83
82
  else:
@@ -98,8 +97,7 @@ def black_find_project_root(sources: Sequence[Path]) -> Path:
98
97
 
99
98
  def _find_project_root(
100
99
  srcs: Union[Sequence[str], Iterable[str]],
101
- ) -> Union[Tuple[Path, str], Path]:
102
- ...
100
+ ) -> Union[Tuple[Path, str], Path]: ...
103
101
 
104
102
  else:
105
103
  from black import find_project_root as _find_project_root
@@ -153,9 +151,9 @@ class CodeFormatter:
153
151
  f' for wrapping string literal in {black.__version__}'
154
152
  )
155
153
  elif black.__version__ < '24.1.0': # type: ignore
156
- black_kwargs[
157
- 'experimental_string_processing'
158
- ] = experimental_string_processing
154
+ black_kwargs['experimental_string_processing'] = (
155
+ experimental_string_processing
156
+ )
159
157
  elif experimental_string_processing:
160
158
  black_kwargs['preview'] = True
161
159
  black_kwargs['unstable'] = config.get('unstable', False)
@@ -240,8 +238,7 @@ class CodeFormatter:
240
238
 
241
239
  if TYPE_CHECKING:
242
240
 
243
- def apply_isort(self, code: str) -> str:
244
- ...
241
+ def apply_isort(self, code: str) -> str: ...
245
242
 
246
243
  else:
247
244
  if isort.__version__.startswith('4.'):
@@ -14,9 +14,14 @@ def get_body(
14
14
  url: str,
15
15
  headers: Optional[Sequence[Tuple[str, str]]] = None,
16
16
  ignore_tls: bool = False,
17
+ query_parameters: Optional[Sequence[Tuple[str, str]]] = None,
17
18
  ) -> str:
18
19
  return httpx.get(
19
- url, headers=headers, verify=not ignore_tls, follow_redirects=True
20
+ url,
21
+ headers=headers,
22
+ verify=not ignore_tls,
23
+ follow_redirects=True,
24
+ params=query_parameters,
20
25
  ).text
21
26
 
22
27
 
@@ -116,5 +116,9 @@ IMPORT_DICT = Import.from_full_path('typing.Dict')
116
116
  IMPORT_DECIMAL = Import.from_full_path('decimal.Decimal')
117
117
  IMPORT_DATE = Import.from_full_path('datetime.date')
118
118
  IMPORT_DATETIME = Import.from_full_path('datetime.datetime')
119
+ IMPORT_PATH = Import.from_full_path('pathlib.Path')
119
120
  IMPORT_TIME = Import.from_full_path('datetime.time')
120
121
  IMPORT_UUID = Import.from_full_path('uuid.UUID')
122
+ IMPORT_PENDULUM_DATE = Import.from_full_path('pendulum.Date')
123
+ IMPORT_PENDULUM_DATETIME = Import.from_full_path('pendulum.DateTime')
124
+ IMPORT_PENDULUM_TIME = Import.from_full_path('pendulum.Time')
@@ -267,8 +267,7 @@ class TemplateBase(ABC):
267
267
  return self.render()
268
268
 
269
269
 
270
- class BaseClassDataType(DataType):
271
- ...
270
+ class BaseClassDataType(DataType): ...
272
271
 
273
272
 
274
273
  UNDEFINED: Any = object()
@@ -126,6 +126,7 @@ class DataModelField(DataModelFieldBase):
126
126
  'min_length',
127
127
  'max_length',
128
128
  'pattern',
129
+ 'examples',
129
130
  # 'unique_items', # not supported by msgspec
130
131
  }
131
132
  _PARSE_METHOD = 'convert'
@@ -9,6 +9,10 @@ from datamodel_code_generator.imports import (
9
9
  IMPORT_DATE,
10
10
  IMPORT_DATETIME,
11
11
  IMPORT_DECIMAL,
12
+ IMPORT_PATH,
13
+ IMPORT_PENDULUM_DATE,
14
+ IMPORT_PENDULUM_DATETIME,
15
+ IMPORT_PENDULUM_TIME,
12
16
  IMPORT_TIME,
13
17
  IMPORT_UUID,
14
18
  )
@@ -52,11 +56,12 @@ def type_map_factory(
52
56
  data_type: Type[DataType],
53
57
  strict_types: Sequence[StrictTypes],
54
58
  pattern_key: str,
59
+ use_pendulum: bool,
55
60
  ) -> Dict[Types, DataType]:
56
61
  data_type_int = data_type(type='int')
57
62
  data_type_float = data_type(type='float')
58
63
  data_type_str = data_type(type='str')
59
- return {
64
+ result = {
60
65
  Types.integer: data_type_int,
61
66
  Types.int32: data_type_int,
62
67
  Types.int64: data_type_int,
@@ -70,6 +75,7 @@ def type_map_factory(
70
75
  Types.binary: data_type(type='bytes'),
71
76
  Types.date: data_type.from_import(IMPORT_DATE),
72
77
  Types.date_time: data_type.from_import(IMPORT_DATETIME),
78
+ Types.path: data_type.from_import(IMPORT_PATH),
73
79
  Types.password: data_type.from_import(IMPORT_SECRET_STR),
74
80
  Types.email: data_type.from_import(IMPORT_EMAIL_STR),
75
81
  Types.uuid: data_type.from_import(IMPORT_UUID),
@@ -98,6 +104,12 @@ def type_map_factory(
98
104
  Types.array: data_type.from_import(IMPORT_ANY, is_list=True),
99
105
  Types.any: data_type.from_import(IMPORT_ANY),
100
106
  }
107
+ if use_pendulum:
108
+ result[Types.date] = data_type.from_import(IMPORT_PENDULUM_DATE)
109
+ result[Types.date_time] = data_type.from_import(IMPORT_PENDULUM_DATETIME)
110
+ result[Types.time] = data_type.from_import(IMPORT_PENDULUM_TIME)
111
+
112
+ return result
101
113
 
102
114
 
103
115
  def strict_type_map_factory(data_type: Type[DataType]) -> Dict[StrictTypes, DataType]:
@@ -145,6 +157,7 @@ class DataTypeManager(_DataTypeManager):
145
157
  strict_types: Optional[Sequence[StrictTypes]] = None,
146
158
  use_non_positive_negative_number_constrained_types: bool = False,
147
159
  use_union_operator: bool = False,
160
+ use_pendulum: bool = False,
148
161
  ):
149
162
  super().__init__(
150
163
  python_version,
@@ -153,6 +166,7 @@ class DataTypeManager(_DataTypeManager):
153
166
  strict_types,
154
167
  use_non_positive_negative_number_constrained_types,
155
168
  use_union_operator,
169
+ use_pendulum,
156
170
  )
157
171
 
158
172
  self.type_map: Dict[Types, DataType] = self.type_map_factory(
@@ -183,7 +197,7 @@ class DataTypeManager(_DataTypeManager):
183
197
  strict_types: Sequence[StrictTypes],
184
198
  pattern_key: str,
185
199
  ) -> Dict[Types, DataType]:
186
- return type_map_factory(data_type, strict_types, pattern_key)
200
+ return type_map_factory(data_type, strict_types, pattern_key, self.use_pendulum)
187
201
 
188
202
  def transform_kwargs(
189
203
  self, kwargs: Dict[str, Any], filter_: Set[str]
@@ -10,7 +10,7 @@
10
10
  {{ decorator }}
11
11
  {% endfor -%}
12
12
 
13
- class {{ class_name }}({{ base_class }}[{{get_type_hint(fields)}}]):{% if comment is defined %} # {{ comment }}{% endif %}
13
+ class {{ class_name }}({{ base_class }}{%- if fields -%}[{{get_type_hint(fields)}}]{%- endif -%}):{% if comment is defined %} # {{ comment }}{% endif %}
14
14
  {%- if description %}
15
15
  """
16
16
  {{ description | indent(4) }}
@@ -58,6 +58,7 @@ class DataTypeManager(_DataTypeManager):
58
58
  strict_types: Optional[Sequence[StrictTypes]] = None,
59
59
  use_non_positive_negative_number_constrained_types: bool = False,
60
60
  use_union_operator: bool = False,
61
+ use_pendulum: bool = False,
61
62
  ):
62
63
  super().__init__(
63
64
  python_version,
@@ -66,6 +67,7 @@ class DataTypeManager(_DataTypeManager):
66
67
  strict_types,
67
68
  use_non_positive_negative_number_constrained_types,
68
69
  use_union_operator,
70
+ use_pendulum,
69
71
  )
70
72
 
71
73
  self.type_map: Dict[Types, DataType] = type_map_factory(
@@ -390,6 +390,8 @@ class Parser(ABC):
390
390
  known_third_party: Optional[List[str]] = None,
391
391
  custom_formatters: Optional[List[str]] = None,
392
392
  custom_formatters_kwargs: Optional[Dict[str, Any]] = None,
393
+ use_pendulum: bool = False,
394
+ http_query_parameters: Optional[Sequence[Tuple[str, str]]] = None,
393
395
  ) -> None:
394
396
  self.data_type_manager: DataTypeManager = data_type_manager_type(
395
397
  python_version=target_python_version,
@@ -397,6 +399,7 @@ class Parser(ABC):
397
399
  use_generic_container_types=use_generic_container_types,
398
400
  strict_types=strict_types,
399
401
  use_union_operator=use_union_operator,
402
+ use_pendulum=use_pendulum,
400
403
  )
401
404
  self.data_model_type: Type[DataModel] = data_model_type
402
405
  self.data_model_root_type: Type[DataModel] = data_model_root_type
@@ -408,19 +411,19 @@ class Parser(ABC):
408
411
  self.base_class: Optional[str] = base_class
409
412
  self.target_python_version: PythonVersion = target_python_version
410
413
  self.results: List[DataModel] = []
411
- self.dump_resolve_reference_action: Optional[
412
- Callable[[Iterable[str]], str]
413
- ] = dump_resolve_reference_action
414
+ self.dump_resolve_reference_action: Optional[Callable[[Iterable[str]], str]] = (
415
+ dump_resolve_reference_action
416
+ )
414
417
  self.validation: bool = validation
415
418
  self.field_constraints: bool = field_constraints
416
419
  self.snake_case_field: bool = snake_case_field
417
420
  self.strip_default_none: bool = strip_default_none
418
- self.apply_default_values_for_required_fields: (
419
- bool
420
- ) = apply_default_values_for_required_fields
421
- self.force_optional_for_required_fields: (
422
- bool
423
- ) = force_optional_for_required_fields
421
+ self.apply_default_values_for_required_fields: bool = (
422
+ apply_default_values_for_required_fields
423
+ )
424
+ self.force_optional_for_required_fields: bool = (
425
+ force_optional_for_required_fields
426
+ )
424
427
  self.use_schema_description: bool = use_schema_description
425
428
  self.use_field_description: bool = use_field_description
426
429
  self.use_default_kwarg: bool = use_default_kwarg
@@ -433,9 +436,9 @@ class Parser(ABC):
433
436
  self.use_generic_container_types: bool = use_generic_container_types
434
437
  self.use_union_operator: bool = use_union_operator
435
438
  self.enable_faux_immutability: bool = enable_faux_immutability
436
- self.custom_class_name_generator: Optional[
437
- Callable[[str], str]
438
- ] = custom_class_name_generator
439
+ self.custom_class_name_generator: Optional[Callable[[str], str]] = (
440
+ custom_class_name_generator
441
+ )
439
442
  self.field_extra_keys: Set[str] = field_extra_keys or set()
440
443
  self.field_extra_keys_without_x_prefix: Set[str] = (
441
444
  field_extra_keys_without_x_prefix or set()
@@ -490,6 +493,9 @@ class Parser(ABC):
490
493
  self.class_name: Optional[str] = class_name
491
494
  self.wrap_string_literal: Optional[bool] = wrap_string_literal
492
495
  self.http_headers: Optional[Sequence[Tuple[str, str]]] = http_headers
496
+ self.http_query_parameters: Optional[Sequence[Tuple[str, str]]] = (
497
+ http_query_parameters
498
+ )
493
499
  self.http_ignore_tls: bool = http_ignore_tls
494
500
  self.use_annotated: bool = use_annotated
495
501
  if self.use_annotated and not self.field_constraints: # pragma: no cover
@@ -547,7 +553,7 @@ class Parser(ABC):
547
553
  return self.remote_text_cache.get_or_put(
548
554
  url,
549
555
  default_factory=lambda url_: get_body(
550
- url, self.http_headers, self.http_ignore_tls
556
+ url, self.http_headers, self.http_ignore_tls, self.http_query_parameters
551
557
  ),
552
558
  )
553
559
 
@@ -568,9 +574,9 @@ class Parser(ABC):
568
574
 
569
575
  def __delete_duplicate_models(self, models: List[DataModel]) -> None:
570
576
  model_class_names: Dict[str, DataModel] = {}
571
- model_to_duplicate_models: DefaultDict[
572
- DataModel, List[DataModel]
573
- ] = defaultdict(list)
577
+ model_to_duplicate_models: DefaultDict[DataModel, List[DataModel]] = (
578
+ defaultdict(list)
579
+ )
574
580
  for model in models[:]:
575
581
  if isinstance(model, self.data_model_root_type):
576
582
  root_data_type = model.fields[0].data_type
@@ -671,7 +677,8 @@ class Parser(ABC):
671
677
  for model in models:
672
678
  scoped_model_resolver.add(model.path, model.class_name)
673
679
  for model in models:
674
- imports.append(model.imports)
680
+ before_import = model.imports
681
+ imports.append(before_import)
675
682
  for data_type in model.all_data_types:
676
683
  # To change from/import
677
684
 
@@ -681,7 +688,12 @@ class Parser(ABC):
681
688
  continue
682
689
 
683
690
  if isinstance(data_type, BaseClassDataType):
684
- from_ = ''.join(relative(model.module_name, data_type.full_name))
691
+ left, right = relative(model.module_name, data_type.full_name)
692
+ from_ = (
693
+ ''.join([left, right])
694
+ if left.endswith('.')
695
+ else '.'.join([left, right])
696
+ )
685
697
  import_ = data_type.reference.short_name
686
698
  full_path = from_, import_
687
699
  else:
@@ -709,6 +721,9 @@ class Parser(ABC):
709
721
  reference_path=data_type.reference.path,
710
722
  ),
711
723
  )
724
+ after_import = model.imports
725
+ if before_import != after_import:
726
+ imports.append(after_import)
712
727
 
713
728
  @classmethod
714
729
  def __extract_inherited_enum(cls, models: List[DataModel]) -> None:
@@ -756,7 +771,7 @@ class Parser(ABC):
756
771
  (pydantic_model.BaseModel, pydantic_model_v2.BaseModel),
757
772
  ):
758
773
  continue # pragma: no cover
759
- type_name = None
774
+ type_names = []
760
775
  if mapping:
761
776
  for name, path in mapping.items():
762
777
  if (
@@ -765,10 +780,10 @@ class Parser(ABC):
765
780
  ):
766
781
  # TODO: support external reference
767
782
  continue
768
- type_name = name
783
+ type_names.append(name)
769
784
  else:
770
- type_name = discriminator_model.path.split('/')[-1]
771
- if not type_name: # pragma: no cover
785
+ type_names = [discriminator_model.path.split('/')[-1]]
786
+ if not type_names: # pragma: no cover
772
787
  raise RuntimeError(
773
788
  f'Discriminator type is not found. {data_type.reference.path}'
774
789
  )
@@ -780,7 +795,11 @@ class Parser(ABC):
780
795
  ) != property_name:
781
796
  continue
782
797
  literals = discriminator_field.data_type.literals
783
- if len(literals) == 1 and literals[0] == type_name:
798
+ if (
799
+ len(literals) == 1 and literals[0] == type_names[0]
800
+ if type_names
801
+ else None
802
+ ):
784
803
  has_one_literal = True
785
804
  continue
786
805
  for (
@@ -789,7 +808,7 @@ class Parser(ABC):
789
808
  if field_data_type.reference: # pragma: no cover
790
809
  field_data_type.remove_reference()
791
810
  discriminator_field.data_type = self.data_type(
792
- literals=[type_name]
811
+ literals=type_names
793
812
  )
794
813
  discriminator_field.data_type.parent = discriminator_field
795
814
  discriminator_field.required = True
@@ -799,7 +818,7 @@ class Parser(ABC):
799
818
  discriminator_model.fields.append(
800
819
  self.data_model_field_type(
801
820
  name=property_name,
802
- data_type=self.data_type(literals=[type_name]),
821
+ data_type=self.data_type(literals=type_names),
803
822
  required=True,
804
823
  )
805
824
  )
@@ -1235,6 +1254,7 @@ class Parser(ABC):
1235
1254
 
1236
1255
  scoped_model_resolver = ModelResolver()
1237
1256
 
1257
+ self.__override_required_field(models)
1238
1258
  self.__replace_unique_list_to_set(models)
1239
1259
  self.__change_from_import(models, imports, scoped_model_resolver, init)
1240
1260
  self.__extract_inherited_enum(models)
@@ -1242,7 +1262,6 @@ class Parser(ABC):
1242
1262
  self.__reuse_model(models, require_update_action_models)
1243
1263
  self.__collapse_root_models(models, unused_models, imports)
1244
1264
  self.__set_default_enum_member(models)
1245
- self.__override_required_field(models)
1246
1265
  self.__sort_models(models, imports)
1247
1266
  self.__set_one_literal_on_default(models)
1248
1267
  self.__apply_discriminator_type(models, imports)
@@ -156,6 +156,8 @@ class GraphQLParser(Parser):
156
156
  known_third_party: Optional[List[str]] = None,
157
157
  custom_formatters: Optional[List[str]] = None,
158
158
  custom_formatters_kwargs: Optional[Dict[str, Any]] = None,
159
+ use_pendulum: bool = False,
160
+ http_query_parameters: Optional[Sequence[Tuple[str, str]]] = None,
159
161
  ) -> None:
160
162
  super().__init__(
161
163
  source=source,
@@ -221,6 +223,8 @@ class GraphQLParser(Parser):
221
223
  known_third_party=known_third_party,
222
224
  custom_formatters=custom_formatters,
223
225
  custom_formatters_kwargs=custom_formatters_kwargs,
226
+ use_pendulum=use_pendulum,
227
+ http_query_parameters=http_query_parameters,
224
228
  )
225
229
 
226
230
  self.data_model_scalar_type = data_model_scalar_type
@@ -118,6 +118,7 @@ json_schema_data_formats: Dict[str, Dict[str, Types]] = {
118
118
  'date-time': Types.date_time,
119
119
  'time': Types.time,
120
120
  'password': Types.password,
121
+ 'path': Types.path,
121
122
  'email': Types.email,
122
123
  'idn-email': Types.email,
123
124
  'uuid': Types.uuid,
@@ -437,6 +438,8 @@ class JsonSchemaParser(Parser):
437
438
  known_third_party: Optional[List[str]] = None,
438
439
  custom_formatters: Optional[List[str]] = None,
439
440
  custom_formatters_kwargs: Optional[Dict[str, Any]] = None,
441
+ use_pendulum: bool = False,
442
+ http_query_parameters: Optional[Sequence[Tuple[str, str]]] = None,
440
443
  ) -> None:
441
444
  super().__init__(
442
445
  source=source,
@@ -502,6 +505,8 @@ class JsonSchemaParser(Parser):
502
505
  known_third_party=known_third_party,
503
506
  custom_formatters=custom_formatters,
504
507
  custom_formatters_kwargs=custom_formatters_kwargs,
508
+ use_pendulum=use_pendulum,
509
+ http_query_parameters=http_query_parameters,
505
510
  )
506
511
 
507
512
  self.remote_object_cache: DefaultPutDict[str, Dict[str, Any]] = DefaultPutDict()
@@ -632,9 +637,9 @@ class JsonSchemaParser(Parser):
632
637
 
633
638
  def set_additional_properties(self, name: str, obj: JsonSchemaObject) -> None:
634
639
  if isinstance(obj.additionalProperties, bool):
635
- self.extra_template_data[name][
636
- 'additionalProperties'
637
- ] = obj.additionalProperties
640
+ self.extra_template_data[name]['additionalProperties'] = (
641
+ obj.additionalProperties
642
+ )
638
643
 
639
644
  def set_title(self, name: str, obj: JsonSchemaObject) -> None:
640
645
  if obj.title:
@@ -220,6 +220,8 @@ class OpenAPIParser(JsonSchemaParser):
220
220
  known_third_party: Optional[List[str]] = None,
221
221
  custom_formatters: Optional[List[str]] = None,
222
222
  custom_formatters_kwargs: Optional[Dict[str, Any]] = None,
223
+ use_pendulum: bool = False,
224
+ http_query_parameters: Optional[Sequence[Tuple[str, str]]] = None,
223
225
  ):
224
226
  super().__init__(
225
227
  source=source,
@@ -285,6 +287,8 @@ class OpenAPIParser(JsonSchemaParser):
285
287
  known_third_party=known_third_party,
286
288
  custom_formatters=custom_formatters,
287
289
  custom_formatters_kwargs=custom_formatters_kwargs,
290
+ use_pendulum=use_pendulum,
291
+ http_query_parameters=http_query_parameters,
288
292
  )
289
293
  self.open_api_scopes: List[OpenAPIScope] = openapi_scopes or [
290
294
  OpenAPIScope.Schemas
@@ -548,6 +548,7 @@ class Types(Enum):
548
548
  date = auto()
549
549
  date_time = auto()
550
550
  password = auto()
551
+ path = auto()
551
552
  email = auto()
552
553
  uuid = auto()
553
554
  uuid1 = auto()
@@ -577,6 +578,7 @@ class DataTypeManager(ABC):
577
578
  strict_types: Optional[Sequence[StrictTypes]] = None,
578
579
  use_non_positive_negative_number_constrained_types: bool = False,
579
580
  use_union_operator: bool = False,
581
+ use_pendulum: bool = False,
580
582
  ) -> None:
581
583
  self.python_version = python_version
582
584
  self.use_standard_collections: bool = use_standard_collections
@@ -586,6 +588,7 @@ class DataTypeManager(ABC):
586
588
  use_non_positive_negative_number_constrained_types
587
589
  )
588
590
  self.use_union_operator: bool = use_union_operator
591
+ self.use_pendulum: bool = use_pendulum
589
592
 
590
593
  if (
591
594
  use_generic_container_types and python_version == PythonVersion.PY_36
@@ -23,8 +23,7 @@ if TYPE_CHECKING:
23
23
 
24
24
  from typing_extensions import Literal
25
25
 
26
- def load_toml(path: Path) -> Dict[str, Any]:
27
- ...
26
+ def load_toml(path: Path) -> Dict[str, Any]: ...
28
27
 
29
28
  else:
30
29
  try:
@@ -0,0 +1 @@
1
+ version: str = '0.25.6'
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "datamodel-code-generator"
3
- version = "0.25.4"
3
+ version = "0.25.6"
4
4
  description = "Datamodel Code Generator"
5
5
  authors = ["Koudai Aono <koxudaxi@gmail.com>"]
6
6
  readme = "README.md"
@@ -78,7 +78,7 @@ types-setuptools = ">=67.6.0.5,<70.0.0.0"
78
78
  pydantic = "*"
79
79
  httpx = ">=0.24.1"
80
80
  PySnooper = "*"
81
- ruff = ">=0.0.290,<0.2.1"
81
+ ruff = ">=0.0.290,<0.4.2"
82
82
  ruff-lsp = ">=0.0.39,<0.0.41"
83
83
  pre-commit = "*"
84
84
  pytest-xdist = "^3.3.1"
@@ -1 +0,0 @@
1
- version: str = '0.25.4'