|
16 | 16 | IMPORT_DATETIME, |
17 | 17 | IMPORT_TIME, |
18 | 18 | IMPORT_TIMEDELTA, |
| 19 | + IMPORT_UNION, |
19 | 20 | Import, |
20 | 21 | ) |
21 | 22 | from datamodel_code_generator.model import DataModel, DataModelFieldBase |
|
36 | 37 | from datamodel_code_generator.model.types import standard_primitive_type_map_factory, type_map_factory |
37 | 38 | from datamodel_code_generator.types import ( |
38 | 39 | NONE, |
| 40 | + OPTIONAL_PREFIX, |
| 41 | + UNION_DELIMITER, |
39 | 42 | UNION_OPERATOR_DELIMITER, |
| 43 | + UNION_PREFIX, |
40 | 44 | DataType, |
41 | 45 | StrictTypes, |
42 | 46 | Types, |
@@ -92,6 +96,8 @@ def new_imports(self: DataModelFieldBaseT) -> tuple[Import, ...]: |
92 | 96 | extra_imports.append(IMPORT_MSGSPEC_META) |
93 | 97 | if not self.required and not self.nullable: |
94 | 98 | extra_imports.append(IMPORT_MSGSPEC_UNSETTYPE) |
| 99 | + if not self.data_type.use_union_operator: |
| 100 | + extra_imports.append(IMPORT_UNION) |
95 | 101 | if self.default is None or self.default is UNDEFINED: |
96 | 102 | extra_imports.append(IMPORT_MSGSPEC_UNSET) |
97 | 103 | return chain_as_tuple(original_imports.fget(self), extra_imports) # pyright: ignore[reportOptionalCall] |
@@ -212,18 +218,32 @@ class Constraints(_Constraints): |
212 | 218 |
|
213 | 219 |
|
214 | 220 | @lru_cache |
215 | | -def get_neither_required_nor_nullable_type(type_: str, use_union_operator: bool) -> str: # noqa: ARG001, FBT001 |
| 221 | +def get_neither_required_nor_nullable_type(type_: str, use_union_operator: bool) -> str: # noqa: FBT001 |
216 | 222 | """Get type hint for fields that are neither required nor nullable, using UnsetType.""" |
217 | | - type_ = _remove_none_from_union(type_, use_union_operator=True) |
| 223 | + type_ = _remove_none_from_union(type_, use_union_operator=use_union_operator) |
| 224 | + if type_.startswith(OPTIONAL_PREFIX): # pragma: no cover |
| 225 | + type_ = type_[len(OPTIONAL_PREFIX) : -1] |
| 226 | + |
218 | 227 | if not type_ or type_ == NONE: |
219 | 228 | return UNSET_TYPE |
220 | | - return UNION_OPERATOR_DELIMITER.join((type_, UNSET_TYPE)) |
| 229 | + if use_union_operator: |
| 230 | + return UNION_OPERATOR_DELIMITER.join((type_, UNSET_TYPE)) |
| 231 | + if type_.startswith(UNION_PREFIX): |
| 232 | + return f"{type_[:-1]}{UNION_DELIMITER}{UNSET_TYPE}]" |
| 233 | + return f"{UNION_PREFIX}{type_}{UNION_DELIMITER}{UNSET_TYPE}]" |
221 | 234 |
|
222 | 235 |
|
223 | 236 | @lru_cache |
224 | | -def _add_unset_type(type_: str, use_union_operator: bool) -> str: # noqa: ARG001, FBT001 |
| 237 | +def _add_unset_type(type_: str, use_union_operator: bool) -> str: # noqa: FBT001 |
225 | 238 | """Add UnsetType to a type hint without removing None.""" |
226 | | - return f"{type_}{UNION_OPERATOR_DELIMITER}{UNSET_TYPE}" |
| 239 | + if use_union_operator: |
| 240 | + return f"{type_}{UNION_OPERATOR_DELIMITER}{UNSET_TYPE}" |
| 241 | + if type_.startswith(UNION_PREFIX): |
| 242 | + return f"{type_[:-1]}{UNION_DELIMITER}{UNSET_TYPE}]" |
| 243 | + if type_.startswith(OPTIONAL_PREFIX): # pragma: no cover |
| 244 | + inner_type = type_[len(OPTIONAL_PREFIX) : -1] |
| 245 | + return f"{UNION_PREFIX}{inner_type}{UNION_DELIMITER}{NONE}{UNION_DELIMITER}{UNSET_TYPE}]" |
| 246 | + return f"{UNION_PREFIX}{type_}{UNION_DELIMITER}{UNSET_TYPE}]" |
227 | 247 |
|
228 | 248 |
|
229 | 249 | @import_extender |
@@ -385,9 +405,9 @@ def annotated(self) -> str | None: # noqa: PLR0911 |
385 | 405 | For ClassVar fields (discriminator tag_field), ClassVar is required |
386 | 406 | regardless of use_annotated setting. |
387 | 407 | """ |
388 | | - if self.extras.get("is_classvar"): |
| 408 | + if self.extras.get("is_classvar"): # pragma: no cover |
389 | 409 | meta = self._get_meta_string() |
390 | | - if self.use_annotated and meta: # pragma: no cover |
| 410 | + if self.use_annotated and meta: |
391 | 411 | return f"ClassVar[Annotated[{self.type_hint}, {meta}]]" |
392 | 412 | return f"ClassVar[{self.type_hint}]" |
393 | 413 |
|
@@ -418,7 +438,7 @@ def needs_annotated_import(self) -> bool: |
418 | 438 | """ |
419 | 439 | if not self.annotated: |
420 | 440 | return False |
421 | | - if self.extras.get("is_classvar"): # pragma: no cover |
| 441 | + if self.extras.get("is_classvar"): |
422 | 442 | return self.use_annotated and self._get_meta_string() is not None |
423 | 443 | return True |
424 | 444 |
|
|
0 commit comments