From b10f4a75161461dd015ed8ef39b7044b2ab40389 Mon Sep 17 00:00:00 2001 From: Eric Butler Date: Mon, 12 Feb 2024 15:13:29 -0500 Subject: [PATCH 1/3] fix: bad code generated for nested unions fixes #958 --- end_to_end_tests/baseline_openapi_3.0.json | 49 ++++++++- end_to_end_tests/baseline_openapi_3.1.yaml | 49 +++++++++ .../my_test_api_client/models/__init__.py | 6 + .../models/a_discriminated_union_type_1.py | 58 ++++++++++ .../models/a_discriminated_union_type_2.py | 58 ++++++++++ .../models/model_with_discriminated_union.py | 103 ++++++++++++++++++ .../parser/properties/union.py | 11 ++ 7 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py diff --git a/end_to_end_tests/baseline_openapi_3.0.json b/end_to_end_tests/baseline_openapi_3.0.json index 6753bb2a4..af8badc10 100644 --- a/end_to_end_tests/baseline_openapi_3.0.json +++ b/end_to_end_tests/baseline_openapi_3.0.json @@ -801,7 +801,7 @@ } } } - }, + }, "/enum/int": { "post": { "tags": [ @@ -2531,6 +2531,53 @@ "ModelWithBackslashInDescription": { "type": "object", "description": "Description with special character: \\" + }, + "ModelWithDiscriminatedUnion": { + "type": "object", + "properties": { + "discriminated_union": { + "allOf": [ + { + "$ref": "#/components/schemas/ADiscriminatedUnion" + } + ], + "nullable": true + } + } + }, + "ADiscriminatedUnion": { + "type": "object", + "discriminator": { + "propertyName": "modelType", + "mapping": { + "type1": "#/components/schemas/ADiscriminatedUnionType1", + "type2": "#/components/schemas/ADiscriminatedUnionType2" + } + }, + "oneOf": [ + { + "$ref": "#/components/schemas/ADiscriminatedUnionType1" + }, + { + "$ref": "#/components/schemas/ADiscriminatedUnionType2" + } + ] + }, + "ADiscriminatedUnionType1": { + "type": "object", + "properties": { + "modelType": { + "type": "string" + } + } + }, + "ADiscriminatedUnionType2": { + "type": "object", + "properties": { + "modelType": { + "type": "string" + } + } } }, "parameters": { diff --git a/end_to_end_tests/baseline_openapi_3.1.yaml b/end_to_end_tests/baseline_openapi_3.1.yaml index b630ce674..f29cdfd21 100644 --- a/end_to_end_tests/baseline_openapi_3.1.yaml +++ b/end_to_end_tests/baseline_openapi_3.1.yaml @@ -2543,6 +2543,55 @@ info: "ModelWithBackslashInDescription": { "type": "object", "description": "Description with special character: \\" + }, + "ModelWithDiscriminatedUnion": { + "type": "object", + "properties": { + "discriminated_union": { + "oneOf": [ + { + "$ref": "#/components/schemas/ADiscriminatedUnion" + }, + { + "type": "null" + } + ], + } + } + }, + "ADiscriminatedUnion": { + "type": "object", + "discriminator": { + "propertyName": "modelType", + "mapping": { + "type1": "#/components/schemas/ADiscriminatedUnionType1", + "type2": "#/components/schemas/ADiscriminatedUnionType2" + } + }, + "oneOf": [ + { + "$ref": "#/components/schemas/ADiscriminatedUnionType1" + }, + { + "$ref": "#/components/schemas/ADiscriminatedUnionType2" + } + ] + }, + "ADiscriminatedUnionType1": { + "type": "object", + "properties": { + "modelType": { + "type": "string" + } + } + }, + "ADiscriminatedUnionType2": { + "type": "object", + "properties": { + "modelType": { + "type": "string" + } + } } }, "parameters": { diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py index 5166f321b..39c021a37 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py @@ -1,5 +1,7 @@ """ Contains all the data models used in inputs/outputs """ +from .a_discriminated_union_type_1 import ADiscriminatedUnionType1 +from .a_discriminated_union_type_2 import ADiscriminatedUnionType2 from .a_form_data import AFormData from .a_model import AModel from .a_model_with_properties_reference_that_are_not_object import AModelWithPropertiesReferenceThatAreNotObject @@ -54,6 +56,7 @@ from .model_with_circular_ref_in_additional_properties_a import ModelWithCircularRefInAdditionalPropertiesA from .model_with_circular_ref_in_additional_properties_b import ModelWithCircularRefInAdditionalPropertiesB from .model_with_date_time_property import ModelWithDateTimeProperty +from .model_with_discriminated_union import ModelWithDiscriminatedUnion from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder from .model_with_property_ref import ModelWithPropertyRef @@ -79,6 +82,8 @@ from .validation_error import ValidationError __all__ = ( + "ADiscriminatedUnionType1", + "ADiscriminatedUnionType2", "AFormData", "AllOfHasPropertiesButNoType", "AllOfHasPropertiesButNoTypeTypeEnum", @@ -125,6 +130,7 @@ "ModelWithCircularRefInAdditionalPropertiesA", "ModelWithCircularRefInAdditionalPropertiesB", "ModelWithDateTimeProperty", + "ModelWithDiscriminatedUnion", "ModelWithPrimitiveAdditionalProperties", "ModelWithPrimitiveAdditionalPropertiesADateHolder", "ModelWithPropertyRef", diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py new file mode 100644 index 000000000..cb1184b18 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py @@ -0,0 +1,58 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ADiscriminatedUnionType1") + + +@_attrs_define +class ADiscriminatedUnionType1: + """ + Attributes: + model_type (Union[Unset, str]): + """ + + model_type: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + model_type = self.model_type + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if model_type is not UNSET: + field_dict["modelType"] = model_type + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + model_type = d.pop("modelType", UNSET) + + a_discriminated_union_type_1 = cls( + model_type=model_type, + ) + + a_discriminated_union_type_1.additional_properties = d + return a_discriminated_union_type_1 + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py new file mode 100644 index 000000000..734f3bef4 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py @@ -0,0 +1,58 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ADiscriminatedUnionType2") + + +@_attrs_define +class ADiscriminatedUnionType2: + """ + Attributes: + model_type (Union[Unset, str]): + """ + + model_type: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + model_type = self.model_type + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if model_type is not UNSET: + field_dict["modelType"] = model_type + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + model_type = d.pop("modelType", UNSET) + + a_discriminated_union_type_2 = cls( + model_type=model_type, + ) + + a_discriminated_union_type_2.additional_properties = d + return a_discriminated_union_type_2 + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py new file mode 100644 index 000000000..e03a6e698 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py @@ -0,0 +1,103 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.a_discriminated_union_type_1 import ADiscriminatedUnionType1 + from ..models.a_discriminated_union_type_2 import ADiscriminatedUnionType2 + + +T = TypeVar("T", bound="ModelWithDiscriminatedUnion") + + +@_attrs_define +class ModelWithDiscriminatedUnion: + """ + Attributes: + discriminated_union (Union['ADiscriminatedUnionType1', 'ADiscriminatedUnionType2', None, Unset]): + """ + + discriminated_union: Union["ADiscriminatedUnionType1", "ADiscriminatedUnionType2", None, Unset] = UNSET + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + from ..models.a_discriminated_union_type_1 import ADiscriminatedUnionType1 + from ..models.a_discriminated_union_type_2 import ADiscriminatedUnionType2 + + discriminated_union: Union[Dict[str, Any], None, Unset] + if isinstance(self.discriminated_union, Unset): + discriminated_union = UNSET + elif isinstance(self.discriminated_union, ADiscriminatedUnionType1): + discriminated_union = self.discriminated_union.to_dict() + elif isinstance(self.discriminated_union, ADiscriminatedUnionType2): + discriminated_union = self.discriminated_union.to_dict() + else: + discriminated_union = self.discriminated_union + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if discriminated_union is not UNSET: + field_dict["discriminated_union"] = discriminated_union + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + from ..models.a_discriminated_union_type_1 import ADiscriminatedUnionType1 + from ..models.a_discriminated_union_type_2 import ADiscriminatedUnionType2 + + d = src_dict.copy() + + def _parse_discriminated_union( + data: object, + ) -> Union["ADiscriminatedUnionType1", "ADiscriminatedUnionType2", None, Unset]: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_a_discriminated_union_type_0 = ADiscriminatedUnionType1.from_dict(data) + + return componentsschemas_a_discriminated_union_type_0 + except: # noqa: E722 + pass + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_a_discriminated_union_type_1 = ADiscriminatedUnionType2.from_dict(data) + + return componentsschemas_a_discriminated_union_type_1 + except: # noqa: E722 + pass + return cast(Union["ADiscriminatedUnionType1", "ADiscriminatedUnionType2", None, Unset], data) + + discriminated_union = _parse_discriminated_union(d.pop("discriminated_union", UNSET)) + + model_with_discriminated_union = cls( + discriminated_union=discriminated_union, + ) + + model_with_discriminated_union.additional_properties = d + return model_with_discriminated_union + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/openapi_python_client/parser/properties/union.py b/openapi_python_client/parser/properties/union.py index ec7d18c7e..8b7b02a48 100644 --- a/openapi_python_client/parser/properties/union.py +++ b/openapi_python_client/parser/properties/union.py @@ -67,6 +67,17 @@ def build( return PropertyError(detail=f"Invalid property in union {name}", data=sub_prop_data), schemas sub_properties.append(sub_prop) + def flatten_union_properties(sub_properties: list[PropertyProtocol]) -> list[PropertyProtocol]: + flattened = [] + for sub_prop in sub_properties: + if isinstance(sub_prop, UnionProperty): + flattened.extend(flatten_union_properties(sub_prop.inner_properties)) + else: + flattened.append(sub_prop) + return flattened + + sub_properties = flatten_union_properties(sub_properties) + prop = UnionProperty( name=name, required=required, From 9acb7449a78a9e03367d65738d937a10e22ff9b7 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 19 Feb 2024 17:56:07 -0700 Subject: [PATCH 2/3] fix: Remove spurious `field_dict.update({})` for types without properties --- ...circular_ref_in_items_object_additional_properties_a_item.py | 2 -- ...circular_ref_in_items_object_additional_properties_b_item.py | 2 -- ..._recursive_ref_in_items_object_additional_properties_item.py | 2 -- .../golden-record/my_test_api_client/models/free_form_model.py | 1 - .../golden-record/my_test_api_client/models/import_.py | 1 - .../golden-record/my_test_api_client/models/model_name.py | 1 - .../my_test_api_client/models/model_reference_with_periods.py | 1 - .../models/model_with_additional_properties_refed.py | 1 - .../my_test_api_client/models/model_with_any_json_properties.py | 1 - ...model_with_any_json_properties_additional_property_type_0.py | 1 - .../models/model_with_backslash_in_description.py | 1 - .../model_with_circular_ref_in_additional_properties_a.py | 1 - .../model_with_circular_ref_in_additional_properties_b.py | 1 - .../model_with_primitive_additional_properties_a_date_holder.py | 1 - .../models/model_with_recursive_ref_in_additional_properties.py | 1 - .../golden-record/my_test_api_client/models/none.py | 1 - ...sponses_unions_simple_before_complex_response_200a_type_1.py | 1 - openapi_python_client/templates/model.py.jinja | 2 ++ 18 files changed, 2 insertions(+), 20 deletions(-) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py index c90579e7e..eec98255f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_a_item.py @@ -32,8 +32,6 @@ def to_dict(self) -> Dict[str, Any]: componentsschemas_an_array_with_a_circular_ref_in_items_object_additional_properties_b_item ) - field_dict.update({}) - return field_dict @classmethod diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py index 732e8ea4c..479b177ea 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_additional_properties_b_item.py @@ -32,8 +32,6 @@ def to_dict(self) -> Dict[str, Any]: componentsschemas_an_array_with_a_circular_ref_in_items_object_additional_properties_a_item ) - field_dict.update({}) - return field_dict @classmethod diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py index bd0472e21..301a66e0e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_additional_properties_item.py @@ -24,8 +24,6 @@ def to_dict(self) -> Dict[str, Any]: componentsschemas_an_array_with_a_recursive_ref_in_items_object_additional_properties_item ) - field_dict.update({}) - return field_dict @classmethod diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py index 327a5d3d7..f757b10ae 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py @@ -15,7 +15,6 @@ class FreeFormModel: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/import_.py b/end_to_end_tests/golden-record/my_test_api_client/models/import_.py index f5a7deecf..85cc594e7 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/import_.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/import_.py @@ -15,7 +15,6 @@ class Import: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py index fa840976e..2a86db3a2 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_name.py @@ -15,7 +15,6 @@ class ModelName: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py index 492b4f8f7..a5ff5d211 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_reference_with_periods.py @@ -15,7 +15,6 @@ class ModelReferenceWithPeriods: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py index 4605b8801..b2500f68c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py @@ -18,7 +18,6 @@ def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = prop.value - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py index 49a66f7a5..6e669914a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py @@ -34,7 +34,6 @@ def to_dict(self) -> Dict[str, Any]: else: field_dict[prop_name] = prop - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py index d167d50d7..6ae70905e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py @@ -15,7 +15,6 @@ class ModelWithAnyJsonPropertiesAdditionalPropertyType0: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py index 5485cf978..5de43ddb9 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_backslash_in_description.py @@ -17,7 +17,6 @@ class ModelWithBackslashInDescription: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py index 9e3f6c12c..4f1d59c57 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_a.py @@ -22,7 +22,6 @@ def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = prop.to_dict() - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py index 5b4f0c268..3f55584e5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_in_additional_properties_b.py @@ -22,7 +22,6 @@ def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = prop.to_dict() - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py index 4693be0a1..b9920fc60 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py @@ -18,7 +18,6 @@ def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = prop.isoformat() - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py index ea5b1211f..2ed2526f5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref_in_additional_properties.py @@ -18,7 +18,6 @@ def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = prop.to_dict() - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/none.py b/end_to_end_tests/golden-record/my_test_api_client/models/none.py index 724990e3e..3510497bf 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/none.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/none.py @@ -15,7 +15,6 @@ class None_: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py index 018926222..601d17cf8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py @@ -15,7 +15,6 @@ class PostResponsesUnionsSimpleBeforeComplexResponse200AType1: def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) return field_dict diff --git a/openapi_python_client/templates/model.py.jinja b/openapi_python_client/templates/model.py.jinja index f8864b343..0df641ea4 100644 --- a/openapi_python_client/templates/model.py.jinja +++ b/openapi_python_client/templates/model.py.jinja @@ -109,6 +109,7 @@ field_dict.update({ field_dict.update(self.additional_properties) {% endif %} {% endif %} +{% if model.required_properties | length > 0 or model.optional_properties | length > 0 %} field_dict.update({ {% for property in model.required_properties + model.optional_properties %} {% if property.required %} @@ -116,6 +117,7 @@ field_dict.update({ {% endif %} {% endfor %} }) +{% endif %} {% for property in model.optional_properties %} {% if not property.required %} if {{ property.python_name }} is not UNSET: From d2bbc09c58f2144e9f513adce81ef73415e92efb Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 19 Feb 2024 18:02:18 -0700 Subject: [PATCH 3/3] chore: changeset --- .changeset/fix_invalid_type_check_for_nested_unions.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/fix_invalid_type_check_for_nested_unions.md diff --git a/.changeset/fix_invalid_type_check_for_nested_unions.md b/.changeset/fix_invalid_type_check_for_nested_unions.md new file mode 100644 index 000000000..6d3c512a2 --- /dev/null +++ b/.changeset/fix_invalid_type_check_for_nested_unions.md @@ -0,0 +1,9 @@ +--- +default: patch +--- + +# Fix invalid type check for nested unions + +Nested union types (unions of unions) were generating `isinstance()` checks that were not valid (at least for Python 3.9). + +Thanks to @codebutler for PR #959 which fixes #958 and #967.