From 4e30205a11d3a7112480b2c4cb943aff8e290ee9 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 9 Feb 2021 17:24:22 -0500 Subject: [PATCH 01/17] Fix tests --- .../test_parser/test_properties/test_init.py | 142 +++++++++--------- .../test_date_property/optional_nullable.py | 2 +- 2 files changed, 70 insertions(+), 74 deletions(-) diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index a7ea05881..2a70322d6 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -16,45 +16,54 @@ class TestProperty: - def test_get_type_string(self, mocker): + @pytest.mark.parametrize( + "query_parameter,nullable,required,no_optional,expected", + [ + (False, False, False, False, "Union[Unset, TestType]"), + (False, False, False, True, "TestType"), + (False, False, True, False, "TestType"), + (False, False, True, True, "TestType"), + (False, True, False, False, "Union[Unset, None, TestType]"), + (False, True, False, True, "TestType"), + (False, True, True, False, "Optional[TestType]"), + (False, True, True, True, "TestType"), + (True, False, False, False, "Union[Unset, None, TestType]"), + (True, False, False, True, "TestType"), + (True, False, True, False, "TestType"), + (True, False, True, True, "TestType"), + (True, True, False, False, "Union[Unset, None, TestType]"), + (True, True, False, True, "TestType"), + (True, True, True, False, "Optional[TestType]"), + (True, True, True, True, "TestType"), + ], + ) + def test_get_type_string(self, mocker, query_parameter, nullable, required, no_optional, expected): from openapi_python_client.parser.properties import Property mocker.patch.object(Property, "_type_string", "TestType") - p = Property(name="test", required=True, default=None, nullable=False) - - base_type_string = f"TestType" - - assert p.get_type_string() == base_type_string - - p = Property(name="test", required=True, default=None, nullable=True) - assert p.get_type_string() == f"Optional[{base_type_string}]" - assert p.get_type_string(no_optional=True) == base_type_string - - p = Property(name="test", required=False, default=None, nullable=True) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" - assert p.get_type_string(no_optional=True) == base_type_string - - p = Property(name="test", required=False, default=None, nullable=False) - assert p.get_type_string() == f"Union[Unset, {base_type_string}]" - assert p.get_type_string(no_optional=True) == base_type_string + p = Property(name="test", required=required, default=None, nullable=nullable) + assert p.get_type_string(no_optional=no_optional, query_parameter=query_parameter) == expected - def test_to_string(self, mocker): + @pytest.mark.parametrize( + "query_parameter,default,required,expected", + [ + (False, None, False, "test: Union[Unset, TestType] = UNSET"), + (False, None, True, "test: TestType"), + (False, "Test", False, "test: Union[Unset, TestType] = Test"), + (False, "Test", True, "test: TestType = Test"), + (True, None, False, "test: Union[Unset, None, TestType] = UNSET"), + (True, None, True, "test: TestType"), + (True, "Test", False, "test: Union[Unset, None, TestType] = Test"), + (True, "Test", True, "test: TestType = Test"), + ], + ) + def test_to_string(self, mocker, query_parameter, default, required, expected): from openapi_python_client.parser.properties import Property name = "test" - get_type_string = mocker.patch.object(Property, "get_type_string") - p = Property(name=name, required=True, default=None, nullable=False) - - assert p.to_string() == f"{name}: {get_type_string()}" - - p = Property(name=name, required=False, default=None, nullable=False) - assert p.to_string() == f"{name}: {get_type_string()} = UNSET" - - p = Property(name=name, required=True, default=None, nullable=False) - assert p.to_string() == f"{name}: {get_type_string()}" - - p = Property(name=name, required=True, default="TEST", nullable=False) - assert p.to_string() == f"{name}: {get_type_string()} = TEST" + mocker.patch.object(Property, "_type_string", "TestType") + p = Property(name=name, required=required, default=default, nullable=False) + assert p.to_string(query_parameter=query_parameter) == expected def test_get_imports(self): from openapi_python_client.parser.properties import Property @@ -87,7 +96,7 @@ def test_get_type_string(self): assert p.get_type_string() == f"Optional[{base_type_string}]" p = StringProperty(name="test", required=False, default=None, nullable=True) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" + assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" p = StringProperty(name="test", required=False, default=None, nullable=False) assert p.get_type_string() == f"Union[Unset, {base_type_string}]" @@ -202,7 +211,7 @@ def test_get_type_string(self, mocker): assert p.get_type_string(no_optional=True) == base_type_string p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=True) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" + assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=False) @@ -242,7 +251,28 @@ def test_get_type_imports(self, mocker): class TestUnionProperty: - def test_get_type_string(self, mocker): + @pytest.mark.parametrize( + "query_parameter,nullable,required,no_optional,expected", + [ + (False, False, False, False, "Union[Unset, inner_type_string_1, inner_type_string_2]"), + (False, False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (False, False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (False, True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), + (False, True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (True, False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (True, True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), + (True, True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + ], + ) + def test_get_type_string(self, mocker, query_parameter, nullable, required, no_optional, expected): from openapi_python_client.parser.properties import UnionProperty inner_property_1 = mocker.MagicMock() @@ -251,46 +281,12 @@ def test_get_type_string(self, mocker): inner_property_2.get_type_string.return_value = "inner_type_string_2" p = UnionProperty( name="test", - required=True, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=False, - ) - - base_type_string = f"Union[inner_type_string_1, inner_type_string_2]" - - assert p.get_type_string() == base_type_string - - p = UnionProperty( - name="test", - required=True, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=True, - ) - assert p.get_type_string() == f"Optional[{base_type_string}]" - assert p.get_type_string(no_optional=True) == base_type_string - - base_type_string_with_unset = f"Union[Unset, inner_type_string_1, inner_type_string_2]" - p = UnionProperty( - name="test", - required=False, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=True, - ) - assert p.get_type_string() == f"Optional[{base_type_string_with_unset}]" - assert p.get_type_string(no_optional=True) == base_type_string - - p = UnionProperty( - name="test", - required=False, + required=required, default=None, inner_properties=[inner_property_1, inner_property_2], - nullable=False, + nullable=nullable, ) - assert p.get_type_string() == base_type_string_with_unset - assert p.get_type_string(no_optional=True) == base_type_string + assert p.get_type_string(query_parameter=query_parameter, no_optional=no_optional) == expected def test_get_imports(self, mocker): from openapi_python_client.parser.properties import UnionProperty @@ -389,7 +385,7 @@ def test_get_type_string(self, mocker): reference=fake_reference, value_type=str, ) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" + assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string p = properties.EnumProperty( diff --git a/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py b/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py index cf8780024..be32cfbd3 100644 --- a/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py +++ b/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py @@ -6,7 +6,7 @@ some_source = date(2020, 10, 12) -some_destination: Union[Unset, str] = UNSET +some_destination: Union[Unset, None, str] = UNSET if not isinstance(some_source, Unset): some_destination = some_source.isoformat() if some_source else None From fda721a2b51e0bdeeb113482dea7804e02472f42 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 9 Feb 2021 17:47:54 -0500 Subject: [PATCH 02/17] Manually apply diff --- end_to_end_tests/openapi.json | 68 +++++++++++++++++- .../parser/properties/__init__.py | 69 +++++++++++++------ .../parser/properties/enum_property.py | 14 ++-- .../parser/properties/model_property.py | 13 +--- .../parser/properties/property.py | 31 ++++++--- .../property_templates/date_property.py.jinja | 4 +- .../datetime_property.py.jinja | 4 +- .../property_templates/enum_property.py.jinja | 8 ++- .../property_templates/file_property.py.jinja | 4 +- .../property_templates/list_property.py.jinja | 5 +- .../model_property.py.jinja | 6 +- .../property_templates/none_property.py.jinja | 2 + .../union_property.py.jinja | 27 ++++++-- .../templates/types.py.jinja | 5 +- 14 files changed, 191 insertions(+), 69 deletions(-) diff --git a/end_to_end_tests/openapi.json b/end_to_end_tests/openapi.json index 196538f19..8b5c883da 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -396,6 +396,14 @@ }, "name": "enum_prop", "in": "query" + }, + { + "required": false, + "schema": { + "$ref": "#/components/schemas/ModelWithUnionProperty" + }, + "name": "model_prop", + "in": "query" } ], "responses": { @@ -622,7 +630,18 @@ "schemas": { "AModel": { "title": "AModel", - "required": ["an_enum_value", "aCamelDateTime", "a_date", "a_nullable_date", "required_nullable", "required_not_nullable", "model", "nullable_model"], + "required": [ + "an_enum_value", + "aCamelDateTime", + "a_date", + "a_nullable_date", + "required_nullable", + "required_not_nullable", + "model", + "nullable_model", + "one_of_models", + "nullable_one_of_models" + ], "type": "object", "properties": { "an_enum_value": { @@ -687,6 +706,53 @@ "type": "string", "nullable": false }, + "one_of_models": { + "oneOf": [ + { + "ref": "#components/schemas/FreeFormModel" + }, + { + "ref": "#components/schemas/ModelWithUnionProperty" + } + ], + "nullable": false + }, + "nullable_one_of_models": { + "oneOf": [ + { + "ref": "#components/schemas/FreeFormModel" + }, + { + "ref": "#components/schemas/ModelWithUnionProperty" + } + ], + "nullable": true + }, + "not_required_one_of_models": { + "oneOf": [ + { + "ref": "#components/schemas/FreeFormModel" + }, + { + "ref": "#components/schemas/ModelWithUnionProperty" + } + ], + "nullable": false + }, + "not_required_nullable_one_of_models": { + "oneOf": [ + { + "ref": "#components/schemas/FreeFormModel" + }, + { + "ref": "#components/schemas/ModelWithUnionProperty" + }, + { + "type": "string" + } + ], + "nullable": true + }, "model": { "type": "object", "allOf": [ diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 2ea75a569..f173b3107 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -19,6 +19,7 @@ class NoneProperty(Property): """ A property that is always None (used for empty schemas) """ _type_string: ClassVar[str] = "None" + _json_type_string: ClassVar[str] = "None" template: ClassVar[Optional[str]] = "none_property.py.jinja" @@ -29,6 +30,7 @@ class StringProperty(Property): max_length: Optional[int] = None pattern: Optional[str] = None _type_string: ClassVar[str] = "str" + _json_type_string: ClassVar[str] = "str" @attr.s(auto_attribs=True, frozen=True) @@ -38,6 +40,7 @@ class DateTimeProperty(Property): """ _type_string: ClassVar[str] = "datetime.datetime" + _json_type_string: ClassVar[str] = "str" template: ClassVar[str] = "datetime_property.py.jinja" def get_imports(self, *, prefix: str) -> Set[str]: @@ -58,6 +61,7 @@ class DateProperty(Property): """ A property of type datetime.date """ _type_string: ClassVar[str] = "datetime.date" + _json_type_string: ClassVar[str] = "str" template: ClassVar[str] = "date_property.py.jinja" def get_imports(self, *, prefix: str) -> Set[str]: @@ -78,6 +82,8 @@ class FileProperty(Property): """ A property used for uploading files """ _type_string: ClassVar[str] = "File" + # Return type of File.to_tuple() + _json_type_string: ClassVar[str] = "Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]" template: ClassVar[str] = "file_property.py.jinja" def get_imports(self, *, prefix: str) -> Set[str]: @@ -98,6 +104,7 @@ class FloatProperty(Property): """ A property of type float """ _type_string: ClassVar[str] = "float" + _json_type_string: ClassVar[str] = "float" @attr.s(auto_attribs=True, frozen=True) @@ -105,6 +112,7 @@ class IntProperty(Property): """ A property of type int """ _type_string: ClassVar[str] = "int" + _json_type_string: ClassVar[str] = "int" @attr.s(auto_attribs=True, frozen=True) @@ -112,6 +120,7 @@ class BooleanProperty(Property): """ Property for bool """ _type_string: ClassVar[str] = "bool" + _json_type_string: ClassVar[str] = "bool" InnerProp = TypeVar("InnerProp", bound=Property) @@ -122,18 +131,11 @@ class ListProperty(Property, Generic[InnerProp]): """ A property representing a list (array) of other properties """ inner_property: InnerProp + _json_type_string: ClassVar[str] = "List[Any]" template: ClassVar[str] = "list_property.py.jinja" - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ - type_string = f"List[{self.inner_property.get_type_string()}]" - if no_optional: - return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - type_string = f"Union[Unset, {type_string}]" - return type_string + def get_base_type_string(self) -> str: + return f"List[{self.inner_property.get_type_string()}]" def get_instance_type_string(self) -> str: """Get a string representation of runtime type that should be used for `isinstance` checks""" @@ -167,18 +169,41 @@ def __attrs_post_init__(self) -> None: self, "has_properties_without_templates", any(prop.template is None for prop in self.inner_properties) ) - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ - inner_types = [p.get_type_string(no_optional=True) for p in self.inner_properties] - inner_prop_string = ", ".join(inner_types) - type_string = f"Union[{inner_prop_string}]" - if no_optional: - return type_string - if not self.required: - type_string = f"Union[Unset, {inner_prop_string}]" - if self.nullable: - type_string = f"Optional[{type_string}]" - return type_string + def _get_inner_type_strings(self, json: bool = False) -> List[str]: + inner_types = [p.get_type_string(no_optional=True, json=json) for p in self.inner_properties] + unique_inner_types = list(dict.fromkeys(inner_types)) + return unique_inner_types + + def get_base_type_string(self) -> str: + return f"Union[{', '.join(self._get_inner_type_strings(json=False))}]" + + def get_base_json_type_string(self) -> str: + return f"Union[{', '.join(self._get_inner_type_strings(json=True))}]" + + def get_type_strings_in_union( + self, no_optional: bool = False, json: bool = False + ) -> List[str]: + type_strings = self._get_inner_type_strings(json=json) + + if no_optional or (self.required and not self.nullable): + return type_strings + elif self.required and self.nullable: + return ["None"] + type_strings + elif not self.required and self.nullable: + return ["Unset", "None"] + type_strings + else: + return ["Unset"] + type_strings + + def get_type_string(self, no_optional: bool = False, json: bool = False) -> str: + """ + Get a string representation of type that should be used when declaring this property. + This implementation differs slightly from `Property.get_type_string` in order to collapse + nested union types. + """ + type_strings_in_union = self.get_type_strings_in_union( + no_optional=no_optional, json=json + ) + return f"Union[{', '.join(type_strings_in_union)}]" def get_imports(self, *, prefix: str) -> Set[str]: """ diff --git a/openapi_python_client/parser/properties/enum_property.py b/openapi_python_client/parser/properties/enum_property.py index 7549ba1a8..0e095e455 100644 --- a/openapi_python_client/parser/properties/enum_property.py +++ b/openapi_python_client/parser/properties/enum_property.py @@ -22,17 +22,11 @@ class EnumProperty(Property): template: ClassVar[str] = "enum_property.py.jinja" - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ + def get_base_type_string(self, json: bool = False) -> str: + return self.reference.class_name - type_string = self.reference.class_name - if no_optional: - return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - type_string = f"Union[Unset, {type_string}]" - return type_string + def get_base_json_type_string(self, json: bool = False) -> str: + return self.value_type.__name__ def get_imports(self, *, prefix: str) -> Set[str]: """ diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py index d5b15e866..c0ebf194e 100644 --- a/openapi_python_client/parser/properties/model_property.py +++ b/openapi_python_client/parser/properties/model_property.py @@ -17,19 +17,12 @@ class ModelProperty(Property): description: str relative_imports: Set[str] additional_properties: Union[bool, Property] + _json_type_string: ClassVar[str] = "Dict[str, Any]" template: ClassVar[str] = "model_property.py.jinja" - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ - type_string = self.reference.class_name - if no_optional: - return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - type_string = f"Union[{type_string}, Unset]" - return type_string + def get_base_type_string(self, json: bool = False) -> str: + return self.reference.class_name def get_imports(self, *, prefix: str) -> Set[str]: """ diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index 0b7047551..9e653beac 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -24,6 +24,7 @@ class Property: required: bool nullable: bool _type_string: ClassVar[str] = "" + _json_type_string: ClassVar[str] = "" # Type of the property after JSON serialization default: Optional[str] = attr.ib() python_name: str = attr.ib(init=False) @@ -32,21 +33,33 @@ class Property: def __attrs_post_init__(self) -> None: object.__setattr__(self, "python_name", utils.to_valid_python_identifier(utils.snake_case(self.name))) - def get_type_string(self, no_optional: bool = False) -> str: + def get_base_type_string(self) -> str: + return self._type_string + + def get_base_json_type_string(self) -> str: + return self._json_type_string + + def get_type_string(self, no_optional: bool = False, json: bool = False) -> str: """ Get a string representation of type that should be used when declaring this property Args: no_optional: Do not include Optional or Unset even if the value is optional (needed for isinstance checks) + json: True if the type refers to the property after JSON serialization """ - type_string = self._type_string - if no_optional: - return self._type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - type_string = f"Union[Unset, {type_string}]" - return type_string + if json: + type_string = self.get_base_json_type_string() + else: + type_string = self.get_base_type_string() + + if no_optional or (self.required and not self.nullable): + return type_string + elif self.required and self.nullable: + return f"Optional[{type_string}]" + elif not self.required and self.nullable: + return f"Union[Unset, None, {type_string}]" + else: + return f"Union[Unset, {type_string}]" def get_instance_type_string(self) -> str: """Get a string representation of runtime type that should be used for `isinstance` checks""" diff --git a/openapi_python_client/templates/property_templates/date_property.py.jinja b/openapi_python_client/templates/property_templates/date_property.py.jinja index a3a980c8f..c8a65a714 100644 --- a/openapi_python_client/templates/property_templates/date_property.py.jinja +++ b/openapi_python_client/templates/property_templates/date_property.py.jinja @@ -9,11 +9,13 @@ if _{{ property.python_name }} is not None: {% endif %} {% endmacro %} +{% macro check_type_for_construct(source) %}isinstance({{ source }}, str){% endmacro %} + {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} {{ destination }} = {{ source }}.isoformat() {% if property.nullable %}if {{ source }} else None {%endif%} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, str]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/datetime_property.py.jinja b/openapi_python_client/templates/property_templates/datetime_property.py.jinja index b8e1b8ff0..696bc7892 100644 --- a/openapi_python_client/templates/property_templates/datetime_property.py.jinja +++ b/openapi_python_client/templates/property_templates/datetime_property.py.jinja @@ -14,6 +14,8 @@ if _{{ property.python_name }} is not None: {% endif %} {% endmacro %} +{% macro check_type_for_construct(source) %}isinstance({{ source }}, str){% endmacro %} + {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} {% if property.nullable %} @@ -22,7 +24,7 @@ if _{{ property.python_name }} is not None: {{ destination }} = {{ source }}.isoformat() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, str]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/enum_property.py.jinja b/openapi_python_client/templates/property_templates/enum_property.py.jinja index 1066fce10..c8db9ad2e 100644 --- a/openapi_python_client/templates/property_templates/enum_property.py.jinja +++ b/openapi_python_client/templates/property_templates/enum_property.py.jinja @@ -9,6 +9,8 @@ if _{{ property.python_name }} is not None and _{{ property.python_name }} is no {% endif %} {% endmacro %} +{% macro check_type_for_construct(source) %}(isinstance({{ source }}, int) or isinstance({{ source }}, str)){% endmacro %} + {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} {% if property.nullable %} @@ -17,12 +19,12 @@ if _{{ property.python_name }} is not None and _{{ property.python_name }} is no {{ destination }} = {{ source }}.value {% endif %} {% else %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable %} - {{ destination }} = {{ source }} if {{ source }} else None + {{ destination }} = {{ source }}.value if {{ source }} else None {% else %} - {{ destination }} = {{ source }} + {{ destination }} = {{ source }}.value {% endif %} {% endif %} {% endmacro %} diff --git a/openapi_python_client/templates/property_templates/file_property.py.jinja b/openapi_python_client/templates/property_templates/file_property.py.jinja index ffa3c20d9..81c846629 100644 --- a/openapi_python_client/templates/property_templates/file_property.py.jinja +++ b/openapi_python_client/templates/property_templates/file_property.py.jinja @@ -4,6 +4,8 @@ ) {% endmacro %} +{% macro check_type_for_construct(source) %}isinstance({{ source }}, bytes){% endmacro %} + {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} {% if property.nullable %} @@ -12,7 +14,7 @@ {{ destination }} = {{ source }}.to_tuple() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable %} {{ destination }} = {{ source }}.to_tuple() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/list_property.py.jinja b/openapi_python_client/templates/property_templates/list_property.py.jinja index d05a13960..61f148d21 100644 --- a/openapi_python_client/templates/property_templates/list_property.py.jinja +++ b/openapi_python_client/templates/property_templates/list_property.py.jinja @@ -31,6 +31,7 @@ for {{ inner_source }} in {{ source }}: {% endif %} {% endmacro %} +{% macro check_type_for_construct(source) %}isinstance({{ source }}, list){% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% set inner_property = property.inner_property %} @@ -44,13 +45,13 @@ else: {{ _transform(property, source, destination) }} {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, List[Any]]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable %} if {{ source }} is None: {{ destination }} = None else: - {{ _transform(property, source, destination) | indent(4)}} + {{ _transform(property, source, destination) | indent(8)}} {% else %} {{ _transform(property, source, destination) | indent(4)}} {% endif %} diff --git a/openapi_python_client/templates/property_templates/model_property.py.jinja b/openapi_python_client/templates/property_templates/model_property.py.jinja index b41289409..df33b7a0f 100644 --- a/openapi_python_client/templates/property_templates/model_property.py.jinja +++ b/openapi_python_client/templates/property_templates/model_property.py.jinja @@ -11,10 +11,12 @@ {% endif %} _{{ property.python_name }} = {{source}} if {% if property.nullable %}_{{ property.python_name }} is not None{% endif %}{% if property.nullable and not property.required %} and {% endif %}{% if not property.required %}not isinstance(_{{ property.python_name }}, Unset){% endif %}: - {{ property.python_name }} = {{ property.reference.class_name }}.from_dict(cast(Dict[str, Any], _{{ property.python_name }})) + {{ property.python_name }} = {{ property.reference.class_name }}.from_dict(_{{ property.python_name }}) {% endif %} {% endmacro %} +{% macro check_type_for_construct(source) %}isinstance({{ source }}, dict){% endmacro %} + {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} {% if property.nullable %} @@ -23,7 +25,7 @@ if {% if property.nullable %}_{{ property.python_name }} is not None{% endif %}{ {{ destination }} = {{ source }}.to_dict() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[{% if property.nullable %}None, {% endif %}Unset, Dict[str, Any]]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable %} {{ destination }} = {{ source }}.to_dict() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/none_property.py.jinja b/openapi_python_client/templates/property_templates/none_property.py.jinja index b3178780a..235530c8b 100644 --- a/openapi_python_client/templates/property_templates/none_property.py.jinja +++ b/openapi_python_client/templates/property_templates/none_property.py.jinja @@ -2,6 +2,8 @@ {{ property.python_name }} = {{ initial_value }} {% endmacro %} +{% macro check_type_for_construct(source) %}{{ source }} is None{% endmacro %} + {% macro transform(property, source, destination, declare_type=True) %} {{ destination }} = None {% endmacro %} diff --git a/openapi_python_client/templates/property_templates/union_property.py.jinja b/openapi_python_client/templates/property_templates/union_property.py.jinja index 4c632c60a..de56fb281 100644 --- a/openapi_python_client/templates/property_templates/union_property.py.jinja +++ b/openapi_python_client/templates/property_templates/union_property.py.jinja @@ -1,17 +1,29 @@ {% macro construct(property, source, initial_value=None) %} -def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string() }}: +def _parse_{{ property.python_name }}(data: {{ property.get_type_string(json=True) }}) -> {{ property.get_type_string() }}: data = None if isinstance(data, Unset) else data {{ property.python_name }}: {{ property.get_type_string() }} + {% if "None" in property.get_type_strings_in_union(json=True) %} + if data is None: + return data + {% endif %} + {% if "Unset" in property.get_type_strings_in_union(json=True) %} + if isinstance(data, Unset): + return data + {% endif %} {% for inner_property in property.inner_properties_with_template() %} {% if not loop.last or property.has_properties_without_templates %} try: - {% from "property_templates/" + inner_property.template import construct %} + {% from "property_templates/" + inner_property.template import construct, check_type_for_construct %} + if not {{ check_type_for_construct("data") }}: + raise TypeError() {{ construct(inner_property, "data", initial_value="UNSET") | indent(8) }} return {{ property.python_name }} except: # noqa: E722 pass {% else %}{# Don't do try/except for the last one #} - {% from "property_templates/" + inner_property.template import construct %} + {% from "property_templates/" + inner_property.template import construct, check_type_for_construct %} + if not {{ check_type_for_construct("data") }}: + raise TypeError() {{ construct(inner_property, "data", initial_value="UNSET") | indent(4) }} return {{ property.python_name }} {% endif %} @@ -24,9 +36,12 @@ def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string( {{ property.python_name }} = _parse_{{ property.python_name }}({{ source }}) {% endmacro %} +{# For now we assume there will be no unions of unions #} +{% macro check_type_for_construct(source) %}True{% endmacro %} + {% macro transform(property, source, destination, declare_type=True) %} -{% if not property.required %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} +{% if not property.required or property.nullable %} +{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} if isinstance({{ source }}, Unset): {{ destination }} = UNSET @@ -37,7 +52,7 @@ if {{ source }} is None: {% else %}{# There's an if UNSET statement before this #} elif {{ source }} is None: {% endif %} - {{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = None + {{ destination }} = None {% endif %} {% for inner_property in property.inner_properties_with_template() %} {% if loop.first and property.required and not property.nullable %}{# No if UNSET or if None statement before this #} diff --git a/openapi_python_client/templates/types.py.jinja b/openapi_python_client/templates/types.py.jinja index 2061b9f08..a354a2192 100644 --- a/openapi_python_client/templates/types.py.jinja +++ b/openapi_python_client/templates/types.py.jinja @@ -11,6 +11,9 @@ class Unset: UNSET: Unset = Unset() +# Used as `FileProperty._json_type_string` +FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] + @attr.s(auto_attribs=True) class File: @@ -20,7 +23,7 @@ class File: file_name: Optional[str] = None mime_type: Optional[str] = None - def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: + def to_tuple(self) -> FileJsonType: """ Return a tuple representation that httpx will accept for multipart/form-data """ return self.file_name, self.payload, self.mime_type From 10926f154df737d86b99d65a6a12586c26801411 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 9 Feb 2021 17:49:35 -0500 Subject: [PATCH 03/17] Regenerate tests --- .../api/tests/defaults_tests_defaults_post.py | 15 +- .../custom_e2e/models/a_model.py | 198 +++++++++++++++++- .../models/model_with_any_json_properties.py | 6 +- ...el_with_primitive_additional_properties.py | 10 +- .../models/model_with_union_property.py | 14 +- .../golden-record-custom/custom_e2e/types.py | 5 +- .../api/tests/defaults_tests_defaults_post.py | 23 +- .../my_test_api_client/models/a_model.py | 198 +++++++++++++++++- .../models/model_with_any_json_properties.py | 6 +- ...el_with_primitive_additional_properties.py | 10 +- .../models/model_with_union_property.py | 14 +- .../golden-record/my_test_api_client/types.py | 5 +- .../parser/properties/__init__.py | 12 +- .../model_property.py.jinja | 2 +- 14 files changed, 455 insertions(+), 63 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index 466b1498d..68302f1d6 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -13,6 +13,7 @@ from ...models.an_enum import AnEnum from ...models.http_validation_error import HTTPValidationError +from ...models.model_with_union_property import ModelWithUnionProperty from ...types import UNSET, Unset @@ -50,6 +51,7 @@ def httpx_request( union_prop: Union[Unset, float, str] = "not a float", union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, + model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: json_datetime_prop: Union[Unset, str] = UNSET @@ -74,20 +76,24 @@ def httpx_request( else: json_union_prop = union_prop - json_union_prop_with_ref: Union[Unset, float, AnEnum] + json_union_prop_with_ref: Union[Unset, float, str] if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): - json_union_prop_with_ref = union_prop_with_ref + json_union_prop_with_ref = union_prop_with_ref.value else: json_union_prop_with_ref = union_prop_with_ref - json_enum_prop: Union[Unset, AnEnum] = UNSET + json_enum_prop: Union[Unset, str] = UNSET if not isinstance(enum_prop, Unset): - json_enum_prop = enum_prop + json_enum_prop = enum_prop.value + + json_model_prop: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(model_prop, Unset): + json_model_prop = model_prop.to_dict() params: Dict[str, Any] = { "string_prop": string_prop, @@ -100,6 +106,7 @@ def httpx_request( "union_prop": json_union_prop, "union_prop_with_ref": json_union_prop_with_ref, "enum_prop": json_enum_prop, + "model_prop": json_model_prop, } params = {k: v for k, v in params.items() if v is not UNSET and v is not None} diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index 1533aaf86..8fececca1 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -10,6 +10,8 @@ from ..models.a_model_nullable_model import AModelNullableModel from ..models.an_enum import AnEnum from ..models.different_enum import DifferentEnum +from ..models.free_form_model import FreeFormModel +from ..models.model_with_union_property import ModelWithUnionProperty from ..types import UNSET, Unset T = TypeVar("T", bound="AModel") @@ -23,16 +25,20 @@ class AModel: a_camel_date_time: Union[datetime.datetime, datetime.date] a_date: datetime.date required_not_nullable: str + one_of_models: Union[FreeFormModel, ModelWithUnionProperty] model: AModelModel a_nullable_date: Optional[datetime.date] required_nullable: Optional[str] + nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] nullable_model: Optional[AModelNullableModel] nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET attr_1_leading_digit: Union[Unset, str] = UNSET - not_required_nullable: Union[Unset, Optional[str]] = UNSET + not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET - not_required_nullable_model: Union[Optional[AModelNotRequiredNullableModel], Unset] = UNSET + not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] = UNSET + not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET + not_required_nullable_model: Union[Unset, None, AModelNotRequiredNullableModel] = UNSET def to_dict(self) -> Dict[str, Any]: an_enum_value = self.an_enum_value.value @@ -45,6 +51,12 @@ def to_dict(self) -> Dict[str, Any]: a_date = self.a_date.isoformat() required_not_nullable = self.required_not_nullable + if isinstance(self.one_of_models, FreeFormModel): + one_of_models = self.one_of_models.to_dict() + + else: + one_of_models = self.one_of_models.to_dict() + model = self.model.to_dict() nested_list_of_enums: Union[Unset, List[Any]] = UNSET @@ -64,13 +76,55 @@ def to_dict(self) -> Dict[str, Any]: required_nullable = self.required_nullable not_required_nullable = self.not_required_nullable not_required_not_nullable = self.not_required_not_nullable + nullable_one_of_models: Union[None, Dict[str, Any]] + if isinstance(self.nullable_one_of_models, Unset): + nullable_one_of_models = UNSET + if self.nullable_one_of_models is None: + nullable_one_of_models = None + elif isinstance(self.nullable_one_of_models, FreeFormModel): + nullable_one_of_models = self.nullable_one_of_models.to_dict() + + else: + nullable_one_of_models = self.nullable_one_of_models.to_dict() + + not_required_one_of_models: Union[Unset, Dict[str, Any]] + if isinstance(self.not_required_one_of_models, Unset): + not_required_one_of_models = UNSET + elif isinstance(self.not_required_one_of_models, FreeFormModel): + not_required_one_of_models = UNSET + if not isinstance(self.not_required_one_of_models, Unset): + not_required_one_of_models = self.not_required_one_of_models.to_dict() + + else: + not_required_one_of_models = UNSET + if not isinstance(self.not_required_one_of_models, Unset): + not_required_one_of_models = self.not_required_one_of_models.to_dict() + + not_required_nullable_one_of_models: Union[Unset, None, Dict[str, Any], str] + if isinstance(self.not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = UNSET + elif self.not_required_nullable_one_of_models is None: + not_required_nullable_one_of_models = None + elif isinstance(self.not_required_nullable_one_of_models, FreeFormModel): + not_required_nullable_one_of_models = UNSET + if not isinstance(self.not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = self.not_required_nullable_one_of_models.to_dict() + + elif isinstance(self.not_required_nullable_one_of_models, ModelWithUnionProperty): + not_required_nullable_one_of_models = UNSET + if not isinstance(self.not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = self.not_required_nullable_one_of_models.to_dict() + + else: + not_required_nullable_one_of_models = self.not_required_nullable_one_of_models + nullable_model = self.nullable_model.to_dict() if self.nullable_model else None not_required_model: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.not_required_model, Unset): not_required_model = self.not_required_model.to_dict() - not_required_nullable_model: Union[None, Unset, Dict[str, Any]] = UNSET + not_required_nullable_model: Union[Unset, None, Dict[str, Any]] = UNSET if not isinstance(self.not_required_nullable_model, Unset): not_required_nullable_model = ( self.not_required_nullable_model.to_dict() if self.not_required_nullable_model else None @@ -83,9 +137,11 @@ def to_dict(self) -> Dict[str, Any]: "aCamelDateTime": a_camel_date_time, "a_date": a_date, "required_not_nullable": required_not_nullable, + "one_of_models": one_of_models, "model": model, "a_nullable_date": a_nullable_date, "required_nullable": required_nullable, + "nullable_one_of_models": nullable_one_of_models, "nullable_model": nullable_model, } ) @@ -97,6 +153,10 @@ def to_dict(self) -> Dict[str, Any]: field_dict["not_required_nullable"] = not_required_nullable if not_required_not_nullable is not UNSET: field_dict["not_required_not_nullable"] = not_required_not_nullable + if not_required_one_of_models is not UNSET: + field_dict["not_required_one_of_models"] = not_required_one_of_models + if not_required_nullable_one_of_models is not UNSET: + field_dict["not_required_nullable_one_of_models"] = not_required_nullable_one_of_models if not_required_model is not UNSET: field_dict["not_required_model"] = not_required_model if not_required_nullable_model is not UNSET: @@ -109,15 +169,19 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.date]: + def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datetime.date]: data = None if isinstance(data, Unset) else data a_camel_date_time: Union[datetime.datetime, datetime.date] try: + if not isinstance(data, str): + raise TypeError() a_camel_date_time = isoparse(data) return a_camel_date_time except: # noqa: E722 pass + if not isinstance(data, str): + raise TypeError() a_camel_date_time = isoparse(data).date() return a_camel_date_time @@ -128,6 +192,25 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat required_not_nullable = d.pop("required_not_nullable") + def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, ModelWithUnionProperty]: + data = None if isinstance(data, Unset) else data + one_of_models: Union[FreeFormModel, ModelWithUnionProperty] + try: + if not isinstance(data, dict): + raise TypeError() + one_of_models = FreeFormModel.from_dict(data) + + return one_of_models + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + one_of_models = ModelWithUnionProperty.from_dict(data) + + return one_of_models + + one_of_models = _parse_one_of_models(d.pop("one_of_models")) + model = AModelModel.from_dict(d.pop("model")) nested_list_of_enums = [] @@ -155,28 +238,118 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) + def _parse_nullable_one_of_models( + data: Union[None, Dict[str, Any]] + ) -> Union[None, FreeFormModel, ModelWithUnionProperty]: + data = None if isinstance(data, Unset) else data + nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + nullable_one_of_models = FreeFormModel.from_dict(data) + + return nullable_one_of_models + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + nullable_one_of_models = ModelWithUnionProperty.from_dict(data) + + return nullable_one_of_models + + nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) + + def _parse_not_required_one_of_models( + data: Union[Unset, Dict[str, Any]] + ) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: + data = None if isinstance(data, Unset) else data + not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + not_required_one_of_models = UNSET + _not_required_one_of_models = data + if not isinstance(_not_required_one_of_models, Unset): + not_required_one_of_models = FreeFormModel.from_dict(_not_required_one_of_models) + + return not_required_one_of_models + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + not_required_one_of_models = UNSET + _not_required_one_of_models = data + if not isinstance(_not_required_one_of_models, Unset): + not_required_one_of_models = ModelWithUnionProperty.from_dict(_not_required_one_of_models) + + return not_required_one_of_models + + not_required_one_of_models = _parse_not_required_one_of_models(d.pop("not_required_one_of_models", UNSET)) + + def _parse_not_required_nullable_one_of_models( + data: Union[Unset, None, Dict[str, Any], str] + ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: + data = None if isinstance(data, Unset) else data + not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + not_required_nullable_one_of_models = UNSET + _not_required_nullable_one_of_models = data + if not isinstance(_not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = FreeFormModel.from_dict(_not_required_nullable_one_of_models) + + return not_required_nullable_one_of_models + except: # noqa: E722 + pass + try: + if not isinstance(data, dict): + raise TypeError() + not_required_nullable_one_of_models = UNSET + _not_required_nullable_one_of_models = data + if not isinstance(_not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = ModelWithUnionProperty.from_dict( + _not_required_nullable_one_of_models + ) + + return not_required_nullable_one_of_models + except: # noqa: E722 + pass + return cast(Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str], data) + + not_required_nullable_one_of_models = _parse_not_required_nullable_one_of_models( + d.pop("not_required_nullable_one_of_models", UNSET) + ) + nullable_model = None _nullable_model = d.pop("nullable_model") if _nullable_model is not None: - nullable_model = AModelNullableModel.from_dict(cast(Dict[str, Any], _nullable_model)) + nullable_model = AModelNullableModel.from_dict(_nullable_model) - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET _not_required_model = d.pop("not_required_model", UNSET) if not isinstance(_not_required_model, Unset): - not_required_model = AModelNotRequiredModel.from_dict(cast(Dict[str, Any], _not_required_model)) + not_required_model = AModelNotRequiredModel.from_dict(_not_required_model) not_required_nullable_model = None _not_required_nullable_model = d.pop("not_required_nullable_model", UNSET) if _not_required_nullable_model is not None and not isinstance(_not_required_nullable_model, Unset): - not_required_nullable_model = AModelNotRequiredNullableModel.from_dict( - cast(Dict[str, Any], _not_required_nullable_model) - ) + not_required_nullable_model = AModelNotRequiredNullableModel.from_dict(_not_required_nullable_model) a_model = cls( an_enum_value=an_enum_value, a_camel_date_time=a_camel_date_time, a_date=a_date, required_not_nullable=required_not_nullable, + one_of_models=one_of_models, model=model, nested_list_of_enums=nested_list_of_enums, a_nullable_date=a_nullable_date, @@ -184,6 +357,9 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat required_nullable=required_nullable, not_required_nullable=not_required_nullable, not_required_not_nullable=not_required_not_nullable, + nullable_one_of_models=nullable_one_of_models, + not_required_one_of_models=not_required_one_of_models, + not_required_nullable_one_of_models=not_required_nullable_one_of_models, nullable_model=nullable_model, not_required_model=not_required_model, not_required_nullable_model=not_required_nullable_model, diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py index 7696b9753..80c907299 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py @@ -42,19 +42,23 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: for prop_name, prop_dict in d.items(): def _parse_additional_property( - data: Any, + data: Union[Dict[str, Any], List[Any], str, float, int, bool] ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: data = None if isinstance(data, Unset) else data additional_property: Union[ ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool ] try: + if not isinstance(data, dict): + raise TypeError() additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data) return additional_property except: # noqa: E722 pass try: + if not isinstance(data, list): + raise TypeError() additional_property = cast(List[str], data) return additional_property diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py index 98f80bf17..68e2238dd 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Type, TypeVar, Union, cast +from typing import Any, Dict, List, Type, TypeVar, Union import attr @@ -14,7 +14,7 @@ class ModelWithPrimitiveAdditionalProperties: """ """ - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: @@ -33,12 +33,10 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET _a_date_holder = d.pop("a_date_holder", UNSET) if not isinstance(_a_date_holder, Unset): - a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict( - cast(Dict[str, Any], _a_date_holder) - ) + a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict(_a_date_holder) model_with_primitive_additional_properties = cls( a_date_holder=a_date_holder, diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index ed8deec19..350b743a5 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -16,18 +16,18 @@ class ModelWithUnionProperty: a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, AnEnum, AnIntEnum] + a_property: Union[Unset, str, int] if isinstance(self.a_property, Unset): a_property = UNSET elif isinstance(self.a_property, AnEnum): a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value else: a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value field_dict: Dict[str, Any] = {} field_dict.update({}) @@ -40,10 +40,14 @@ def to_dict(self) -> Dict[str, Any]: def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: + def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIntEnum]: data = None if isinstance(data, Unset) else data a_property: Union[Unset, AnEnum, AnIntEnum] + if isinstance(data, Unset): + return data try: + if not (isinstance(data, int) or isinstance(data, str)): + raise TypeError() a_property = UNSET _a_property = data if _a_property is not None and _a_property is not UNSET: @@ -52,6 +56,8 @@ def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: return a_property except: # noqa: E722 pass + if not (isinstance(data, int) or isinstance(data, str)): + raise TypeError() a_property = UNSET _a_property = data if _a_property is not None and _a_property is not UNSET: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/types.py b/end_to_end_tests/golden-record-custom/custom_e2e/types.py index 2061b9f08..a354a2192 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/types.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/types.py @@ -11,6 +11,9 @@ def __bool__(self) -> bool: UNSET: Unset = Unset() +# Used as `FileProperty._json_type_string` +FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] + @attr.s(auto_attribs=True) class File: @@ -20,7 +23,7 @@ class File: file_name: Optional[str] = None mime_type: Optional[str] = None - def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: + def to_tuple(self) -> FileJsonType: """ Return a tuple representation that httpx will accept for multipart/form-data """ return self.file_name, self.payload, self.mime_type diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index b3e6d6dfb..689255a46 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -7,6 +7,7 @@ from ...client import Client from ...models.an_enum import AnEnum from ...models.http_validation_error import HTTPValidationError +from ...models.model_with_union_property import ModelWithUnionProperty from ...types import UNSET, Response, Unset @@ -23,6 +24,7 @@ def _get_kwargs( union_prop: Union[Unset, float, str] = "not a float", union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, + model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Dict[str, Any]: url = "{}/tests/defaults".format(client.base_url) @@ -50,20 +52,24 @@ def _get_kwargs( else: json_union_prop = union_prop - json_union_prop_with_ref: Union[Unset, float, AnEnum] + json_union_prop_with_ref: Union[Unset, float, str] if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): - json_union_prop_with_ref = union_prop_with_ref + json_union_prop_with_ref = union_prop_with_ref.value else: json_union_prop_with_ref = union_prop_with_ref - json_enum_prop: Union[Unset, AnEnum] = UNSET + json_enum_prop: Union[Unset, str] = UNSET if not isinstance(enum_prop, Unset): - json_enum_prop = enum_prop + json_enum_prop = enum_prop.value + + json_model_prop: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(model_prop, Unset): + json_model_prop = model_prop.to_dict() params: Dict[str, Any] = { "string_prop": string_prop, @@ -76,6 +82,7 @@ def _get_kwargs( "union_prop": json_union_prop, "union_prop_with_ref": json_union_prop_with_ref, "enum_prop": json_enum_prop, + "model_prop": json_model_prop, } params = {k: v for k, v in params.items() if v is not UNSET and v is not None} @@ -122,6 +129,7 @@ def sync_detailed( union_prop: Union[Unset, float, str] = "not a float", union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, + model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -135,6 +143,7 @@ def sync_detailed( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, ) response = httpx.post( @@ -157,6 +166,7 @@ def sync( union_prop: Union[Unset, float, str] = "not a float", union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, + model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Optional[Union[None, HTTPValidationError]]: """ """ @@ -172,6 +182,7 @@ def sync( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, ).parsed @@ -188,6 +199,7 @@ async def asyncio_detailed( union_prop: Union[Unset, float, str] = "not a float", union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, + model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -201,6 +213,7 @@ async def asyncio_detailed( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, ) async with httpx.AsyncClient() as _client: @@ -222,6 +235,7 @@ async def asyncio( union_prop: Union[Unset, float, str] = "not a float", union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, + model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Optional[Union[None, HTTPValidationError]]: """ """ @@ -238,5 +252,6 @@ async def asyncio( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, ) ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 1533aaf86..8fececca1 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -10,6 +10,8 @@ from ..models.a_model_nullable_model import AModelNullableModel from ..models.an_enum import AnEnum from ..models.different_enum import DifferentEnum +from ..models.free_form_model import FreeFormModel +from ..models.model_with_union_property import ModelWithUnionProperty from ..types import UNSET, Unset T = TypeVar("T", bound="AModel") @@ -23,16 +25,20 @@ class AModel: a_camel_date_time: Union[datetime.datetime, datetime.date] a_date: datetime.date required_not_nullable: str + one_of_models: Union[FreeFormModel, ModelWithUnionProperty] model: AModelModel a_nullable_date: Optional[datetime.date] required_nullable: Optional[str] + nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] nullable_model: Optional[AModelNullableModel] nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET attr_1_leading_digit: Union[Unset, str] = UNSET - not_required_nullable: Union[Unset, Optional[str]] = UNSET + not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET - not_required_nullable_model: Union[Optional[AModelNotRequiredNullableModel], Unset] = UNSET + not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] = UNSET + not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET + not_required_nullable_model: Union[Unset, None, AModelNotRequiredNullableModel] = UNSET def to_dict(self) -> Dict[str, Any]: an_enum_value = self.an_enum_value.value @@ -45,6 +51,12 @@ def to_dict(self) -> Dict[str, Any]: a_date = self.a_date.isoformat() required_not_nullable = self.required_not_nullable + if isinstance(self.one_of_models, FreeFormModel): + one_of_models = self.one_of_models.to_dict() + + else: + one_of_models = self.one_of_models.to_dict() + model = self.model.to_dict() nested_list_of_enums: Union[Unset, List[Any]] = UNSET @@ -64,13 +76,55 @@ def to_dict(self) -> Dict[str, Any]: required_nullable = self.required_nullable not_required_nullable = self.not_required_nullable not_required_not_nullable = self.not_required_not_nullable + nullable_one_of_models: Union[None, Dict[str, Any]] + if isinstance(self.nullable_one_of_models, Unset): + nullable_one_of_models = UNSET + if self.nullable_one_of_models is None: + nullable_one_of_models = None + elif isinstance(self.nullable_one_of_models, FreeFormModel): + nullable_one_of_models = self.nullable_one_of_models.to_dict() + + else: + nullable_one_of_models = self.nullable_one_of_models.to_dict() + + not_required_one_of_models: Union[Unset, Dict[str, Any]] + if isinstance(self.not_required_one_of_models, Unset): + not_required_one_of_models = UNSET + elif isinstance(self.not_required_one_of_models, FreeFormModel): + not_required_one_of_models = UNSET + if not isinstance(self.not_required_one_of_models, Unset): + not_required_one_of_models = self.not_required_one_of_models.to_dict() + + else: + not_required_one_of_models = UNSET + if not isinstance(self.not_required_one_of_models, Unset): + not_required_one_of_models = self.not_required_one_of_models.to_dict() + + not_required_nullable_one_of_models: Union[Unset, None, Dict[str, Any], str] + if isinstance(self.not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = UNSET + elif self.not_required_nullable_one_of_models is None: + not_required_nullable_one_of_models = None + elif isinstance(self.not_required_nullable_one_of_models, FreeFormModel): + not_required_nullable_one_of_models = UNSET + if not isinstance(self.not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = self.not_required_nullable_one_of_models.to_dict() + + elif isinstance(self.not_required_nullable_one_of_models, ModelWithUnionProperty): + not_required_nullable_one_of_models = UNSET + if not isinstance(self.not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = self.not_required_nullable_one_of_models.to_dict() + + else: + not_required_nullable_one_of_models = self.not_required_nullable_one_of_models + nullable_model = self.nullable_model.to_dict() if self.nullable_model else None not_required_model: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.not_required_model, Unset): not_required_model = self.not_required_model.to_dict() - not_required_nullable_model: Union[None, Unset, Dict[str, Any]] = UNSET + not_required_nullable_model: Union[Unset, None, Dict[str, Any]] = UNSET if not isinstance(self.not_required_nullable_model, Unset): not_required_nullable_model = ( self.not_required_nullable_model.to_dict() if self.not_required_nullable_model else None @@ -83,9 +137,11 @@ def to_dict(self) -> Dict[str, Any]: "aCamelDateTime": a_camel_date_time, "a_date": a_date, "required_not_nullable": required_not_nullable, + "one_of_models": one_of_models, "model": model, "a_nullable_date": a_nullable_date, "required_nullable": required_nullable, + "nullable_one_of_models": nullable_one_of_models, "nullable_model": nullable_model, } ) @@ -97,6 +153,10 @@ def to_dict(self) -> Dict[str, Any]: field_dict["not_required_nullable"] = not_required_nullable if not_required_not_nullable is not UNSET: field_dict["not_required_not_nullable"] = not_required_not_nullable + if not_required_one_of_models is not UNSET: + field_dict["not_required_one_of_models"] = not_required_one_of_models + if not_required_nullable_one_of_models is not UNSET: + field_dict["not_required_nullable_one_of_models"] = not_required_nullable_one_of_models if not_required_model is not UNSET: field_dict["not_required_model"] = not_required_model if not_required_nullable_model is not UNSET: @@ -109,15 +169,19 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.date]: + def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datetime.date]: data = None if isinstance(data, Unset) else data a_camel_date_time: Union[datetime.datetime, datetime.date] try: + if not isinstance(data, str): + raise TypeError() a_camel_date_time = isoparse(data) return a_camel_date_time except: # noqa: E722 pass + if not isinstance(data, str): + raise TypeError() a_camel_date_time = isoparse(data).date() return a_camel_date_time @@ -128,6 +192,25 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat required_not_nullable = d.pop("required_not_nullable") + def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, ModelWithUnionProperty]: + data = None if isinstance(data, Unset) else data + one_of_models: Union[FreeFormModel, ModelWithUnionProperty] + try: + if not isinstance(data, dict): + raise TypeError() + one_of_models = FreeFormModel.from_dict(data) + + return one_of_models + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + one_of_models = ModelWithUnionProperty.from_dict(data) + + return one_of_models + + one_of_models = _parse_one_of_models(d.pop("one_of_models")) + model = AModelModel.from_dict(d.pop("model")) nested_list_of_enums = [] @@ -155,28 +238,118 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) + def _parse_nullable_one_of_models( + data: Union[None, Dict[str, Any]] + ) -> Union[None, FreeFormModel, ModelWithUnionProperty]: + data = None if isinstance(data, Unset) else data + nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + nullable_one_of_models = FreeFormModel.from_dict(data) + + return nullable_one_of_models + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + nullable_one_of_models = ModelWithUnionProperty.from_dict(data) + + return nullable_one_of_models + + nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) + + def _parse_not_required_one_of_models( + data: Union[Unset, Dict[str, Any]] + ) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: + data = None if isinstance(data, Unset) else data + not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + not_required_one_of_models = UNSET + _not_required_one_of_models = data + if not isinstance(_not_required_one_of_models, Unset): + not_required_one_of_models = FreeFormModel.from_dict(_not_required_one_of_models) + + return not_required_one_of_models + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + not_required_one_of_models = UNSET + _not_required_one_of_models = data + if not isinstance(_not_required_one_of_models, Unset): + not_required_one_of_models = ModelWithUnionProperty.from_dict(_not_required_one_of_models) + + return not_required_one_of_models + + not_required_one_of_models = _parse_not_required_one_of_models(d.pop("not_required_one_of_models", UNSET)) + + def _parse_not_required_nullable_one_of_models( + data: Union[Unset, None, Dict[str, Any], str] + ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: + data = None if isinstance(data, Unset) else data + not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + not_required_nullable_one_of_models = UNSET + _not_required_nullable_one_of_models = data + if not isinstance(_not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = FreeFormModel.from_dict(_not_required_nullable_one_of_models) + + return not_required_nullable_one_of_models + except: # noqa: E722 + pass + try: + if not isinstance(data, dict): + raise TypeError() + not_required_nullable_one_of_models = UNSET + _not_required_nullable_one_of_models = data + if not isinstance(_not_required_nullable_one_of_models, Unset): + not_required_nullable_one_of_models = ModelWithUnionProperty.from_dict( + _not_required_nullable_one_of_models + ) + + return not_required_nullable_one_of_models + except: # noqa: E722 + pass + return cast(Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str], data) + + not_required_nullable_one_of_models = _parse_not_required_nullable_one_of_models( + d.pop("not_required_nullable_one_of_models", UNSET) + ) + nullable_model = None _nullable_model = d.pop("nullable_model") if _nullable_model is not None: - nullable_model = AModelNullableModel.from_dict(cast(Dict[str, Any], _nullable_model)) + nullable_model = AModelNullableModel.from_dict(_nullable_model) - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET _not_required_model = d.pop("not_required_model", UNSET) if not isinstance(_not_required_model, Unset): - not_required_model = AModelNotRequiredModel.from_dict(cast(Dict[str, Any], _not_required_model)) + not_required_model = AModelNotRequiredModel.from_dict(_not_required_model) not_required_nullable_model = None _not_required_nullable_model = d.pop("not_required_nullable_model", UNSET) if _not_required_nullable_model is not None and not isinstance(_not_required_nullable_model, Unset): - not_required_nullable_model = AModelNotRequiredNullableModel.from_dict( - cast(Dict[str, Any], _not_required_nullable_model) - ) + not_required_nullable_model = AModelNotRequiredNullableModel.from_dict(_not_required_nullable_model) a_model = cls( an_enum_value=an_enum_value, a_camel_date_time=a_camel_date_time, a_date=a_date, required_not_nullable=required_not_nullable, + one_of_models=one_of_models, model=model, nested_list_of_enums=nested_list_of_enums, a_nullable_date=a_nullable_date, @@ -184,6 +357,9 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat required_nullable=required_nullable, not_required_nullable=not_required_nullable, not_required_not_nullable=not_required_not_nullable, + nullable_one_of_models=nullable_one_of_models, + not_required_one_of_models=not_required_one_of_models, + not_required_nullable_one_of_models=not_required_nullable_one_of_models, nullable_model=nullable_model, not_required_model=not_required_model, not_required_nullable_model=not_required_nullable_model, 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 7696b9753..80c907299 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 @@ -42,19 +42,23 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: for prop_name, prop_dict in d.items(): def _parse_additional_property( - data: Any, + data: Union[Dict[str, Any], List[Any], str, float, int, bool] ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: data = None if isinstance(data, Unset) else data additional_property: Union[ ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool ] try: + if not isinstance(data, dict): + raise TypeError() additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data) return additional_property except: # noqa: E722 pass try: + if not isinstance(data, list): + raise TypeError() additional_property = cast(List[str], data) return additional_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py index 98f80bf17..68e2238dd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Type, TypeVar, Union, cast +from typing import Any, Dict, List, Type, TypeVar, Union import attr @@ -14,7 +14,7 @@ class ModelWithPrimitiveAdditionalProperties: """ """ - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: @@ -33,12 +33,10 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET _a_date_holder = d.pop("a_date_holder", UNSET) if not isinstance(_a_date_holder, Unset): - a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict( - cast(Dict[str, Any], _a_date_holder) - ) + a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict(_a_date_holder) model_with_primitive_additional_properties = cls( a_date_holder=a_date_holder, diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index ed8deec19..350b743a5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -16,18 +16,18 @@ class ModelWithUnionProperty: a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, AnEnum, AnIntEnum] + a_property: Union[Unset, str, int] if isinstance(self.a_property, Unset): a_property = UNSET elif isinstance(self.a_property, AnEnum): a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value else: a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value field_dict: Dict[str, Any] = {} field_dict.update({}) @@ -40,10 +40,14 @@ def to_dict(self) -> Dict[str, Any]: def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: + def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIntEnum]: data = None if isinstance(data, Unset) else data a_property: Union[Unset, AnEnum, AnIntEnum] + if isinstance(data, Unset): + return data try: + if not (isinstance(data, int) or isinstance(data, str)): + raise TypeError() a_property = UNSET _a_property = data if _a_property is not None and _a_property is not UNSET: @@ -52,6 +56,8 @@ def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: return a_property except: # noqa: E722 pass + if not (isinstance(data, int) or isinstance(data, str)): + raise TypeError() a_property = UNSET _a_property = data if _a_property is not None and _a_property is not UNSET: diff --git a/end_to_end_tests/golden-record/my_test_api_client/types.py b/end_to_end_tests/golden-record/my_test_api_client/types.py index 2061b9f08..a354a2192 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/types.py +++ b/end_to_end_tests/golden-record/my_test_api_client/types.py @@ -11,6 +11,9 @@ def __bool__(self) -> bool: UNSET: Unset = Unset() +# Used as `FileProperty._json_type_string` +FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] + @attr.s(auto_attribs=True) class File: @@ -20,7 +23,7 @@ class File: file_name: Optional[str] = None mime_type: Optional[str] = None - def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: + def to_tuple(self) -> FileJsonType: """ Return a tuple representation that httpx will accept for multipart/form-data """ return self.file_name, self.payload, self.mime_type diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index f173b3107..dfe778e71 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -40,7 +40,7 @@ class DateTimeProperty(Property): """ _type_string: ClassVar[str] = "datetime.datetime" - _json_type_string: ClassVar[str] = "str" + _json_type_string: ClassVar[str] = "str" template: ClassVar[str] = "datetime_property.py.jinja" def get_imports(self, *, prefix: str) -> Set[str]: @@ -176,13 +176,11 @@ def _get_inner_type_strings(self, json: bool = False) -> List[str]: def get_base_type_string(self) -> str: return f"Union[{', '.join(self._get_inner_type_strings(json=False))}]" - + def get_base_json_type_string(self) -> str: return f"Union[{', '.join(self._get_inner_type_strings(json=True))}]" - def get_type_strings_in_union( - self, no_optional: bool = False, json: bool = False - ) -> List[str]: + def get_type_strings_in_union(self, no_optional: bool = False, json: bool = False) -> List[str]: type_strings = self._get_inner_type_strings(json=json) if no_optional or (self.required and not self.nullable): @@ -200,9 +198,7 @@ def get_type_string(self, no_optional: bool = False, json: bool = False) -> str: This implementation differs slightly from `Property.get_type_string` in order to collapse nested union types. """ - type_strings_in_union = self.get_type_strings_in_union( - no_optional=no_optional, json=json - ) + type_strings_in_union = self.get_type_strings_in_union(no_optional=no_optional, json=json) return f"Union[{', '.join(type_strings_in_union)}]" def get_imports(self, *, prefix: str) -> Set[str]: diff --git a/openapi_python_client/templates/property_templates/model_property.py.jinja b/openapi_python_client/templates/property_templates/model_property.py.jinja index df33b7a0f..68f4d1266 100644 --- a/openapi_python_client/templates/property_templates/model_property.py.jinja +++ b/openapi_python_client/templates/property_templates/model_property.py.jinja @@ -25,7 +25,7 @@ if {% if property.nullable %}_{{ property.python_name }} is not None{% endif %}{ {{ destination }} = {{ source }}.to_dict() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable %} {{ destination }} = {{ source }}.to_dict() if {{ source }} else None From 465943dcd02073e9379561468c08697c3c8469fb Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 9 Feb 2021 18:01:55 -0500 Subject: [PATCH 04/17] Fix tests --- .../api/tests/defaults_tests_defaults_post.py | 30 +++++-- .../custom_e2e/models/a_model.py | 5 -- .../models/model_with_any_json_properties.py | 2 - .../models/model_with_union_property.py | 1 - .../api/tests/defaults_tests_defaults_post.py | 68 ++++++++++++---- .../my_test_api_client/models/a_model.py | 5 -- .../models/model_with_any_json_properties.py | 2 - .../models/model_with_union_property.py | 1 - end_to_end_tests/openapi.json | 41 +++++++++- .../union_property.py.jinja | 1 - .../test_parser/test_properties/test_init.py | 78 +++++++------------ .../test_properties/test_model_property.py | 4 +- 12 files changed, 149 insertions(+), 89 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index 68302f1d6..f1aedb4f0 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -7,7 +7,7 @@ Client = httpx.Client import datetime -from typing import Dict, List, Union +from typing import Dict, List, Optional, Union from dateutil.parser import isoparse @@ -42,7 +42,10 @@ def httpx_request( *, client: Client, string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, float] = 3.14, int_prop: Union[Unset, int] = 7, @@ -54,9 +57,21 @@ def httpx_request( model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: - json_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(datetime_prop, Unset): - json_datetime_prop = datetime_prop.isoformat() + json_not_required_not_nullable_datetime_prop: Union[Unset, str] = UNSET + if not isinstance(not_required_not_nullable_datetime_prop, Unset): + json_not_required_not_nullable_datetime_prop = not_required_not_nullable_datetime_prop.isoformat() + + json_not_required_nullable_datetime_prop: Union[Unset, None, str] = UNSET + if not isinstance(not_required_nullable_datetime_prop, Unset): + json_not_required_nullable_datetime_prop = ( + not_required_nullable_datetime_prop.isoformat() if not_required_nullable_datetime_prop else None + ) + + json_required_not_nullable_datetime_prop = required_not_nullable_datetime_prop.isoformat() + + json_required_nullable_datetime_prop = ( + required_nullable_datetime_prop.isoformat() if required_nullable_datetime_prop else None + ) json_date_prop: Union[Unset, str] = UNSET if not isinstance(date_prop, Unset): @@ -97,7 +112,10 @@ def httpx_request( params: Dict[str, Any] = { "string_prop": string_prop, - "datetime_prop": json_datetime_prop, + "not_required_not_nullable_datetime_prop": json_not_required_not_nullable_datetime_prop, + "not_required_nullable_datetime_prop": json_not_required_nullable_datetime_prop, + "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, + "required_nullable_datetime_prop": json_required_nullable_datetime_prop, "date_prop": json_date_prop, "float_prop": float_prop, "int_prop": int_prop, diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index 8fececca1..cf9280cab 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -170,7 +170,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: an_enum_value = AnEnum(d.pop("an_enum_value")) def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datetime.date]: - data = None if isinstance(data, Unset) else data a_camel_date_time: Union[datetime.datetime, datetime.date] try: if not isinstance(data, str): @@ -193,7 +192,6 @@ def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datet required_not_nullable = d.pop("required_not_nullable") def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, ModelWithUnionProperty]: - data = None if isinstance(data, Unset) else data one_of_models: Union[FreeFormModel, ModelWithUnionProperty] try: if not isinstance(data, dict): @@ -241,7 +239,6 @@ def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, Mo def _parse_nullable_one_of_models( data: Union[None, Dict[str, Any]] ) -> Union[None, FreeFormModel, ModelWithUnionProperty]: - data = None if isinstance(data, Unset) else data nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] if data is None: return data @@ -264,7 +261,6 @@ def _parse_nullable_one_of_models( def _parse_not_required_one_of_models( data: Union[Unset, Dict[str, Any]] ) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: - data = None if isinstance(data, Unset) else data not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] if isinstance(data, Unset): return data @@ -293,7 +289,6 @@ def _parse_not_required_one_of_models( def _parse_not_required_nullable_one_of_models( data: Union[Unset, None, Dict[str, Any], str] ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: - data = None if isinstance(data, Unset) else data not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] if data is None: return data diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py index 80c907299..716bcd618 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py @@ -3,7 +3,6 @@ import attr from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty -from ..types import Unset T = TypeVar("T", bound="ModelWithAnyJsonProperties") @@ -44,7 +43,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: Union[Dict[str, Any], List[Any], str, float, int, bool] ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: - data = None if isinstance(data, Unset) else data additional_property: Union[ ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool ] diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index 350b743a5..9321920b0 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -41,7 +41,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIntEnum]: - data = None if isinstance(data, Unset) else data a_property: Union[Unset, AnEnum, AnIntEnum] if isinstance(data, Unset): return data diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index 689255a46..b8b1a3220 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -15,7 +15,10 @@ def _get_kwargs( *, client: Client, string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, float] = 3.14, int_prop: Union[Unset, int] = 7, @@ -30,9 +33,21 @@ def _get_kwargs( headers: Dict[str, Any] = client.get_headers() - json_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(datetime_prop, Unset): - json_datetime_prop = datetime_prop.isoformat() + json_not_required_not_nullable_datetime_prop: Union[Unset, str] = UNSET + if not isinstance(not_required_not_nullable_datetime_prop, Unset): + json_not_required_not_nullable_datetime_prop = not_required_not_nullable_datetime_prop.isoformat() + + json_not_required_nullable_datetime_prop: Union[Unset, None, str] = UNSET + if not isinstance(not_required_nullable_datetime_prop, Unset): + json_not_required_nullable_datetime_prop = ( + not_required_nullable_datetime_prop.isoformat() if not_required_nullable_datetime_prop else None + ) + + json_required_not_nullable_datetime_prop = required_not_nullable_datetime_prop.isoformat() + + json_required_nullable_datetime_prop = ( + required_nullable_datetime_prop.isoformat() if required_nullable_datetime_prop else None + ) json_date_prop: Union[Unset, str] = UNSET if not isinstance(date_prop, Unset): @@ -73,7 +88,10 @@ def _get_kwargs( params: Dict[str, Any] = { "string_prop": string_prop, - "datetime_prop": json_datetime_prop, + "not_required_not_nullable_datetime_prop": json_not_required_not_nullable_datetime_prop, + "not_required_nullable_datetime_prop": json_not_required_nullable_datetime_prop, + "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, + "required_nullable_datetime_prop": json_required_nullable_datetime_prop, "date_prop": json_date_prop, "float_prop": float_prop, "int_prop": int_prop, @@ -120,7 +138,10 @@ def sync_detailed( *, client: Client, string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, float] = 3.14, int_prop: Union[Unset, int] = 7, @@ -134,7 +155,10 @@ def sync_detailed( kwargs = _get_kwargs( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, @@ -157,7 +181,10 @@ def sync( *, client: Client, string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, float] = 3.14, int_prop: Union[Unset, int] = 7, @@ -173,7 +200,10 @@ def sync( return sync_detailed( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, @@ -190,7 +220,10 @@ async def asyncio_detailed( *, client: Client, string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, float] = 3.14, int_prop: Union[Unset, int] = 7, @@ -204,7 +237,10 @@ async def asyncio_detailed( kwargs = _get_kwargs( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, @@ -226,7 +262,10 @@ async def asyncio( *, client: Client, string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, float] = 3.14, int_prop: Union[Unset, int] = 7, @@ -243,7 +282,10 @@ async def asyncio( await asyncio_detailed( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 8fececca1..cf9280cab 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -170,7 +170,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: an_enum_value = AnEnum(d.pop("an_enum_value")) def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datetime.date]: - data = None if isinstance(data, Unset) else data a_camel_date_time: Union[datetime.datetime, datetime.date] try: if not isinstance(data, str): @@ -193,7 +192,6 @@ def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datet required_not_nullable = d.pop("required_not_nullable") def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, ModelWithUnionProperty]: - data = None if isinstance(data, Unset) else data one_of_models: Union[FreeFormModel, ModelWithUnionProperty] try: if not isinstance(data, dict): @@ -241,7 +239,6 @@ def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, Mo def _parse_nullable_one_of_models( data: Union[None, Dict[str, Any]] ) -> Union[None, FreeFormModel, ModelWithUnionProperty]: - data = None if isinstance(data, Unset) else data nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] if data is None: return data @@ -264,7 +261,6 @@ def _parse_nullable_one_of_models( def _parse_not_required_one_of_models( data: Union[Unset, Dict[str, Any]] ) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: - data = None if isinstance(data, Unset) else data not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] if isinstance(data, Unset): return data @@ -293,7 +289,6 @@ def _parse_not_required_one_of_models( def _parse_not_required_nullable_one_of_models( data: Union[Unset, None, Dict[str, Any], str] ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: - data = None if isinstance(data, Unset) else data not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] if data is None: return data 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 80c907299..716bcd618 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 @@ -3,7 +3,6 @@ import attr from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty -from ..types import Unset T = TypeVar("T", bound="ModelWithAnyJsonProperties") @@ -44,7 +43,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: Union[Dict[str, Any], List[Any], str, float, int, bool] ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: - data = None if isinstance(data, Unset) else data additional_property: Union[ ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool ] diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index 350b743a5..9321920b0 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -41,7 +41,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIntEnum]: - data = None if isinstance(data, Unset) else data a_property: Union[Unset, AnEnum, AnIntEnum] if isinstance(data, Unset): return data diff --git a/end_to_end_tests/openapi.json b/end_to_end_tests/openapi.json index 8b5c883da..fd4e584b9 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -290,12 +290,49 @@ { "required": false, "schema": { - "title": "Datetime Prop", + "title": "Not Required, Not Nullable Datetime Prop", + "nullable": false, "type": "string", "format": "date-time", "default": "1010-10-10T00:00:00" }, - "name": "datetime_prop", + "name": "not_required_not_nullable_datetime_prop", + "in": "query" + }, + { + "required": false, + "schema": { + "title": "Not Required, Nullable Datetime Prop", + "nullable": true, + "type": "string", + "format": "date-time", + "default": "1010-10-10T00:00:00" + }, + "name": "not_required_nullable_datetime_prop", + "in": "query" + }, + { + "required": true, + "schema": { + "title": "Required, Not Nullable Datetime Prop", + "nullable": false, + "type": "string", + "format": "date-time", + "default": "1010-10-10T00:00:00" + }, + "name": "required_not_nullable_datetime_prop", + "in": "query" + }, + { + "required": true, + "schema": { + "title": "Required, Nullable Datetime Prop", + "nullable": true, + "type": "string", + "format": "date-time", + "default": "1010-10-10T00:00:00" + }, + "name": "required_nullable_datetime_prop", "in": "query" }, { diff --git a/openapi_python_client/templates/property_templates/union_property.py.jinja b/openapi_python_client/templates/property_templates/union_property.py.jinja index de56fb281..051c7c460 100644 --- a/openapi_python_client/templates/property_templates/union_property.py.jinja +++ b/openapi_python_client/templates/property_templates/union_property.py.jinja @@ -1,6 +1,5 @@ {% macro construct(property, source, initial_value=None) %} def _parse_{{ property.python_name }}(data: {{ property.get_type_string(json=True) }}) -> {{ property.get_type_string() }}: - data = None if isinstance(data, Unset) else data {{ property.python_name }}: {{ property.get_type_string() }} {% if "None" in property.get_type_strings_in_union(json=True) %} if data is None: diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 2a70322d6..865210eb6 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -17,53 +17,41 @@ class TestProperty: @pytest.mark.parametrize( - "query_parameter,nullable,required,no_optional,expected", + "nullable,required,no_optional,expected", [ - (False, False, False, False, "Union[Unset, TestType]"), - (False, False, False, True, "TestType"), - (False, False, True, False, "TestType"), - (False, False, True, True, "TestType"), - (False, True, False, False, "Union[Unset, None, TestType]"), - (False, True, False, True, "TestType"), - (False, True, True, False, "Optional[TestType]"), - (False, True, True, True, "TestType"), - (True, False, False, False, "Union[Unset, None, TestType]"), - (True, False, False, True, "TestType"), - (True, False, True, False, "TestType"), - (True, False, True, True, "TestType"), - (True, True, False, False, "Union[Unset, None, TestType]"), - (True, True, False, True, "TestType"), - (True, True, True, False, "Optional[TestType]"), - (True, True, True, True, "TestType"), + (False, False, False, "Union[Unset, TestType]"), + (False, False, True, "TestType"), + (False, True, False, "TestType"), + (False, True, True, "TestType"), + (True, False, False, "Union[Unset, None, TestType]"), + (True, False, True, "TestType"), + (True, True, False, "Optional[TestType]"), + (True, True, True, "TestType"), ], ) - def test_get_type_string(self, mocker, query_parameter, nullable, required, no_optional, expected): + def test_get_type_string(self, mocker, nullable, required, no_optional, expected): from openapi_python_client.parser.properties import Property mocker.patch.object(Property, "_type_string", "TestType") p = Property(name="test", required=required, default=None, nullable=nullable) - assert p.get_type_string(no_optional=no_optional, query_parameter=query_parameter) == expected + assert p.get_type_string(no_optional=no_optional) == expected @pytest.mark.parametrize( - "query_parameter,default,required,expected", + "default,required,expected", [ - (False, None, False, "test: Union[Unset, TestType] = UNSET"), - (False, None, True, "test: TestType"), - (False, "Test", False, "test: Union[Unset, TestType] = Test"), - (False, "Test", True, "test: TestType = Test"), - (True, None, False, "test: Union[Unset, None, TestType] = UNSET"), - (True, None, True, "test: TestType"), - (True, "Test", False, "test: Union[Unset, None, TestType] = Test"), - (True, "Test", True, "test: TestType = Test"), + (None, False, "test: Union[Unset, TestType] = UNSET"), + (None, True, "test: TestType"), + ("Test", False, "test: Union[Unset, TestType] = Test"), + ("Test", True, "test: TestType = Test"), ], ) - def test_to_string(self, mocker, query_parameter, default, required, expected): + def test_to_string(self, mocker, default, required, expected): from openapi_python_client.parser.properties import Property name = "test" mocker.patch.object(Property, "_type_string", "TestType") p = Property(name=name, required=required, default=default, nullable=False) - assert p.to_string(query_parameter=query_parameter) == expected + assert p.to_string() == expected def test_get_imports(self): from openapi_python_client.parser.properties import Property @@ -252,27 +240,19 @@ def test_get_type_imports(self, mocker): class TestUnionProperty: @pytest.mark.parametrize( - "query_parameter,nullable,required,no_optional,expected", + "nullable,required,no_optional,expected", [ - (False, False, False, False, "Union[Unset, inner_type_string_1, inner_type_string_2]"), - (False, False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), - (False, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), - (False, False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), - (False, True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), - (False, True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), - (False, True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), - (False, True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), - (True, False, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), - (True, False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), - (True, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), - (True, False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), - (True, True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), - (True, True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), - (True, True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), - (True, True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, False, False, "Union[Unset, inner_type_string_1, inner_type_string_2]"), + (False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), + (True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), ], ) - def test_get_type_string(self, mocker, query_parameter, nullable, required, no_optional, expected): + def test_get_type_string(self, mocker, nullable, required, no_optional, expected): from openapi_python_client.parser.properties import UnionProperty inner_property_1 = mocker.MagicMock() @@ -286,7 +266,7 @@ def test_get_type_string(self, mocker, query_parameter, nullable, required, no_o inner_properties=[inner_property_1, inner_property_2], nullable=nullable, ) - assert p.get_type_string(query_parameter=query_parameter, no_optional=no_optional) == expected + assert p.get_type_string(no_optional=no_optional) == expected def test_get_imports(self, mocker): from openapi_python_client.parser.properties import UnionProperty diff --git a/tests/test_parser/test_properties/test_model_property.py b/tests/test_parser/test_properties/test_model_property.py index 1024ef179..410112666 100644 --- a/tests/test_parser/test_properties/test_model_property.py +++ b/tests/test_parser/test_properties/test_model_property.py @@ -4,9 +4,9 @@ @pytest.mark.parametrize( "no_optional,nullable,required,expected", [ - (False, False, False, "Union[MyClass, Unset]"), + (False, False, False, "Union[Unset, MyClass]"), (False, False, True, "MyClass"), - (False, True, False, "Union[Optional[MyClass], Unset]"), + (False, True, False, "Union[Unset, None, MyClass]"), (False, True, True, "Optional[MyClass]"), (True, False, False, "MyClass"), (True, False, True, "MyClass"), From 9ec739493631784560ba470cd6b371a933df5b12 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 9 Feb 2021 18:06:25 -0500 Subject: [PATCH 05/17] Fix tests --- .../custom_e2e/models/model_with_union_property.py | 8 ++++---- .../models/model_with_union_property.py | 8 ++++---- .../templates/property_templates/date_property.py.jinja | 2 +- .../property_templates/datetime_property.py.jinja | 2 +- .../templates/property_templates/enum_property.py.jinja | 6 +++--- .../templates/property_templates/file_property.py.jinja | 2 +- .../templates/property_templates/list_property.py.jinja | 2 +- .../templates/property_templates/model_property.py.jinja | 2 +- .../templates/property_templates/none_property.py.jinja | 2 +- .../templates/property_templates/union_property.py.jinja | 6 +++--- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index 9321920b0..296b43905 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -45,21 +45,21 @@ def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIn if isinstance(data, Unset): return data try: - if not (isinstance(data, int) or isinstance(data, str)): + if not isinstance(data, int): raise TypeError() a_property = UNSET _a_property = data - if _a_property is not None and _a_property is not UNSET: + if _a_property is not None and _a_property is not UNSET: # type: ignore a_property = AnEnum(_a_property) return a_property except: # noqa: E722 pass - if not (isinstance(data, int) or isinstance(data, str)): + if not isinstance(data, int): raise TypeError() a_property = UNSET _a_property = data - if _a_property is not None and _a_property is not UNSET: + if _a_property is not None and _a_property is not UNSET: # type: ignore a_property = AnIntEnum(_a_property) return a_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index 9321920b0..296b43905 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -45,21 +45,21 @@ def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIn if isinstance(data, Unset): return data try: - if not (isinstance(data, int) or isinstance(data, str)): + if not isinstance(data, int): raise TypeError() a_property = UNSET _a_property = data - if _a_property is not None and _a_property is not UNSET: + if _a_property is not None and _a_property is not UNSET: # type: ignore a_property = AnEnum(_a_property) return a_property except: # noqa: E722 pass - if not (isinstance(data, int) or isinstance(data, str)): + if not isinstance(data, int): raise TypeError() a_property = UNSET _a_property = data - if _a_property is not None and _a_property is not UNSET: + if _a_property is not None and _a_property is not UNSET: # type: ignore a_property = AnIntEnum(_a_property) return a_property diff --git a/openapi_python_client/templates/property_templates/date_property.py.jinja b/openapi_python_client/templates/property_templates/date_property.py.jinja index c8a65a714..8cf4f00bc 100644 --- a/openapi_python_client/templates/property_templates/date_property.py.jinja +++ b/openapi_python_client/templates/property_templates/date_property.py.jinja @@ -9,7 +9,7 @@ if _{{ property.python_name }} is not None: {% endif %} {% endmacro %} -{% macro check_type_for_construct(source) %}isinstance({{ source }}, str){% endmacro %} +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, str){% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} diff --git a/openapi_python_client/templates/property_templates/datetime_property.py.jinja b/openapi_python_client/templates/property_templates/datetime_property.py.jinja index 696bc7892..92cb0cb2e 100644 --- a/openapi_python_client/templates/property_templates/datetime_property.py.jinja +++ b/openapi_python_client/templates/property_templates/datetime_property.py.jinja @@ -14,7 +14,7 @@ if _{{ property.python_name }} is not None: {% endif %} {% endmacro %} -{% macro check_type_for_construct(source) %}isinstance({{ source }}, str){% endmacro %} +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, str){% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} diff --git a/openapi_python_client/templates/property_templates/enum_property.py.jinja b/openapi_python_client/templates/property_templates/enum_property.py.jinja index c8db9ad2e..7aae8214b 100644 --- a/openapi_python_client/templates/property_templates/enum_property.py.jinja +++ b/openapi_python_client/templates/property_templates/enum_property.py.jinja @@ -1,15 +1,15 @@ {% macro construct(property, source, initial_value="None") %} -{% if property.required %} +{% if property.required and not property.nullable %} {{ property.python_name }} = {{ property.reference.class_name }}({{ source }}) {% else %} {{ property.python_name }} = {{ initial_value }} _{{ property.python_name }} = {{ source }} -if _{{ property.python_name }} is not None and _{{ property.python_name }} is not UNSET: +if _{{ property.python_name }} is not None and _{{ property.python_name }} is not UNSET: # type: ignore {{ property.python_name }} = {{ property.reference.class_name }}(_{{ property.python_name }}) {% endif %} {% endmacro %} -{% macro check_type_for_construct(source) %}(isinstance({{ source }}, int) or isinstance({{ source }}, str)){% endmacro %} +{% macro check_type_for_construct(property, source) %}{% if property.value_type == str %}isinstance({{ source }}, str){% else %}isinstance({{ source }}, int){% endif %}{% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} diff --git a/openapi_python_client/templates/property_templates/file_property.py.jinja b/openapi_python_client/templates/property_templates/file_property.py.jinja index 81c846629..a6c321765 100644 --- a/openapi_python_client/templates/property_templates/file_property.py.jinja +++ b/openapi_python_client/templates/property_templates/file_property.py.jinja @@ -4,7 +4,7 @@ ) {% endmacro %} -{% macro check_type_for_construct(source) %}isinstance({{ source }}, bytes){% endmacro %} +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, bytes){% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} diff --git a/openapi_python_client/templates/property_templates/list_property.py.jinja b/openapi_python_client/templates/property_templates/list_property.py.jinja index 61f148d21..60ad68663 100644 --- a/openapi_python_client/templates/property_templates/list_property.py.jinja +++ b/openapi_python_client/templates/property_templates/list_property.py.jinja @@ -31,7 +31,7 @@ for {{ inner_source }} in {{ source }}: {% endif %} {% endmacro %} -{% macro check_type_for_construct(source) %}isinstance({{ source }}, list){% endmacro %} +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, list){% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% set inner_property = property.inner_property %} diff --git a/openapi_python_client/templates/property_templates/model_property.py.jinja b/openapi_python_client/templates/property_templates/model_property.py.jinja index 68f4d1266..b4fdf6528 100644 --- a/openapi_python_client/templates/property_templates/model_property.py.jinja +++ b/openapi_python_client/templates/property_templates/model_property.py.jinja @@ -15,7 +15,7 @@ if {% if property.nullable %}_{{ property.python_name }} is not None{% endif %}{ {% endif %} {% endmacro %} -{% macro check_type_for_construct(source) %}isinstance({{ source }}, dict){% endmacro %} +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, dict){% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} diff --git a/openapi_python_client/templates/property_templates/none_property.py.jinja b/openapi_python_client/templates/property_templates/none_property.py.jinja index 235530c8b..adc6b1524 100644 --- a/openapi_python_client/templates/property_templates/none_property.py.jinja +++ b/openapi_python_client/templates/property_templates/none_property.py.jinja @@ -2,7 +2,7 @@ {{ property.python_name }} = {{ initial_value }} {% endmacro %} -{% macro check_type_for_construct(source) %}{{ source }} is None{% endmacro %} +{% macro check_type_for_construct(property, source) %}{{ source }} is None{% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {{ destination }} = None diff --git a/openapi_python_client/templates/property_templates/union_property.py.jinja b/openapi_python_client/templates/property_templates/union_property.py.jinja index 051c7c460..14a7715bd 100644 --- a/openapi_python_client/templates/property_templates/union_property.py.jinja +++ b/openapi_python_client/templates/property_templates/union_property.py.jinja @@ -13,7 +13,7 @@ def _parse_{{ property.python_name }}(data: {{ property.get_type_string(json=Tru {% if not loop.last or property.has_properties_without_templates %} try: {% from "property_templates/" + inner_property.template import construct, check_type_for_construct %} - if not {{ check_type_for_construct("data") }}: + if not {{ check_type_for_construct(inner_property, "data") }}: raise TypeError() {{ construct(inner_property, "data", initial_value="UNSET") | indent(8) }} return {{ property.python_name }} @@ -21,7 +21,7 @@ def _parse_{{ property.python_name }}(data: {{ property.get_type_string(json=Tru pass {% else %}{# Don't do try/except for the last one #} {% from "property_templates/" + inner_property.template import construct, check_type_for_construct %} - if not {{ check_type_for_construct("data") }}: + if not {{ check_type_for_construct(inner_property, "data") }}: raise TypeError() {{ construct(inner_property, "data", initial_value="UNSET") | indent(4) }} return {{ property.python_name }} @@ -36,7 +36,7 @@ def _parse_{{ property.python_name }}(data: {{ property.get_type_string(json=Tru {% endmacro %} {# For now we assume there will be no unions of unions #} -{% macro check_type_for_construct(source) %}True{% endmacro %} +{% macro check_type_for_construct(property, source) %}True{% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% if not property.required or property.nullable %} From db33752b91ef063f4d0a6732e1233bfc59ab3480 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 9 Feb 2021 18:14:10 -0500 Subject: [PATCH 06/17] Remove unnecessary check --- .../golden-record-custom/custom_e2e/models/a_model.py | 2 -- .../golden-record/my_test_api_client/models/a_model.py | 2 -- .../templates/property_templates/union_property.py.jinja | 2 ++ 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index cf9280cab..0192aacd6 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -77,8 +77,6 @@ def to_dict(self) -> Dict[str, Any]: not_required_nullable = self.not_required_nullable not_required_not_nullable = self.not_required_not_nullable nullable_one_of_models: Union[None, Dict[str, Any]] - if isinstance(self.nullable_one_of_models, Unset): - nullable_one_of_models = UNSET if self.nullable_one_of_models is None: nullable_one_of_models = None elif isinstance(self.nullable_one_of_models, FreeFormModel): diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index cf9280cab..0192aacd6 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -77,8 +77,6 @@ def to_dict(self) -> Dict[str, Any]: not_required_nullable = self.not_required_nullable not_required_not_nullable = self.not_required_not_nullable nullable_one_of_models: Union[None, Dict[str, Any]] - if isinstance(self.nullable_one_of_models, Unset): - nullable_one_of_models = UNSET if self.nullable_one_of_models is None: nullable_one_of_models = None elif isinstance(self.nullable_one_of_models, FreeFormModel): diff --git a/openapi_python_client/templates/property_templates/union_property.py.jinja b/openapi_python_client/templates/property_templates/union_property.py.jinja index 14a7715bd..3fb6a0967 100644 --- a/openapi_python_client/templates/property_templates/union_property.py.jinja +++ b/openapi_python_client/templates/property_templates/union_property.py.jinja @@ -42,9 +42,11 @@ def _parse_{{ property.python_name }}(data: {{ property.get_type_string(json=Tru {% if not property.required or property.nullable %} {{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} +{% if not property.required %} if isinstance({{ source }}, Unset): {{ destination }} = UNSET {% endif %} +{% endif %} {% if property.nullable %} {% if property.required %} if {{ source }} is None: From 49185f03046976134cdf53b7da6ac49885cb20d3 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 9 Feb 2021 18:20:04 -0500 Subject: [PATCH 07/17] Address union of one type --- .../custom_e2e/models/a_model.py | 4 ++-- .../my_test_api_client/models/a_model.py | 4 ++-- openapi_python_client/parser/properties/__init__.py | 12 +++++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index 0192aacd6..d49f4c0dc 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -167,7 +167,7 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datetime.date]: + def _parse_a_camel_date_time(data: str) -> Union[datetime.datetime, datetime.date]: a_camel_date_time: Union[datetime.datetime, datetime.date] try: if not isinstance(data, str): @@ -189,7 +189,7 @@ def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datet required_not_nullable = d.pop("required_not_nullable") - def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, ModelWithUnionProperty]: + def _parse_one_of_models(data: Dict[str, Any]) -> Union[FreeFormModel, ModelWithUnionProperty]: one_of_models: Union[FreeFormModel, ModelWithUnionProperty] try: if not isinstance(data, dict): diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 0192aacd6..d49f4c0dc 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -167,7 +167,7 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datetime.date]: + def _parse_a_camel_date_time(data: str) -> Union[datetime.datetime, datetime.date]: a_camel_date_time: Union[datetime.datetime, datetime.date] try: if not isinstance(data, str): @@ -189,7 +189,7 @@ def _parse_a_camel_date_time(data: Union[str]) -> Union[datetime.datetime, datet required_not_nullable = d.pop("required_not_nullable") - def _parse_one_of_models(data: Union[Dict[str, Any]]) -> Union[FreeFormModel, ModelWithUnionProperty]: + def _parse_one_of_models(data: Dict[str, Any]) -> Union[FreeFormModel, ModelWithUnionProperty]: one_of_models: Union[FreeFormModel, ModelWithUnionProperty] try: if not isinstance(data, dict): diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index dfe778e71..aca0313a8 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -174,11 +174,17 @@ def _get_inner_type_strings(self, json: bool = False) -> List[str]: unique_inner_types = list(dict.fromkeys(inner_types)) return unique_inner_types + def _get_type_string_from_inner_type_strings(self, inner_types: List[str]) -> str: + if len(inner_types) == 1: + return inner_types[0] + else: + return f"Union[{', '.join(inner_types)}]" + def get_base_type_string(self) -> str: - return f"Union[{', '.join(self._get_inner_type_strings(json=False))}]" + return self._get_type_string_from_inner_type_strings(self._get_inner_type_strings(json=False)) def get_base_json_type_string(self) -> str: - return f"Union[{', '.join(self._get_inner_type_strings(json=True))}]" + return self._get_type_string_from_inner_type_strings(self._get_inner_type_strings(json=True)) def get_type_strings_in_union(self, no_optional: bool = False, json: bool = False) -> List[str]: type_strings = self._get_inner_type_strings(json=json) @@ -199,7 +205,7 @@ def get_type_string(self, no_optional: bool = False, json: bool = False) -> str: nested union types. """ type_strings_in_union = self.get_type_strings_in_union(no_optional=no_optional, json=json) - return f"Union[{', '.join(type_strings_in_union)}]" + return self._get_type_string_from_inner_type_strings(type_strings_in_union) def get_imports(self, *, prefix: str) -> Set[str]: """ From b71f718e3cb32583ea10affe7f819702281c2dca Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 10 Feb 2021 11:19:30 -0500 Subject: [PATCH 08/17] Fix union of inline models --- .../custom_e2e/models/__init__.py | 5 +- .../custom_e2e/models/a_model.py | 4 +- .../models/model_with_any_json_properties.py | 26 ++++--- ...n_properties_additional_property_item0.py} | 10 +-- .../models/model_with_union_property.py | 14 ++-- .../model_with_union_property_inlined.py | 68 +++++++++++++++++++ ...with_union_property_inlined_fruit_item0.py | 54 +++++++++++++++ ...with_union_property_inlined_fruit_item1.py | 54 +++++++++++++++ .../my_test_api_client/models/__init__.py | 5 +- .../my_test_api_client/models/a_model.py | 4 +- .../models/model_with_any_json_properties.py | 26 ++++--- ...n_properties_additional_property_item0.py} | 10 +-- .../models/model_with_union_property.py | 14 ++-- .../model_with_union_property_inlined.py | 68 +++++++++++++++++++ ...with_union_property_inlined_fruit_item0.py | 54 +++++++++++++++ ...with_union_property_inlined_fruit_item1.py | 54 +++++++++++++++ end_to_end_tests/openapi.json | 23 +++++++ .../parser/properties/__init__.py | 4 +- 18 files changed, 443 insertions(+), 54 deletions(-) rename end_to_end_tests/golden-record-custom/custom_e2e/models/{model_with_any_json_properties_additional_property.py => model_with_any_json_properties_additional_property_item0.py} (82%) create mode 100644 end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py create mode 100644 end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py create mode 100644 end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item1.py rename end_to_end_tests/golden-record/my_test_api_client/models/{model_with_any_json_properties_additional_property.py => model_with_any_json_properties_additional_property_item0.py} (82%) create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item1.py diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py index 6f5ac7423..391bca440 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py @@ -17,10 +17,13 @@ ) from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed from .model_with_any_json_properties import ModelWithAnyJsonProperties -from .model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty +from .model_with_any_json_properties_additional_property_item0 import ModelWithAnyJsonPropertiesAdditionalPropertyItem0 from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder from .model_with_union_property import ModelWithUnionProperty +from .model_with_union_property_inlined import ModelWithUnionPropertyInlined +from .model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 +from .model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 from .test_inline_objects_json_body import TestInlineObjectsJsonBody from .test_inline_objects_response_200 import TestInlineObjectsResponse_200 from .validation_error import ValidationError diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index 1533aaf86..ef383ae6f 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -113,12 +113,12 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat data = None if isinstance(data, Unset) else data a_camel_date_time: Union[datetime.datetime, datetime.date] try: - a_camel_date_time = isoparse(data) + isoparse(data) return a_camel_date_time except: # noqa: E722 pass - a_camel_date_time = isoparse(data).date() + isoparse(data).date() return a_camel_date_time diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py index 7696b9753..f411ddea8 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py @@ -2,7 +2,9 @@ import attr -from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty +from ..models.model_with_any_json_properties_additional_property_item0 import ( + ModelWithAnyJsonPropertiesAdditionalPropertyItem0, +) from ..types import Unset T = TypeVar("T", bound="ModelWithAnyJsonProperties") @@ -13,14 +15,14 @@ class ModelWithAnyJsonProperties: """ """ additional_properties: Dict[ - str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + str, Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool] ] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): - if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalProperty): + if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyItem0): field_dict[prop_name] = prop.to_dict() elif isinstance(prop, list): @@ -43,24 +45,26 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: Any, - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool]: data = None if isinstance(data, Unset) else data additional_property: Union[ - ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool + ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool ] try: - additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data) + ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) return additional_property except: # noqa: E722 pass try: - additional_property = cast(List[str], data) + cast(List[str], data) return additional_property except: # noqa: E722 pass - return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data) + return cast( + Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool], data + ) additional_property = _parse_additional_property(prop_dict) @@ -75,11 +79,13 @@ def additional_keys(self) -> List[str]: def __getitem__( self, key: str - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool]: return self.additional_properties[key] def __setitem__( - self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + self, + key: str, + value: Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool], ) -> None: self.additional_properties[key] = value diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_item0.py similarity index 82% rename from end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property.py rename to end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_item0.py index 69aa84641..3a8334ae4 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_item0.py @@ -2,11 +2,11 @@ import attr -T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalProperty") +T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyItem0") @attr.s(auto_attribs=True) -class ModelWithAnyJsonPropertiesAdditionalProperty: +class ModelWithAnyJsonPropertiesAdditionalPropertyItem0: """ """ additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) @@ -22,10 +22,10 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - model_with_any_json_properties_additional_property = cls() + model_with_any_json_properties_additional_property_item0 = cls() - model_with_any_json_properties_additional_property.additional_properties = d - return model_with_any_json_properties_additional_property + model_with_any_json_properties_additional_property_item0.additional_properties = d + return model_with_any_json_properties_additional_property_item0 @property def additional_keys(self) -> List[str]: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index ed8deec19..bf6b357b2 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -44,18 +44,16 @@ def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: data = None if isinstance(data, Unset) else data a_property: Union[Unset, AnEnum, AnIntEnum] try: - a_property = UNSET - _a_property = data - if _a_property is not None and _a_property is not UNSET: - a_property = AnEnum(_a_property) + _a_property_item0 = data + if _a_property_item0 is not None and _a_property_item0 is not UNSET: + AnEnum(_a_property_item0) return a_property except: # noqa: E722 pass - a_property = UNSET - _a_property = data - if _a_property is not None and _a_property is not UNSET: - a_property = AnIntEnum(_a_property) + _a_property_item1 = data + if _a_property_item1 is not None and _a_property_item1 is not UNSET: + AnIntEnum(_a_property_item1) return a_property diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py new file mode 100644 index 000000000..e9c90b4d2 --- /dev/null +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py @@ -0,0 +1,68 @@ +from typing import Any, Dict, Type, TypeVar, Union, cast + +import attr + +from ..models.model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 +from ..models.model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithUnionPropertyInlined") + + +@attr.s(auto_attribs=True) +class ModelWithUnionPropertyInlined: + """ """ + + fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] = UNSET + + def to_dict(self) -> Dict[str, Any]: + fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] + if isinstance(self.fruit, Unset): + fruit = UNSET + elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitItem0): + fruit = UNSET + if not isinstance(self.fruit, Unset): + fruit = self.fruit.to_dict() + + else: + fruit = UNSET + if not isinstance(self.fruit, Unset): + fruit = self.fruit.to_dict() + + field_dict: Dict[str, Any] = {} + field_dict.update({}) + if fruit is not UNSET: + field_dict["fruit"] = fruit + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + + def _parse_fruit( + data: Any, + ) -> Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1]: + data = None if isinstance(data, Unset) else data + fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] + try: + _fruit_item0 = data + if not isinstance(_fruit_item0, Unset): + ModelWithUnionPropertyInlinedFruitItem0.from_dict(cast(Dict[str, Any], _fruit_item0)) + + return fruit + except: # noqa: E722 + pass + _fruit_item1 = data + if not isinstance(_fruit_item1, Unset): + ModelWithUnionPropertyInlinedFruitItem1.from_dict(cast(Dict[str, Any], _fruit_item1)) + + return fruit + + fruit = _parse_fruit(d.pop("fruit", UNSET)) + + model_with_union_property_inlined = cls( + fruit=fruit, + ) + + return model_with_union_property_inlined diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py new file mode 100644 index 000000000..ab82f5f01 --- /dev/null +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py @@ -0,0 +1,54 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +import attr + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem0") + + +@attr.s(auto_attribs=True) +class ModelWithUnionPropertyInlinedFruitItem0: + """ """ + + apples: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + apples = self.apples + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if apples is not UNSET: + field_dict["apples"] = apples + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + apples = d.pop("apples", UNSET) + + model_with_union_property_inlined_fruit_item0 = cls( + apples=apples, + ) + + model_with_union_property_inlined_fruit_item0.additional_properties = d + return model_with_union_property_inlined_fruit_item0 + + @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-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item1.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item1.py new file mode 100644 index 000000000..df2f1c7bd --- /dev/null +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item1.py @@ -0,0 +1,54 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +import attr + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem1") + + +@attr.s(auto_attribs=True) +class ModelWithUnionPropertyInlinedFruitItem1: + """ """ + + bananas: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + bananas = self.bananas + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if bananas is not UNSET: + field_dict["bananas"] = bananas + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + bananas = d.pop("bananas", UNSET) + + model_with_union_property_inlined_fruit_item1 = cls( + bananas=bananas, + ) + + model_with_union_property_inlined_fruit_item1.additional_properties = d + return model_with_union_property_inlined_fruit_item1 + + @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/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py index 6f5ac7423..391bca440 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 @@ -17,10 +17,13 @@ ) from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed from .model_with_any_json_properties import ModelWithAnyJsonProperties -from .model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty +from .model_with_any_json_properties_additional_property_item0 import ModelWithAnyJsonPropertiesAdditionalPropertyItem0 from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder from .model_with_union_property import ModelWithUnionProperty +from .model_with_union_property_inlined import ModelWithUnionPropertyInlined +from .model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 +from .model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 from .test_inline_objects_json_body import TestInlineObjectsJsonBody from .test_inline_objects_response_200 import TestInlineObjectsResponse_200 from .validation_error import ValidationError diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 1533aaf86..ef383ae6f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -113,12 +113,12 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat data = None if isinstance(data, Unset) else data a_camel_date_time: Union[datetime.datetime, datetime.date] try: - a_camel_date_time = isoparse(data) + isoparse(data) return a_camel_date_time except: # noqa: E722 pass - a_camel_date_time = isoparse(data).date() + isoparse(data).date() return a_camel_date_time 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 7696b9753..f411ddea8 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 @@ -2,7 +2,9 @@ import attr -from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty +from ..models.model_with_any_json_properties_additional_property_item0 import ( + ModelWithAnyJsonPropertiesAdditionalPropertyItem0, +) from ..types import Unset T = TypeVar("T", bound="ModelWithAnyJsonProperties") @@ -13,14 +15,14 @@ class ModelWithAnyJsonProperties: """ """ additional_properties: Dict[ - str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + str, Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool] ] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): - if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalProperty): + if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyItem0): field_dict[prop_name] = prop.to_dict() elif isinstance(prop, list): @@ -43,24 +45,26 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: Any, - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool]: data = None if isinstance(data, Unset) else data additional_property: Union[ - ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool + ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool ] try: - additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data) + ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) return additional_property except: # noqa: E722 pass try: - additional_property = cast(List[str], data) + cast(List[str], data) return additional_property except: # noqa: E722 pass - return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data) + return cast( + Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool], data + ) additional_property = _parse_additional_property(prop_dict) @@ -75,11 +79,13 @@ def additional_keys(self) -> List[str]: def __getitem__( self, key: str - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool]: return self.additional_properties[key] def __setitem__( - self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + self, + key: str, + value: Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool], ) -> None: self.additional_properties[key] = value diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_item0.py similarity index 82% rename from end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py rename to end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_item0.py index 69aa84641..3a8334ae4 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_item0.py @@ -2,11 +2,11 @@ import attr -T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalProperty") +T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyItem0") @attr.s(auto_attribs=True) -class ModelWithAnyJsonPropertiesAdditionalProperty: +class ModelWithAnyJsonPropertiesAdditionalPropertyItem0: """ """ additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) @@ -22,10 +22,10 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - model_with_any_json_properties_additional_property = cls() + model_with_any_json_properties_additional_property_item0 = cls() - model_with_any_json_properties_additional_property.additional_properties = d - return model_with_any_json_properties_additional_property + model_with_any_json_properties_additional_property_item0.additional_properties = d + return model_with_any_json_properties_additional_property_item0 @property def additional_keys(self) -> List[str]: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index ed8deec19..bf6b357b2 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -44,18 +44,16 @@ def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: data = None if isinstance(data, Unset) else data a_property: Union[Unset, AnEnum, AnIntEnum] try: - a_property = UNSET - _a_property = data - if _a_property is not None and _a_property is not UNSET: - a_property = AnEnum(_a_property) + _a_property_item0 = data + if _a_property_item0 is not None and _a_property_item0 is not UNSET: + AnEnum(_a_property_item0) return a_property except: # noqa: E722 pass - a_property = UNSET - _a_property = data - if _a_property is not None and _a_property is not UNSET: - a_property = AnIntEnum(_a_property) + _a_property_item1 = data + if _a_property_item1 is not None and _a_property_item1 is not UNSET: + AnIntEnum(_a_property_item1) return a_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py new file mode 100644 index 000000000..e9c90b4d2 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py @@ -0,0 +1,68 @@ +from typing import Any, Dict, Type, TypeVar, Union, cast + +import attr + +from ..models.model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 +from ..models.model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithUnionPropertyInlined") + + +@attr.s(auto_attribs=True) +class ModelWithUnionPropertyInlined: + """ """ + + fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] = UNSET + + def to_dict(self) -> Dict[str, Any]: + fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] + if isinstance(self.fruit, Unset): + fruit = UNSET + elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitItem0): + fruit = UNSET + if not isinstance(self.fruit, Unset): + fruit = self.fruit.to_dict() + + else: + fruit = UNSET + if not isinstance(self.fruit, Unset): + fruit = self.fruit.to_dict() + + field_dict: Dict[str, Any] = {} + field_dict.update({}) + if fruit is not UNSET: + field_dict["fruit"] = fruit + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + + def _parse_fruit( + data: Any, + ) -> Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1]: + data = None if isinstance(data, Unset) else data + fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] + try: + _fruit_item0 = data + if not isinstance(_fruit_item0, Unset): + ModelWithUnionPropertyInlinedFruitItem0.from_dict(cast(Dict[str, Any], _fruit_item0)) + + return fruit + except: # noqa: E722 + pass + _fruit_item1 = data + if not isinstance(_fruit_item1, Unset): + ModelWithUnionPropertyInlinedFruitItem1.from_dict(cast(Dict[str, Any], _fruit_item1)) + + return fruit + + fruit = _parse_fruit(d.pop("fruit", UNSET)) + + model_with_union_property_inlined = cls( + fruit=fruit, + ) + + return model_with_union_property_inlined diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py new file mode 100644 index 000000000..ab82f5f01 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py @@ -0,0 +1,54 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +import attr + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem0") + + +@attr.s(auto_attribs=True) +class ModelWithUnionPropertyInlinedFruitItem0: + """ """ + + apples: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + apples = self.apples + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if apples is not UNSET: + field_dict["apples"] = apples + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + apples = d.pop("apples", UNSET) + + model_with_union_property_inlined_fruit_item0 = cls( + apples=apples, + ) + + model_with_union_property_inlined_fruit_item0.additional_properties = d + return model_with_union_property_inlined_fruit_item0 + + @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_union_property_inlined_fruit_item1.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item1.py new file mode 100644 index 000000000..df2f1c7bd --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item1.py @@ -0,0 +1,54 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +import attr + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem1") + + +@attr.s(auto_attribs=True) +class ModelWithUnionPropertyInlinedFruitItem1: + """ """ + + bananas: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + bananas = self.bananas + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if bananas is not UNSET: + field_dict["bananas"] = bananas + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + bananas = d.pop("bananas", UNSET) + + model_with_union_property_inlined_fruit_item1 = cls( + bananas=bananas, + ) + + model_with_union_property_inlined_fruit_item1.additional_properties = d + return model_with_union_property_inlined_fruit_item1 + + @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/openapi.json b/end_to_end_tests/openapi.json index 196538f19..46c631533 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -806,6 +806,29 @@ }, "additionalProperties": false }, + "ModelWithUnionPropertyInlined": { + "title": "ModelWithUnionPropertyInlined", + "type": "object", + "properties": { + "fruit": { + "oneOf": [ + { + "type": "object", + "properties": { + "apples": {"type": "string"} + } + }, + { + "type": "object", + "properties": { + "bananas": {"type": "string"} + } + } + ] + } + }, + "additionalProperties": false + }, "FreeFormModel": { "title": "FreeFormModel", "type": "object" diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 2ea75a569..6f573bf8d 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -382,9 +382,9 @@ def build_union_property( *, data: oai.Schema, name: str, required: bool, schemas: Schemas, parent_name: str ) -> Tuple[Union[UnionProperty, PropertyError], Schemas]: sub_properties: List[Property] = [] - for sub_prop_data in chain(data.anyOf, data.oneOf): + for i, sub_prop_data in enumerate(chain(data.anyOf, data.oneOf)): sub_prop, schemas = property_from_data( - name=name, required=required, data=sub_prop_data, schemas=schemas, parent_name=parent_name + name=f"{name}_item{i}", required=required, data=sub_prop_data, schemas=schemas, parent_name=parent_name ) if isinstance(sub_prop, PropertyError): return PropertyError(detail=f"Invalid property in union {name}", data=sub_prop_data), schemas From c25156057a29546597f8c8c047ab794939e15651 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 10 Feb 2021 11:34:52 -0500 Subject: [PATCH 09/17] Fix union --- .../custom_e2e/models/a_model.py | 11 ++++++----- .../models/model_with_any_json_properties.py | 13 ++++++------- .../custom_e2e/models/model_with_union_property.py | 13 ++++++++----- .../models/model_with_union_property_inlined.py | 13 ++++++++----- .../my_test_api_client/models/a_model.py | 11 ++++++----- .../models/model_with_any_json_properties.py | 13 ++++++------- .../models/model_with_union_property.py | 13 ++++++++----- .../models/model_with_union_property_inlined.py | 13 ++++++++----- .../property_templates/union_property.py.jinja | 7 ++++--- 9 files changed, 60 insertions(+), 47 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index ef383ae6f..5a63f52e3 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -111,16 +111,17 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.date]: data = None if isinstance(data, Unset) else data - a_camel_date_time: Union[datetime.datetime, datetime.date] try: - isoparse(data) + a_camel_date_time_item0: datetime.datetime + a_camel_date_time_item0 = isoparse(data) - return a_camel_date_time + return a_camel_date_time_item0 except: # noqa: E722 pass - isoparse(data).date() + a_camel_date_time_item1: datetime.date + a_camel_date_time_item1 = isoparse(data).date() - return a_camel_date_time + return a_camel_date_time_item1 a_camel_date_time = _parse_a_camel_date_time(d.pop("aCamelDateTime")) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py index f411ddea8..0cba269f2 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py @@ -47,19 +47,18 @@ def _parse_additional_property( data: Any, ) -> Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool]: data = None if isinstance(data, Unset) else data - additional_property: Union[ - ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool - ] try: - ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) + additional_property_item0: ModelWithAnyJsonPropertiesAdditionalPropertyItem0 + additional_property_item0 = ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) - return additional_property + return additional_property_item0 except: # noqa: E722 pass try: - cast(List[str], data) + additional_property_item1: List[str] + additional_property_item1 = cast(List[str], data) - return additional_property + return additional_property_item1 except: # noqa: E722 pass return cast( diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index bf6b357b2..a478ee462 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -42,20 +42,23 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: data = None if isinstance(data, Unset) else data - a_property: Union[Unset, AnEnum, AnIntEnum] try: + a_property_item0: Union[Unset, AnEnum] + a_property_item0 = UNSET _a_property_item0 = data if _a_property_item0 is not None and _a_property_item0 is not UNSET: - AnEnum(_a_property_item0) + a_property_item0 = AnEnum(_a_property_item0) - return a_property + return a_property_item0 except: # noqa: E722 pass + a_property_item1: Union[Unset, AnIntEnum] + a_property_item1 = UNSET _a_property_item1 = data if _a_property_item1 is not None and _a_property_item1 is not UNSET: - AnIntEnum(_a_property_item1) + a_property_item1 = AnIntEnum(_a_property_item1) - return a_property + return a_property_item1 a_property = _parse_a_property(d.pop("a_property", UNSET)) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py index e9c90b4d2..7c7ff77bc 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py @@ -44,20 +44,23 @@ def _parse_fruit( data: Any, ) -> Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1]: data = None if isinstance(data, Unset) else data - fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] try: + fruit_item0: Union[ModelWithUnionPropertyInlinedFruitItem0, Unset] + fruit_item0 = UNSET _fruit_item0 = data if not isinstance(_fruit_item0, Unset): - ModelWithUnionPropertyInlinedFruitItem0.from_dict(cast(Dict[str, Any], _fruit_item0)) + fruit_item0 = ModelWithUnionPropertyInlinedFruitItem0.from_dict(cast(Dict[str, Any], _fruit_item0)) - return fruit + return fruit_item0 except: # noqa: E722 pass + fruit_item1: Union[ModelWithUnionPropertyInlinedFruitItem1, Unset] + fruit_item1 = UNSET _fruit_item1 = data if not isinstance(_fruit_item1, Unset): - ModelWithUnionPropertyInlinedFruitItem1.from_dict(cast(Dict[str, Any], _fruit_item1)) + fruit_item1 = ModelWithUnionPropertyInlinedFruitItem1.from_dict(cast(Dict[str, Any], _fruit_item1)) - return fruit + return fruit_item1 fruit = _parse_fruit(d.pop("fruit", UNSET)) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index ef383ae6f..5a63f52e3 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -111,16 +111,17 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.date]: data = None if isinstance(data, Unset) else data - a_camel_date_time: Union[datetime.datetime, datetime.date] try: - isoparse(data) + a_camel_date_time_item0: datetime.datetime + a_camel_date_time_item0 = isoparse(data) - return a_camel_date_time + return a_camel_date_time_item0 except: # noqa: E722 pass - isoparse(data).date() + a_camel_date_time_item1: datetime.date + a_camel_date_time_item1 = isoparse(data).date() - return a_camel_date_time + return a_camel_date_time_item1 a_camel_date_time = _parse_a_camel_date_time(d.pop("aCamelDateTime")) 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 f411ddea8..0cba269f2 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 @@ -47,19 +47,18 @@ def _parse_additional_property( data: Any, ) -> Union[ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool]: data = None if isinstance(data, Unset) else data - additional_property: Union[ - ModelWithAnyJsonPropertiesAdditionalPropertyItem0, List[str], str, float, int, bool - ] try: - ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) + additional_property_item0: ModelWithAnyJsonPropertiesAdditionalPropertyItem0 + additional_property_item0 = ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) - return additional_property + return additional_property_item0 except: # noqa: E722 pass try: - cast(List[str], data) + additional_property_item1: List[str] + additional_property_item1 = cast(List[str], data) - return additional_property + return additional_property_item1 except: # noqa: E722 pass return cast( diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index bf6b357b2..a478ee462 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -42,20 +42,23 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: data = None if isinstance(data, Unset) else data - a_property: Union[Unset, AnEnum, AnIntEnum] try: + a_property_item0: Union[Unset, AnEnum] + a_property_item0 = UNSET _a_property_item0 = data if _a_property_item0 is not None and _a_property_item0 is not UNSET: - AnEnum(_a_property_item0) + a_property_item0 = AnEnum(_a_property_item0) - return a_property + return a_property_item0 except: # noqa: E722 pass + a_property_item1: Union[Unset, AnIntEnum] + a_property_item1 = UNSET _a_property_item1 = data if _a_property_item1 is not None and _a_property_item1 is not UNSET: - AnIntEnum(_a_property_item1) + a_property_item1 = AnIntEnum(_a_property_item1) - return a_property + return a_property_item1 a_property = _parse_a_property(d.pop("a_property", UNSET)) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py index e9c90b4d2..7c7ff77bc 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py @@ -44,20 +44,23 @@ def _parse_fruit( data: Any, ) -> Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1]: data = None if isinstance(data, Unset) else data - fruit: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1] try: + fruit_item0: Union[ModelWithUnionPropertyInlinedFruitItem0, Unset] + fruit_item0 = UNSET _fruit_item0 = data if not isinstance(_fruit_item0, Unset): - ModelWithUnionPropertyInlinedFruitItem0.from_dict(cast(Dict[str, Any], _fruit_item0)) + fruit_item0 = ModelWithUnionPropertyInlinedFruitItem0.from_dict(cast(Dict[str, Any], _fruit_item0)) - return fruit + return fruit_item0 except: # noqa: E722 pass + fruit_item1: Union[ModelWithUnionPropertyInlinedFruitItem1, Unset] + fruit_item1 = UNSET _fruit_item1 = data if not isinstance(_fruit_item1, Unset): - ModelWithUnionPropertyInlinedFruitItem1.from_dict(cast(Dict[str, Any], _fruit_item1)) + fruit_item1 = ModelWithUnionPropertyInlinedFruitItem1.from_dict(cast(Dict[str, Any], _fruit_item1)) - return fruit + return fruit_item1 fruit = _parse_fruit(d.pop("fruit", UNSET)) diff --git a/openapi_python_client/templates/property_templates/union_property.py.jinja b/openapi_python_client/templates/property_templates/union_property.py.jinja index 4c632c60a..056f6f4d1 100644 --- a/openapi_python_client/templates/property_templates/union_property.py.jinja +++ b/openapi_python_client/templates/property_templates/union_property.py.jinja @@ -1,19 +1,20 @@ {% macro construct(property, source, initial_value=None) %} def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string() }}: data = None if isinstance(data, Unset) else data - {{ property.python_name }}: {{ property.get_type_string() }} {% for inner_property in property.inner_properties_with_template() %} {% if not loop.last or property.has_properties_without_templates %} try: + {{ inner_property.python_name }}: {{ inner_property.get_type_string() }} {% from "property_templates/" + inner_property.template import construct %} {{ construct(inner_property, "data", initial_value="UNSET") | indent(8) }} - return {{ property.python_name }} + return {{ inner_property.python_name }} except: # noqa: E722 pass {% else %}{# Don't do try/except for the last one #} + {{ inner_property.python_name }}: {{ inner_property.get_type_string() }} {% from "property_templates/" + inner_property.template import construct %} {{ construct(inner_property, "data", initial_value="UNSET") | indent(4) }} - return {{ property.python_name }} + return {{ inner_property.python_name }} {% endif %} {% endfor %} {% if property.has_properties_without_templates %} From 3c536f7c2a61445e4cfffd5b095f35ed4ac211bc Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 10 Feb 2021 17:58:57 -0500 Subject: [PATCH 10/17] More tests --- .../test_parser/test_properties/test_init.py | 69 ++++++++++++------- .../test_date_property/optional_nullable.py | 2 +- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 858f6b15e..1770a70c9 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -17,24 +17,33 @@ class TestProperty: @pytest.mark.parametrize( - "nullable,required,no_optional,expected", + "nullable,required,no_optional,json,expected", [ - (False, False, False, "Union[Unset, TestType]"), - (False, False, True, "TestType"), - (False, True, False, "TestType"), - (False, True, True, "TestType"), - (True, False, False, "Union[Unset, None, TestType]"), - (True, False, True, "TestType"), - (True, True, False, "Optional[TestType]"), - (True, True, True, "TestType"), + (False, False, False, False, "Union[Unset, TestType]"), + (False, False, True, False, "TestType"), + (False, True, False, False, "TestType"), + (False, True, True, False, "TestType"), + (True, False, False, False, "Union[Unset, None, TestType]"), + (True, False, True, False, "TestType"), + (True, True, False, False, "Optional[TestType]"), + (True, True, True, False, "TestType"), + (False, False, False, True, "Union[Unset, str]"), + (False, False, True, True, "str"), + (False, True, False, True, "str"), + (False, True, True, True, "str"), + (True, False, False, True, "Union[Unset, None, str]"), + (True, False, True, True, "str"), + (True, True, False, True, "Optional[str]"), + (True, True, True, True, "str"), ], ) - def test_get_type_string(self, mocker, nullable, required, no_optional, expected): + def test_get_type_string(self, mocker, nullable, required, no_optional, json, expected): from openapi_python_client.parser.properties import Property mocker.patch.object(Property, "_type_string", "TestType") + mocker.patch.object(Property, "_json_type_string", "str") p = Property(name="test", required=required, default=None, nullable=nullable) - assert p.get_type_string(no_optional=no_optional) == expected + assert p.get_type_string(no_optional=no_optional, json=json) == expected @pytest.mark.parametrize( "default,required,expected", @@ -240,25 +249,37 @@ def test_get_type_imports(self, mocker): class TestUnionProperty: @pytest.mark.parametrize( - "nullable,required,no_optional,expected", + "nullable,required,no_optional,json,expected", [ - (False, False, False, "Union[Unset, inner_type_string_1, inner_type_string_2]"), - (False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), - (False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), - (False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), - (True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), - (True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), - (True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), - (True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, False, False, False, "Union[Unset, inner_type_string_1, inner_type_string_2]"), + (False, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, False, False, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (True, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (True, True, False, False, "Union[None, inner_type_string_1, inner_type_string_2]"), + (True, True, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (False, False, False, True, "Union[Unset, inner_json_type_string_1, inner_json_type_string_2]"), + (False, False, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), + (False, True, False, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), + (False, True, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), + (True, False, False, True, "Union[Unset, None, inner_json_type_string_1, inner_json_type_string_2]"), + (True, False, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), + (True, True, False, True, "Union[None, inner_json_type_string_1, inner_json_type_string_2]"), + (True, True, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), ], ) - def test_get_type_string(self, mocker, nullable, required, no_optional, expected): + def test_get_type_string(self, mocker, nullable, required, no_optional, json, expected): from openapi_python_client.parser.properties import UnionProperty inner_property_1 = mocker.MagicMock() - inner_property_1.get_type_string.return_value = "inner_type_string_1" + inner_property_1.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "inner_json_type_string_1" if json else "inner_type_string_1" + ) inner_property_2 = mocker.MagicMock() - inner_property_2.get_type_string.return_value = "inner_type_string_2" + inner_property_2.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "inner_json_type_string_2" if json else "inner_type_string_2" + ) p = UnionProperty( name="test", required=required, @@ -266,7 +287,7 @@ def test_get_type_string(self, mocker, nullable, required, no_optional, expected inner_properties=[inner_property_1, inner_property_2], nullable=nullable, ) - assert p.get_type_string(no_optional=no_optional) == expected + assert p.get_type_string(no_optional=no_optional, json=json) == expected def test_get_imports(self, mocker): from openapi_python_client.parser.properties import UnionProperty diff --git a/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py b/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py index bdbe148c1..0b44852df 100644 --- a/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py +++ b/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py @@ -3,7 +3,7 @@ from dateutil.parser import isoparse some_source = date(2020, 10, 12) -some_destination: Union[Unset, str] = UNSET +some_destination: Union[Unset, None, str] = UNSET if not isinstance(some_source, Unset): some_destination = some_source.isoformat() if some_source else None From 8a7273211d9d4ade746da0388aab438a0777f497 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 10 Feb 2021 18:06:32 -0500 Subject: [PATCH 11/17] Change parse annotation to object --- .../custom_e2e/models/a_model.py | 14 +++++--------- .../models/model_with_any_json_properties.py | 2 +- .../custom_e2e/models/model_with_union_property.py | 2 +- .../my_test_api_client/models/a_model.py | 14 +++++--------- .../models/model_with_any_json_properties.py | 2 +- .../models/model_with_union_property.py | 2 +- .../property_templates/union_property.py.jinja | 2 +- 7 files changed, 15 insertions(+), 23 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index 59a848dc8..16c385b55 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -174,7 +174,7 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: str) -> Union[datetime.datetime, datetime.date]: + def _parse_a_camel_date_time(data: object) -> Union[datetime.datetime, datetime.date]: a_camel_date_time: Union[datetime.datetime, datetime.date] try: if not isinstance(data, str): @@ -196,7 +196,7 @@ def _parse_a_camel_date_time(data: str) -> Union[datetime.datetime, datetime.dat required_not_nullable = d.pop("required_not_nullable") - def _parse_one_of_models(data: Dict[str, Any]) -> Union[FreeFormModel, ModelWithUnionProperty]: + def _parse_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty]: one_of_models: Union[FreeFormModel, ModelWithUnionProperty] try: if not isinstance(data, dict): @@ -246,9 +246,7 @@ def _parse_one_of_models(data: Dict[str, Any]) -> Union[FreeFormModel, ModelWith not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) - def _parse_nullable_one_of_models( - data: Union[None, Dict[str, Any]] - ) -> Union[None, FreeFormModel, ModelWithUnionProperty]: + def _parse_nullable_one_of_models(data: object) -> Union[None, FreeFormModel, ModelWithUnionProperty]: nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] if data is None: return data @@ -268,9 +266,7 @@ def _parse_nullable_one_of_models( nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) - def _parse_not_required_one_of_models( - data: Union[Unset, Dict[str, Any]] - ) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: + def _parse_not_required_one_of_models(data: object) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] if isinstance(data, Unset): return data @@ -297,7 +293,7 @@ def _parse_not_required_one_of_models( not_required_one_of_models = _parse_not_required_one_of_models(d.pop("not_required_one_of_models", UNSET)) def _parse_not_required_nullable_one_of_models( - data: Union[Unset, None, Dict[str, Any], str] + data: object, ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] if data is None: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py index 716bcd618..5b91034b0 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py @@ -41,7 +41,7 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: for prop_name, prop_dict in d.items(): def _parse_additional_property( - data: Union[Dict[str, Any], List[Any], str, float, int, bool] + data: object, ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: additional_property: Union[ ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index 4fc7c2d2d..a5f9c3638 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -40,7 +40,7 @@ def to_dict(self) -> Dict[str, Any]: def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIntEnum]: + def _parse_a_property(data: object) -> Union[Unset, AnEnum, AnIntEnum]: a_property: Union[Unset, AnEnum, AnIntEnum] if isinstance(data, Unset): return data diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 59a848dc8..16c385b55 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -174,7 +174,7 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: str) -> Union[datetime.datetime, datetime.date]: + def _parse_a_camel_date_time(data: object) -> Union[datetime.datetime, datetime.date]: a_camel_date_time: Union[datetime.datetime, datetime.date] try: if not isinstance(data, str): @@ -196,7 +196,7 @@ def _parse_a_camel_date_time(data: str) -> Union[datetime.datetime, datetime.dat required_not_nullable = d.pop("required_not_nullable") - def _parse_one_of_models(data: Dict[str, Any]) -> Union[FreeFormModel, ModelWithUnionProperty]: + def _parse_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty]: one_of_models: Union[FreeFormModel, ModelWithUnionProperty] try: if not isinstance(data, dict): @@ -246,9 +246,7 @@ def _parse_one_of_models(data: Dict[str, Any]) -> Union[FreeFormModel, ModelWith not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) - def _parse_nullable_one_of_models( - data: Union[None, Dict[str, Any]] - ) -> Union[None, FreeFormModel, ModelWithUnionProperty]: + def _parse_nullable_one_of_models(data: object) -> Union[None, FreeFormModel, ModelWithUnionProperty]: nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] if data is None: return data @@ -268,9 +266,7 @@ def _parse_nullable_one_of_models( nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) - def _parse_not_required_one_of_models( - data: Union[Unset, Dict[str, Any]] - ) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: + def _parse_not_required_one_of_models(data: object) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] if isinstance(data, Unset): return data @@ -297,7 +293,7 @@ def _parse_not_required_one_of_models( not_required_one_of_models = _parse_not_required_one_of_models(d.pop("not_required_one_of_models", UNSET)) def _parse_not_required_nullable_one_of_models( - data: Union[Unset, None, Dict[str, Any], str] + data: object, ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] if data is None: 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 716bcd618..5b91034b0 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 @@ -41,7 +41,7 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: for prop_name, prop_dict in d.items(): def _parse_additional_property( - data: Union[Dict[str, Any], List[Any], str, float, int, bool] + data: object, ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: additional_property: Union[ ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index 4fc7c2d2d..a5f9c3638 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -40,7 +40,7 @@ def to_dict(self) -> Dict[str, Any]: def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - def _parse_a_property(data: Union[Unset, str, int]) -> Union[Unset, AnEnum, AnIntEnum]: + def _parse_a_property(data: object) -> Union[Unset, AnEnum, AnIntEnum]: a_property: Union[Unset, AnEnum, AnIntEnum] if isinstance(data, Unset): return data diff --git a/openapi_python_client/templates/property_templates/union_property.py.jinja b/openapi_python_client/templates/property_templates/union_property.py.jinja index 3fb6a0967..73806346f 100644 --- a/openapi_python_client/templates/property_templates/union_property.py.jinja +++ b/openapi_python_client/templates/property_templates/union_property.py.jinja @@ -1,5 +1,5 @@ {% macro construct(property, source, initial_value=None) %} -def _parse_{{ property.python_name }}(data: {{ property.get_type_string(json=True) }}) -> {{ property.get_type_string() }}: +def _parse_{{ property.python_name }}(data: object) -> {{ property.get_type_string() }}: {{ property.python_name }}: {{ property.get_type_string() }} {% if "None" in property.get_type_strings_in_union(json=True) %} if data is None: From b5fa15d61468fd0a0a48d86b831db5a27eb78c18 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 10 Feb 2021 18:18:35 -0500 Subject: [PATCH 12/17] Address suggestions --- .../custom_e2e/models/model_with_union_property.py | 2 +- end_to_end_tests/golden-record-custom/custom_e2e/types.py | 1 - .../my_test_api_client/models/model_with_union_property.py | 2 +- end_to_end_tests/golden-record/my_test_api_client/types.py | 1 - .../templates/property_templates/enum_property.py.jinja | 2 +- openapi_python_client/templates/types.py.jinja | 2 +- 6 files changed, 4 insertions(+), 6 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index a5f9c3638..29fa47c67 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -45,7 +45,7 @@ def _parse_a_property(data: object) -> Union[Unset, AnEnum, AnIntEnum]: if isinstance(data, Unset): return data try: - if not isinstance(data, int): + if not isinstance(data, str): raise TypeError() a_property = UNSET _a_property = data diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/types.py b/end_to_end_tests/golden-record-custom/custom_e2e/types.py index a354a2192..0739e2197 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/types.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/types.py @@ -11,7 +11,6 @@ def __bool__(self) -> bool: UNSET: Unset = Unset() -# Used as `FileProperty._json_type_string` FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index a5f9c3638..29fa47c67 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -45,7 +45,7 @@ def _parse_a_property(data: object) -> Union[Unset, AnEnum, AnIntEnum]: if isinstance(data, Unset): return data try: - if not isinstance(data, int): + if not isinstance(data, str): raise TypeError() a_property = UNSET _a_property = data diff --git a/end_to_end_tests/golden-record/my_test_api_client/types.py b/end_to_end_tests/golden-record/my_test_api_client/types.py index a354a2192..0739e2197 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/types.py +++ b/end_to_end_tests/golden-record/my_test_api_client/types.py @@ -11,7 +11,6 @@ def __bool__(self) -> bool: UNSET: Unset = Unset() -# Used as `FileProperty._json_type_string` FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] diff --git a/openapi_python_client/templates/property_templates/enum_property.py.jinja b/openapi_python_client/templates/property_templates/enum_property.py.jinja index db69abf03..4916927bd 100644 --- a/openapi_python_client/templates/property_templates/enum_property.py.jinja +++ b/openapi_python_client/templates/property_templates/enum_property.py.jinja @@ -8,7 +8,7 @@ {{ construct_template(construct_function, property, source, initial_value=initial_value) }} {% endmacro %} -{% macro check_type_for_construct(property, source) %}{% if property.value_type == str %}isinstance({{ source }}, str){% else %}isinstance({{ source }}, int){% endif %}{% endmacro %} +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, {{ property.value_type.__name__ }}){% endmacro %} {% macro transform(property, source, destination, declare_type=True) %} {% if property.required %} diff --git a/openapi_python_client/templates/types.py.jinja b/openapi_python_client/templates/types.py.jinja index a354a2192..116054226 100644 --- a/openapi_python_client/templates/types.py.jinja +++ b/openapi_python_client/templates/types.py.jinja @@ -11,7 +11,7 @@ class Unset: UNSET: Unset = Unset() -# Used as `FileProperty._json_type_string` +{# Used as `FileProperty._json_type_string` #} FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] From 43969ae292ebc5379255168f5e9234a4882605ac Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Thu, 11 Feb 2021 09:03:06 -0500 Subject: [PATCH 13/17] Make inner types into a set, fix List type string, add tests --- .../api/tests/defaults_tests_defaults_post.py | 4 +-- ...tional_value_tests_optional_query_param.py | 2 +- .../custom_e2e/models/a_model.py | 34 +++++++++---------- .../models/http_validation_error.py | 2 +- .../models/model_with_any_json_properties.py | 12 +++---- .../models/model_with_union_property.py | 8 ++--- .../api/tests/defaults_tests_defaults_post.py | 12 +++---- ...tional_value_tests_optional_query_param.py | 2 +- .../my_test_api_client/models/a_model.py | 34 +++++++++---------- .../models/http_validation_error.py | 2 +- .../models/model_with_any_json_properties.py | 12 +++---- .../models/model_with_union_property.py | 8 ++--- .../parser/properties/__init__.py | 32 ++++++++--------- .../test_parser/test_properties/test_init.py | 11 ++++-- .../test_properties/test_model_property.py | 23 +++++++------ 15 files changed, 101 insertions(+), 97 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index f1aedb4f0..6ce8e7092 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -52,7 +52,7 @@ def httpx_request( boolean_prop: Union[Unset, bool] = False, list_prop: Union[Unset, List[AnEnum]] = UNSET, union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, + union_prop_with_ref: Union[AnEnum, Unset, float] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: @@ -77,7 +77,7 @@ def httpx_request( if not isinstance(date_prop, Unset): json_date_prop = date_prop.isoformat() - json_list_prop: Union[Unset, List[Any]] = UNSET + json_list_prop: Union[Unset, List[str]] = UNSET if not isinstance(list_prop, Unset): json_list_prop = [] for list_prop_item_data in list_prop: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py index 78413711a..244cdc161 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py @@ -39,7 +39,7 @@ def httpx_request( query_param: Union[Unset, List[str]] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: - json_query_param: Union[Unset, List[Any]] = UNSET + json_query_param: Union[Unset, List[str]] = UNSET if not isinstance(query_param, Unset): json_query_param = query_param diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index 16c385b55..242112521 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -22,22 +22,22 @@ class AModel: """ A Model for testing all the ways custom objects can be used """ an_enum_value: AnEnum - a_camel_date_time: Union[datetime.datetime, datetime.date] + a_camel_date_time: Union[datetime.date, datetime.datetime] a_date: datetime.date required_not_nullable: str one_of_models: Union[FreeFormModel, ModelWithUnionProperty] model: AModelModel a_nullable_date: Optional[datetime.date] required_nullable: Optional[str] - nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] + nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None] nullable_model: Optional[AModelNullableModel] nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET a_not_required_date: Union[Unset, datetime.date] = UNSET attr_1_leading_digit: Union[Unset, str] = UNSET not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET - not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] = UNSET - not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] = UNSET + not_required_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, Unset] = UNSET + not_required_nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str] = UNSET not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET not_required_nullable_model: Union[Unset, None, AModelNotRequiredNullableModel] = UNSET @@ -60,7 +60,7 @@ def to_dict(self) -> Dict[str, Any]: model = self.model.to_dict() - nested_list_of_enums: Union[Unset, List[Any]] = UNSET + nested_list_of_enums: Union[Unset, List[List[str]]] = UNSET if not isinstance(self.nested_list_of_enums, Unset): nested_list_of_enums = [] for nested_list_of_enums_item_data in self.nested_list_of_enums: @@ -81,7 +81,7 @@ def to_dict(self) -> Dict[str, Any]: required_nullable = self.required_nullable not_required_nullable = self.not_required_nullable not_required_not_nullable = self.not_required_not_nullable - nullable_one_of_models: Union[None, Dict[str, Any]] + nullable_one_of_models: Union[Dict[str, Any], None] if self.nullable_one_of_models is None: nullable_one_of_models = None elif isinstance(self.nullable_one_of_models, FreeFormModel): @@ -90,7 +90,7 @@ def to_dict(self) -> Dict[str, Any]: else: nullable_one_of_models = self.nullable_one_of_models.to_dict() - not_required_one_of_models: Union[Unset, Dict[str, Any]] + not_required_one_of_models: Union[Dict[str, Any], Unset] if isinstance(self.not_required_one_of_models, Unset): not_required_one_of_models = UNSET elif isinstance(self.not_required_one_of_models, FreeFormModel): @@ -103,7 +103,7 @@ def to_dict(self) -> Dict[str, Any]: if not isinstance(self.not_required_one_of_models, Unset): not_required_one_of_models = self.not_required_one_of_models.to_dict() - not_required_nullable_one_of_models: Union[Unset, None, Dict[str, Any], str] + not_required_nullable_one_of_models: Union[Dict[str, Any], None, Unset, str] if isinstance(self.not_required_nullable_one_of_models, Unset): not_required_nullable_one_of_models = UNSET elif self.not_required_nullable_one_of_models is None: @@ -174,8 +174,8 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: object) -> Union[datetime.datetime, datetime.date]: - a_camel_date_time: Union[datetime.datetime, datetime.date] + def _parse_a_camel_date_time(data: object) -> Union[datetime.date, datetime.datetime]: + a_camel_date_time: Union[datetime.date, datetime.datetime] try: if not isinstance(data, str): raise TypeError() @@ -246,8 +246,8 @@ def _parse_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionPro not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) - def _parse_nullable_one_of_models(data: object) -> Union[None, FreeFormModel, ModelWithUnionProperty]: - nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] + def _parse_nullable_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty, None]: + nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None] if data is None: return data try: @@ -266,8 +266,8 @@ def _parse_nullable_one_of_models(data: object) -> Union[None, FreeFormModel, Mo nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) - def _parse_not_required_one_of_models(data: object) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: - not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] + def _parse_not_required_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty, Unset]: + not_required_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, Unset] if isinstance(data, Unset): return data try: @@ -294,8 +294,8 @@ def _parse_not_required_one_of_models(data: object) -> Union[Unset, FreeFormMode def _parse_not_required_nullable_one_of_models( data: object, - ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: - not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] + ) -> Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str]: + not_required_nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str] if data is None: return data if isinstance(data, Unset): @@ -324,7 +324,7 @@ def _parse_not_required_nullable_one_of_models( return not_required_nullable_one_of_models except: # noqa: E722 pass - return cast(Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str], data) + return cast(Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str], data) not_required_nullable_one_of_models = _parse_not_required_nullable_one_of_models( d.pop("not_required_nullable_one_of_models", UNSET) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/http_validation_error.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/http_validation_error.py index 3025b07af..feb2cdd6b 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/http_validation_error.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/http_validation_error.py @@ -15,7 +15,7 @@ class HTTPValidationError: detail: Union[Unset, List[ValidationError]] = UNSET def to_dict(self) -> Dict[str, Any]: - detail: Union[Unset, List[Any]] = UNSET + detail: Union[Unset, List[Dict[str, Any]]] = UNSET if not isinstance(self.detail, Unset): detail = [] for detail_item_data in self.detail: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py index 5b91034b0..cf900f3c6 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py @@ -12,7 +12,7 @@ class ModelWithAnyJsonProperties: """ """ additional_properties: Dict[ - str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + str, Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str] ] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: @@ -42,9 +42,9 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: object, - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str]: additional_property: Union[ - ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool + List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str ] try: if not isinstance(data, dict): @@ -62,7 +62,7 @@ def _parse_additional_property( return additional_property except: # noqa: E722 pass - return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data) + return cast(Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str], data) additional_property = _parse_additional_property(prop_dict) @@ -77,11 +77,11 @@ def additional_keys(self) -> List[str]: def __getitem__( self, key: str - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str]: return self.additional_properties[key] def __setitem__( - self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + self, key: str, value: Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str] ) -> None: self.additional_properties[key] = value diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index 29fa47c67..a74bc5274 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -13,10 +13,10 @@ class ModelWithUnionProperty: """ """ - a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET + a_property: Union[AnEnum, AnIntEnum, Unset] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, str, int] + a_property: Union[Unset, int, str] if isinstance(self.a_property, Unset): a_property = UNSET elif isinstance(self.a_property, AnEnum): @@ -40,8 +40,8 @@ def to_dict(self) -> Dict[str, Any]: def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - def _parse_a_property(data: object) -> Union[Unset, AnEnum, AnIntEnum]: - a_property: Union[Unset, AnEnum, AnIntEnum] + def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]: + a_property: Union[AnEnum, AnIntEnum, Unset] if isinstance(data, Unset): return data try: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index b8b1a3220..fb836d977 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -25,7 +25,7 @@ def _get_kwargs( boolean_prop: Union[Unset, bool] = False, list_prop: Union[Unset, List[AnEnum]] = UNSET, union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, + union_prop_with_ref: Union[AnEnum, Unset, float] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Dict[str, Any]: @@ -53,7 +53,7 @@ def _get_kwargs( if not isinstance(date_prop, Unset): json_date_prop = date_prop.isoformat() - json_list_prop: Union[Unset, List[Any]] = UNSET + json_list_prop: Union[Unset, List[str]] = UNSET if not isinstance(list_prop, Unset): json_list_prop = [] for list_prop_item_data in list_prop: @@ -148,7 +148,7 @@ def sync_detailed( boolean_prop: Union[Unset, bool] = False, list_prop: Union[Unset, List[AnEnum]] = UNSET, union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, + union_prop_with_ref: Union[AnEnum, Unset, float] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: @@ -191,7 +191,7 @@ def sync( boolean_prop: Union[Unset, bool] = False, list_prop: Union[Unset, List[AnEnum]] = UNSET, union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, + union_prop_with_ref: Union[AnEnum, Unset, float] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Optional[Union[None, HTTPValidationError]]: @@ -230,7 +230,7 @@ async def asyncio_detailed( boolean_prop: Union[Unset, bool] = False, list_prop: Union[Unset, List[AnEnum]] = UNSET, union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, + union_prop_with_ref: Union[AnEnum, Unset, float] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: @@ -272,7 +272,7 @@ async def asyncio( boolean_prop: Union[Unset, bool] = False, list_prop: Union[Unset, List[AnEnum]] = UNSET, union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, + union_prop_with_ref: Union[AnEnum, Unset, float] = 0.6, enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, ) -> Optional[Union[None, HTTPValidationError]]: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py index 3de18244f..32f8bd3ec 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py @@ -16,7 +16,7 @@ def _get_kwargs( headers: Dict[str, Any] = client.get_headers() - json_query_param: Union[Unset, List[Any]] = UNSET + json_query_param: Union[Unset, List[str]] = UNSET if not isinstance(query_param, Unset): json_query_param = query_param diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 16c385b55..242112521 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -22,22 +22,22 @@ class AModel: """ A Model for testing all the ways custom objects can be used """ an_enum_value: AnEnum - a_camel_date_time: Union[datetime.datetime, datetime.date] + a_camel_date_time: Union[datetime.date, datetime.datetime] a_date: datetime.date required_not_nullable: str one_of_models: Union[FreeFormModel, ModelWithUnionProperty] model: AModelModel a_nullable_date: Optional[datetime.date] required_nullable: Optional[str] - nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] + nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None] nullable_model: Optional[AModelNullableModel] nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET a_not_required_date: Union[Unset, datetime.date] = UNSET attr_1_leading_digit: Union[Unset, str] = UNSET not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET - not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] = UNSET - not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] = UNSET + not_required_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, Unset] = UNSET + not_required_nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str] = UNSET not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET not_required_nullable_model: Union[Unset, None, AModelNotRequiredNullableModel] = UNSET @@ -60,7 +60,7 @@ def to_dict(self) -> Dict[str, Any]: model = self.model.to_dict() - nested_list_of_enums: Union[Unset, List[Any]] = UNSET + nested_list_of_enums: Union[Unset, List[List[str]]] = UNSET if not isinstance(self.nested_list_of_enums, Unset): nested_list_of_enums = [] for nested_list_of_enums_item_data in self.nested_list_of_enums: @@ -81,7 +81,7 @@ def to_dict(self) -> Dict[str, Any]: required_nullable = self.required_nullable not_required_nullable = self.not_required_nullable not_required_not_nullable = self.not_required_not_nullable - nullable_one_of_models: Union[None, Dict[str, Any]] + nullable_one_of_models: Union[Dict[str, Any], None] if self.nullable_one_of_models is None: nullable_one_of_models = None elif isinstance(self.nullable_one_of_models, FreeFormModel): @@ -90,7 +90,7 @@ def to_dict(self) -> Dict[str, Any]: else: nullable_one_of_models = self.nullable_one_of_models.to_dict() - not_required_one_of_models: Union[Unset, Dict[str, Any]] + not_required_one_of_models: Union[Dict[str, Any], Unset] if isinstance(self.not_required_one_of_models, Unset): not_required_one_of_models = UNSET elif isinstance(self.not_required_one_of_models, FreeFormModel): @@ -103,7 +103,7 @@ def to_dict(self) -> Dict[str, Any]: if not isinstance(self.not_required_one_of_models, Unset): not_required_one_of_models = self.not_required_one_of_models.to_dict() - not_required_nullable_one_of_models: Union[Unset, None, Dict[str, Any], str] + not_required_nullable_one_of_models: Union[Dict[str, Any], None, Unset, str] if isinstance(self.not_required_nullable_one_of_models, Unset): not_required_nullable_one_of_models = UNSET elif self.not_required_nullable_one_of_models is None: @@ -174,8 +174,8 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() an_enum_value = AnEnum(d.pop("an_enum_value")) - def _parse_a_camel_date_time(data: object) -> Union[datetime.datetime, datetime.date]: - a_camel_date_time: Union[datetime.datetime, datetime.date] + def _parse_a_camel_date_time(data: object) -> Union[datetime.date, datetime.datetime]: + a_camel_date_time: Union[datetime.date, datetime.datetime] try: if not isinstance(data, str): raise TypeError() @@ -246,8 +246,8 @@ def _parse_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionPro not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) - def _parse_nullable_one_of_models(data: object) -> Union[None, FreeFormModel, ModelWithUnionProperty]: - nullable_one_of_models: Union[None, FreeFormModel, ModelWithUnionProperty] + def _parse_nullable_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty, None]: + nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None] if data is None: return data try: @@ -266,8 +266,8 @@ def _parse_nullable_one_of_models(data: object) -> Union[None, FreeFormModel, Mo nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) - def _parse_not_required_one_of_models(data: object) -> Union[Unset, FreeFormModel, ModelWithUnionProperty]: - not_required_one_of_models: Union[Unset, FreeFormModel, ModelWithUnionProperty] + def _parse_not_required_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty, Unset]: + not_required_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, Unset] if isinstance(data, Unset): return data try: @@ -294,8 +294,8 @@ def _parse_not_required_one_of_models(data: object) -> Union[Unset, FreeFormMode def _parse_not_required_nullable_one_of_models( data: object, - ) -> Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str]: - not_required_nullable_one_of_models: Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str] + ) -> Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str]: + not_required_nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str] if data is None: return data if isinstance(data, Unset): @@ -324,7 +324,7 @@ def _parse_not_required_nullable_one_of_models( return not_required_nullable_one_of_models except: # noqa: E722 pass - return cast(Union[Unset, None, FreeFormModel, ModelWithUnionProperty, str], data) + return cast(Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str], data) not_required_nullable_one_of_models = _parse_not_required_nullable_one_of_models( d.pop("not_required_nullable_one_of_models", UNSET) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py index 3025b07af..feb2cdd6b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py @@ -15,7 +15,7 @@ class HTTPValidationError: detail: Union[Unset, List[ValidationError]] = UNSET def to_dict(self) -> Dict[str, Any]: - detail: Union[Unset, List[Any]] = UNSET + detail: Union[Unset, List[Dict[str, Any]]] = UNSET if not isinstance(self.detail, Unset): detail = [] for detail_item_data in self.detail: 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 5b91034b0..cf900f3c6 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 @@ -12,7 +12,7 @@ class ModelWithAnyJsonProperties: """ """ additional_properties: Dict[ - str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + str, Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str] ] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: @@ -42,9 +42,9 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: object, - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str]: additional_property: Union[ - ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool + List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str ] try: if not isinstance(data, dict): @@ -62,7 +62,7 @@ def _parse_additional_property( return additional_property except: # noqa: E722 pass - return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data) + return cast(Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str], data) additional_property = _parse_additional_property(prop_dict) @@ -77,11 +77,11 @@ def additional_keys(self) -> List[str]: def __getitem__( self, key: str - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str]: return self.additional_properties[key] def __setitem__( - self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + self, key: str, value: Union[List[str], ModelWithAnyJsonPropertiesAdditionalProperty, bool, float, int, str] ) -> None: self.additional_properties[key] = value diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index 29fa47c67..a74bc5274 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -13,10 +13,10 @@ class ModelWithUnionProperty: """ """ - a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET + a_property: Union[AnEnum, AnIntEnum, Unset] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, str, int] + a_property: Union[Unset, int, str] if isinstance(self.a_property, Unset): a_property = UNSET elif isinstance(self.a_property, AnEnum): @@ -40,8 +40,8 @@ def to_dict(self) -> Dict[str, Any]: def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - def _parse_a_property(data: object) -> Union[Unset, AnEnum, AnIntEnum]: - a_property: Union[Unset, AnEnum, AnIntEnum] + def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]: + a_property: Union[AnEnum, AnIntEnum, Unset] if isinstance(data, Unset): return data try: diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 971967c88..5583c4519 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -131,12 +131,14 @@ class ListProperty(Property, Generic[InnerProp]): """ A property representing a list (array) of other properties """ inner_property: InnerProp - _json_type_string: ClassVar[str] = "List[Any]" template: ClassVar[str] = "list_property.py.jinja" def get_base_type_string(self) -> str: return f"List[{self.inner_property.get_type_string()}]" + def get_base_json_type_string(self) -> str: + return f"List[{self.inner_property.get_type_string(json=True)}]" + def get_instance_type_string(self) -> str: """Get a string representation of runtime type that should be used for `isinstance` checks""" return "list" @@ -169,16 +171,14 @@ def __attrs_post_init__(self) -> None: self, "has_properties_without_templates", any(prop.template is None for prop in self.inner_properties) ) - def _get_inner_type_strings(self, json: bool = False) -> List[str]: - inner_types = [p.get_type_string(no_optional=True, json=json) for p in self.inner_properties] - unique_inner_types = list(dict.fromkeys(inner_types)) - return unique_inner_types + def _get_inner_type_strings(self, json: bool = False) -> Set[str]: + return {p.get_type_string(no_optional=True, json=json) for p in self.inner_properties} - def _get_type_string_from_inner_type_strings(self, inner_types: List[str]) -> str: + def _get_type_string_from_inner_type_strings(self, inner_types: Set[str]) -> str: if len(inner_types) == 1: - return inner_types[0] + return inner_types.pop() else: - return f"Union[{', '.join(inner_types)}]" + return f"Union[{', '.join(sorted(inner_types))}]" def get_base_type_string(self) -> str: return self._get_type_string_from_inner_type_strings(self._get_inner_type_strings(json=False)) @@ -186,17 +186,15 @@ def get_base_type_string(self) -> str: def get_base_json_type_string(self) -> str: return self._get_type_string_from_inner_type_strings(self._get_inner_type_strings(json=True)) - def get_type_strings_in_union(self, no_optional: bool = False, json: bool = False) -> List[str]: + def get_type_strings_in_union(self, no_optional: bool = False, json: bool = False) -> Set[str]: type_strings = self._get_inner_type_strings(json=json) - - if no_optional or (self.required and not self.nullable): + if no_optional: return type_strings - elif self.required and self.nullable: - return ["None"] + type_strings - elif not self.required and self.nullable: - return ["Unset", "None"] + type_strings - else: - return ["Unset"] + type_strings + if self.nullable: + type_strings.add("None") + if not self.required: + type_strings.add("Unset") + return type_strings def get_type_string(self, no_optional: bool = False, json: bool = False) -> str: """ diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 1770a70c9..3e635e7e2 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -88,6 +88,7 @@ def test_get_type_string(self): base_type_string = f"str" assert p.get_type_string() == base_type_string + assert p.get_type_string(json=True) == base_type_string p = StringProperty(name="test", required=True, default=None, nullable=True) assert p.get_type_string() == f"Optional[{base_type_string}]" @@ -196,12 +197,15 @@ def test_get_type_string(self, mocker): inner_property = mocker.MagicMock() inner_type_string = mocker.MagicMock() - inner_property.get_type_string.return_value = inner_type_string + inner_property.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "int" if json else inner_type_string + ) p = ListProperty(name="test", required=True, default=None, inner_property=inner_property, nullable=False) base_type_string = f"List[{inner_type_string}]" assert p.get_type_string() == base_type_string + assert p.get_type_string(json=True) == "List[int]" p = ListProperty(name="test", required=True, default=None, inner_property=inner_property, nullable=True) assert p.get_type_string() == f"Optional[{base_type_string}]" @@ -255,7 +259,7 @@ class TestUnionProperty: (False, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), (False, True, False, False, "Union[inner_type_string_1, inner_type_string_2]"), (False, True, True, False, "Union[inner_type_string_1, inner_type_string_2]"), - (True, False, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (True, False, False, False, "Union[None, Unset, inner_type_string_1, inner_type_string_2]"), (True, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), (True, True, False, False, "Union[None, inner_type_string_1, inner_type_string_2]"), (True, True, True, False, "Union[inner_type_string_1, inner_type_string_2]"), @@ -263,7 +267,7 @@ class TestUnionProperty: (False, False, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), (False, True, False, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), (False, True, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), - (True, False, False, True, "Union[Unset, None, inner_json_type_string_1, inner_json_type_string_2]"), + (True, False, False, True, "Union[None, Unset, inner_json_type_string_1, inner_json_type_string_2]"), (True, False, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), (True, True, False, True, "Union[None, inner_json_type_string_1, inner_json_type_string_2]"), (True, True, True, True, "Union[inner_json_type_string_1, inner_json_type_string_2]"), @@ -364,6 +368,7 @@ def test_get_type_string(self, mocker): base_type_string = f"MyTestEnum" assert p.get_type_string() == base_type_string + assert p.get_type_string(json=True) == "str" p = properties.EnumProperty( name="test", diff --git a/tests/test_parser/test_properties/test_model_property.py b/tests/test_parser/test_properties/test_model_property.py index 410112666..def1734e7 100644 --- a/tests/test_parser/test_properties/test_model_property.py +++ b/tests/test_parser/test_properties/test_model_property.py @@ -2,19 +2,20 @@ @pytest.mark.parametrize( - "no_optional,nullable,required,expected", + "no_optional,nullable,required,json,expected", [ - (False, False, False, "Union[Unset, MyClass]"), - (False, False, True, "MyClass"), - (False, True, False, "Union[Unset, None, MyClass]"), - (False, True, True, "Optional[MyClass]"), - (True, False, False, "MyClass"), - (True, False, True, "MyClass"), - (True, True, False, "MyClass"), - (True, True, True, "MyClass"), + (False, False, False, False, "Union[Unset, MyClass]"), + (False, False, True, False, "MyClass"), + (False, True, False, False, "Union[Unset, None, MyClass]"), + (False, True, True, False, "Optional[MyClass]"), + (True, False, False, False, "MyClass"), + (True, False, True, False, "MyClass"), + (True, True, False, False, "MyClass"), + (True, True, True, False, "MyClass"), + (False, False, True, True, "Dict[str, Any]"), ], ) -def test_get_type_string(no_optional, nullable, required, expected): +def test_get_type_string(no_optional, nullable, required, json, expected): from openapi_python_client.parser.properties import ModelProperty, Reference prop = ModelProperty( @@ -30,7 +31,7 @@ def test_get_type_string(no_optional, nullable, required, expected): additional_properties=False, ) - assert prop.get_type_string(no_optional=no_optional) == expected + assert prop.get_type_string(no_optional=no_optional, json=json) == expected def test_get_imports(): From caea77ab53258f80a87304dd248a9b1d1b913373 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Thu, 11 Feb 2021 09:06:09 -0500 Subject: [PATCH 14/17] Add more E2E tests --- .../api/tests/defaults_tests_defaults_post.py | 20 +++++++++++ .../api/tests/defaults_tests_defaults_post.py | 36 +++++++++++++++++++ end_to_end_tests/openapi.json | 26 ++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index 4586ffd7c..bf0a91507 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -56,6 +56,8 @@ def httpx_request( enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, required_model_prop: ModelWithUnionProperty, + nullable_model_prop: Union[ModelWithUnionProperty, None, Unset] = UNSET, + nullable_required_model_prop: Union[ModelWithUnionProperty, None], ) -> Response[Union[None, HTTPValidationError]]: json_not_required_not_nullable_datetime_prop: Union[Unset, str] = UNSET @@ -113,6 +115,22 @@ def httpx_request( json_required_model_prop = required_model_prop.to_dict() + json_nullable_model_prop: Union[Dict[str, Any], None, Unset] + if isinstance(nullable_model_prop, Unset): + json_nullable_model_prop = UNSET + elif nullable_model_prop is None: + json_nullable_model_prop = None + else: + json_nullable_model_prop = UNSET + if not isinstance(nullable_model_prop, Unset): + json_nullable_model_prop = nullable_model_prop.to_dict() + + json_nullable_required_model_prop: Union[Dict[str, Any], None] + if nullable_required_model_prop is None: + json_nullable_required_model_prop = None + else: + json_nullable_required_model_prop = nullable_required_model_prop.to_dict() + params: Dict[str, Any] = { "string_prop": string_prop, "not_required_not_nullable_datetime_prop": json_not_required_not_nullable_datetime_prop, @@ -127,6 +145,8 @@ def httpx_request( "union_prop": json_union_prop, "union_prop_with_ref": json_union_prop_with_ref, "enum_prop": json_enum_prop, + "nullable_model_prop": json_nullable_model_prop, + "nullable_required_model_prop": json_nullable_required_model_prop, } if not isinstance(json_model_prop, Unset): params.update(json_model_prop) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index fff59bef5..07c270ce5 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -29,6 +29,8 @@ def _get_kwargs( enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, required_model_prop: ModelWithUnionProperty, + nullable_model_prop: Union[ModelWithUnionProperty, None, Unset] = UNSET, + nullable_required_model_prop: Union[ModelWithUnionProperty, None], ) -> Dict[str, Any]: url = "{}/tests/defaults".format(client.base_url) @@ -89,6 +91,22 @@ def _get_kwargs( json_required_model_prop = required_model_prop.to_dict() + json_nullable_model_prop: Union[Dict[str, Any], None, Unset] + if isinstance(nullable_model_prop, Unset): + json_nullable_model_prop = UNSET + elif nullable_model_prop is None: + json_nullable_model_prop = None + else: + json_nullable_model_prop = UNSET + if not isinstance(nullable_model_prop, Unset): + json_nullable_model_prop = nullable_model_prop.to_dict() + + json_nullable_required_model_prop: Union[Dict[str, Any], None] + if nullable_required_model_prop is None: + json_nullable_required_model_prop = None + else: + json_nullable_required_model_prop = nullable_required_model_prop.to_dict() + params: Dict[str, Any] = { "string_prop": string_prop, "not_required_not_nullable_datetime_prop": json_not_required_not_nullable_datetime_prop, @@ -103,6 +121,8 @@ def _get_kwargs( "union_prop": json_union_prop, "union_prop_with_ref": json_union_prop_with_ref, "enum_prop": json_enum_prop, + "nullable_model_prop": json_nullable_model_prop, + "nullable_required_model_prop": json_nullable_required_model_prop, } if not isinstance(json_model_prop, Unset): params.update(json_model_prop) @@ -157,6 +177,8 @@ def sync_detailed( enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, required_model_prop: ModelWithUnionProperty, + nullable_model_prop: Union[ModelWithUnionProperty, None, Unset] = UNSET, + nullable_required_model_prop: Union[ModelWithUnionProperty, None], ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -175,6 +197,8 @@ def sync_detailed( enum_prop=enum_prop, model_prop=model_prop, required_model_prop=required_model_prop, + nullable_model_prop=nullable_model_prop, + nullable_required_model_prop=nullable_required_model_prop, ) response = httpx.post( @@ -202,6 +226,8 @@ def sync( enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, required_model_prop: ModelWithUnionProperty, + nullable_model_prop: Union[ModelWithUnionProperty, None, Unset] = UNSET, + nullable_required_model_prop: Union[ModelWithUnionProperty, None], ) -> Optional[Union[None, HTTPValidationError]]: """ """ @@ -222,6 +248,8 @@ def sync( enum_prop=enum_prop, model_prop=model_prop, required_model_prop=required_model_prop, + nullable_model_prop=nullable_model_prop, + nullable_required_model_prop=nullable_required_model_prop, ).parsed @@ -243,6 +271,8 @@ async def asyncio_detailed( enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, required_model_prop: ModelWithUnionProperty, + nullable_model_prop: Union[ModelWithUnionProperty, None, Unset] = UNSET, + nullable_required_model_prop: Union[ModelWithUnionProperty, None], ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -261,6 +291,8 @@ async def asyncio_detailed( enum_prop=enum_prop, model_prop=model_prop, required_model_prop=required_model_prop, + nullable_model_prop=nullable_model_prop, + nullable_required_model_prop=nullable_required_model_prop, ) async with httpx.AsyncClient() as _client: @@ -287,6 +319,8 @@ async def asyncio( enum_prop: Union[Unset, AnEnum] = UNSET, model_prop: Union[Unset, ModelWithUnionProperty] = UNSET, required_model_prop: ModelWithUnionProperty, + nullable_model_prop: Union[ModelWithUnionProperty, None, Unset] = UNSET, + nullable_required_model_prop: Union[ModelWithUnionProperty, None], ) -> Optional[Union[None, HTTPValidationError]]: """ """ @@ -308,5 +342,7 @@ async def asyncio( enum_prop=enum_prop, model_prop=model_prop, required_model_prop=required_model_prop, + nullable_model_prop=nullable_model_prop, + nullable_required_model_prop=nullable_required_model_prop, ) ).parsed diff --git a/end_to_end_tests/openapi.json b/end_to_end_tests/openapi.json index c5f723d6e..e2c29ace0 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -449,6 +449,32 @@ }, "name": "required_model_prop", "in": "query" + }, + { + "required": false, + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/ModelWithUnionProperty" + } + ], + "nullable": true + }, + "name": "nullable_model_prop", + "in": "query" + }, + { + "required": true, + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/ModelWithUnionProperty" + } + ], + "nullable": true + }, + "name": "nullable_required_model_prop", + "in": "query" } ], "responses": { From 55496e5a7bb3d2630a04fc2508c77d80ea8f230c Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 2 Mar 2021 19:42:45 -0500 Subject: [PATCH 15/17] Add tests --- .../test_parser/test_properties/test_init.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 3e635e7e2..977282a56 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -293,6 +293,46 @@ def test_get_type_string(self, mocker, nullable, required, no_optional, json, ex ) assert p.get_type_string(no_optional=no_optional, json=json) == expected + def test_get_base_type_string(self, mocker): + from openapi_python_client.parser.properties import UnionProperty + + inner_property_1 = mocker.MagicMock() + inner_property_1.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "inner_json_type_string_1" if json else "inner_type_string_1" + ) + inner_property_2 = mocker.MagicMock() + inner_property_2.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "inner_json_type_string_2" if json else "inner_type_string_2" + ) + p = UnionProperty( + name="test", + required=False, + default=None, + inner_properties=[inner_property_1, inner_property_2], + nullable=True, + ) + assert p.get_base_type_string() == "Union[inner_type_string_1, inner_type_string_2]" + + def test_get_base_json_type_string(self, mocker): + from openapi_python_client.parser.properties import UnionProperty + + inner_property_1 = mocker.MagicMock() + inner_property_1.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "inner_json_type_string_1" if json else "inner_type_string_1" + ) + inner_property_2 = mocker.MagicMock() + inner_property_2.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "inner_json_type_string_2" if json else "inner_type_string_2" + ) + p = UnionProperty( + name="test", + required=False, + default=None, + inner_properties=[inner_property_1, inner_property_2], + nullable=True, + ) + assert p.get_base_json_type_string() == "Union[inner_json_type_string_1, inner_json_type_string_2]" + def test_get_imports(self, mocker): from openapi_python_client.parser.properties import UnionProperty From 1ddd486b5c14d654d04916ac20aab6adf8e8ae86 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 2 Mar 2021 19:44:22 -0500 Subject: [PATCH 16/17] Change item to type --- .../custom_e2e/models/__init__.py | 6 +- .../custom_e2e/models/a_model.py | 88 +++++++++---------- .../models/model_with_any_json_properties.py | 28 +++--- ...n_properties_additional_property_type0.py} | 10 +-- .../models/model_with_union_property.py | 24 ++--- .../model_with_union_property_inlined.py | 34 +++---- ...ith_union_property_inlined_fruit_type0.py} | 10 +-- ...ith_union_property_inlined_fruit_type1.py} | 10 +-- .../my_test_api_client/models/__init__.py | 6 +- .../my_test_api_client/models/a_model.py | 88 +++++++++---------- .../models/model_with_any_json_properties.py | 28 +++--- ...n_properties_additional_property_type0.py} | 10 +-- .../models/model_with_union_property.py | 24 ++--- .../model_with_union_property_inlined.py | 34 +++---- ...ith_union_property_inlined_fruit_type0.py} | 10 +-- ...ith_union_property_inlined_fruit_type1.py} | 10 +-- .../parser/properties/__init__.py | 2 +- 17 files changed, 211 insertions(+), 211 deletions(-) rename end_to_end_tests/golden-record-custom/custom_e2e/models/{model_with_any_json_properties_additional_property_item0.py => model_with_any_json_properties_additional_property_type0.py} (84%) rename end_to_end_tests/{golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py => golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_type0.py} (80%) rename end_to_end_tests/golden-record-custom/custom_e2e/models/{model_with_union_property_inlined_fruit_item1.py => model_with_union_property_inlined_fruit_type1.py} (81%) rename end_to_end_tests/golden-record/my_test_api_client/models/{model_with_any_json_properties_additional_property_item0.py => model_with_any_json_properties_additional_property_type0.py} (84%) rename end_to_end_tests/{golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py => golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type0.py} (80%) rename end_to_end_tests/golden-record/my_test_api_client/models/{model_with_union_property_inlined_fruit_item1.py => model_with_union_property_inlined_fruit_type1.py} (81%) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py index 391bca440..2679739df 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py @@ -17,13 +17,13 @@ ) from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed from .model_with_any_json_properties import ModelWithAnyJsonProperties -from .model_with_any_json_properties_additional_property_item0 import ModelWithAnyJsonPropertiesAdditionalPropertyItem0 +from .model_with_any_json_properties_additional_property_type0 import ModelWithAnyJsonPropertiesAdditionalPropertyType0 from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder from .model_with_union_property import ModelWithUnionProperty from .model_with_union_property_inlined import ModelWithUnionPropertyInlined -from .model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 -from .model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 +from .model_with_union_property_inlined_fruit_type0 import ModelWithUnionPropertyInlinedFruitType0 +from .model_with_union_property_inlined_fruit_type1 import ModelWithUnionPropertyInlinedFruitType1 from .test_inline_objects_json_body import TestInlineObjectsJsonBody from .test_inline_objects_response_200 import TestInlineObjectsResponse_200 from .validation_error import ValidationError diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index f2e934910..91b62c01b 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -176,20 +176,20 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_a_camel_date_time(data: object) -> Union[datetime.date, datetime.datetime]: try: - a_camel_date_time_item0: datetime.datetime + a_camel_date_time_type0: datetime.datetime if not isinstance(data, str): raise TypeError() - a_camel_date_time_item0 = isoparse(data) + a_camel_date_time_type0 = isoparse(data) - return a_camel_date_time_item0 + return a_camel_date_time_type0 except: # noqa: E722 pass if not isinstance(data, str): raise TypeError() - a_camel_date_time_item1: datetime.date - a_camel_date_time_item1 = isoparse(data).date() + a_camel_date_time_type1: datetime.date + a_camel_date_time_type1 = isoparse(data).date() - return a_camel_date_time_item1 + return a_camel_date_time_type1 a_camel_date_time = _parse_a_camel_date_time(d.pop("aCamelDateTime")) @@ -199,20 +199,20 @@ def _parse_a_camel_date_time(data: object) -> Union[datetime.date, datetime.date def _parse_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty]: try: - one_of_models_item0: FreeFormModel + one_of_models_type0: FreeFormModel if not isinstance(data, dict): raise TypeError() - one_of_models_item0 = FreeFormModel.from_dict(data) + one_of_models_type0 = FreeFormModel.from_dict(data) - return one_of_models_item0 + return one_of_models_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - one_of_models_item1: ModelWithUnionProperty - one_of_models_item1 = ModelWithUnionProperty.from_dict(data) + one_of_models_type1: ModelWithUnionProperty + one_of_models_type1 = ModelWithUnionProperty.from_dict(data) - return one_of_models_item1 + return one_of_models_type1 one_of_models = _parse_one_of_models(d.pop("one_of_models")) @@ -252,20 +252,20 @@ def _parse_nullable_one_of_models(data: object) -> Union[FreeFormModel, ModelWit if data is None: return data try: - nullable_one_of_models_item0: FreeFormModel + nullable_one_of_models_type0: FreeFormModel if not isinstance(data, dict): raise TypeError() - nullable_one_of_models_item0 = FreeFormModel.from_dict(data) + nullable_one_of_models_type0 = FreeFormModel.from_dict(data) - return nullable_one_of_models_item0 + return nullable_one_of_models_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - nullable_one_of_models_item1: ModelWithUnionProperty - nullable_one_of_models_item1 = ModelWithUnionProperty.from_dict(data) + nullable_one_of_models_type1: ModelWithUnionProperty + nullable_one_of_models_type1 = ModelWithUnionProperty.from_dict(data) - return nullable_one_of_models_item1 + return nullable_one_of_models_type1 nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) @@ -273,26 +273,26 @@ def _parse_not_required_one_of_models(data: object) -> Union[FreeFormModel, Mode if isinstance(data, Unset): return data try: - not_required_one_of_models_item0: Union[Unset, FreeFormModel] + not_required_one_of_models_type0: Union[Unset, FreeFormModel] if not isinstance(data, dict): raise TypeError() - not_required_one_of_models_item0 = UNSET - _not_required_one_of_models_item0 = data - if not isinstance(_not_required_one_of_models_item0, Unset): - not_required_one_of_models_item0 = FreeFormModel.from_dict(_not_required_one_of_models_item0) + not_required_one_of_models_type0 = UNSET + _not_required_one_of_models_type0 = data + if not isinstance(_not_required_one_of_models_type0, Unset): + not_required_one_of_models_type0 = FreeFormModel.from_dict(_not_required_one_of_models_type0) - return not_required_one_of_models_item0 + return not_required_one_of_models_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - not_required_one_of_models_item1: Union[Unset, ModelWithUnionProperty] - not_required_one_of_models_item1 = UNSET - _not_required_one_of_models_item1 = data - if not isinstance(_not_required_one_of_models_item1, Unset): - not_required_one_of_models_item1 = ModelWithUnionProperty.from_dict(_not_required_one_of_models_item1) + not_required_one_of_models_type1: Union[Unset, ModelWithUnionProperty] + not_required_one_of_models_type1 = UNSET + _not_required_one_of_models_type1 = data + if not isinstance(_not_required_one_of_models_type1, Unset): + not_required_one_of_models_type1 = ModelWithUnionProperty.from_dict(_not_required_one_of_models_type1) - return not_required_one_of_models_item1 + return not_required_one_of_models_type1 not_required_one_of_models = _parse_not_required_one_of_models(d.pop("not_required_one_of_models", UNSET)) @@ -304,31 +304,31 @@ def _parse_not_required_nullable_one_of_models( if isinstance(data, Unset): return data try: - not_required_nullable_one_of_models_item0: Union[Unset, FreeFormModel] + not_required_nullable_one_of_models_type0: Union[Unset, FreeFormModel] if not isinstance(data, dict): raise TypeError() - not_required_nullable_one_of_models_item0 = UNSET - _not_required_nullable_one_of_models_item0 = data - if not isinstance(_not_required_nullable_one_of_models_item0, Unset): - not_required_nullable_one_of_models_item0 = FreeFormModel.from_dict( - _not_required_nullable_one_of_models_item0 + not_required_nullable_one_of_models_type0 = UNSET + _not_required_nullable_one_of_models_type0 = data + if not isinstance(_not_required_nullable_one_of_models_type0, Unset): + not_required_nullable_one_of_models_type0 = FreeFormModel.from_dict( + _not_required_nullable_one_of_models_type0 ) - return not_required_nullable_one_of_models_item0 + return not_required_nullable_one_of_models_type0 except: # noqa: E722 pass try: - not_required_nullable_one_of_models_item1: Union[Unset, ModelWithUnionProperty] + not_required_nullable_one_of_models_type1: Union[Unset, ModelWithUnionProperty] if not isinstance(data, dict): raise TypeError() - not_required_nullable_one_of_models_item1 = UNSET - _not_required_nullable_one_of_models_item1 = data - if not isinstance(_not_required_nullable_one_of_models_item1, Unset): - not_required_nullable_one_of_models_item1 = ModelWithUnionProperty.from_dict( - _not_required_nullable_one_of_models_item1 + not_required_nullable_one_of_models_type1 = UNSET + _not_required_nullable_one_of_models_type1 = data + if not isinstance(_not_required_nullable_one_of_models_type1, Unset): + not_required_nullable_one_of_models_type1 = ModelWithUnionProperty.from_dict( + _not_required_nullable_one_of_models_type1 ) - return not_required_nullable_one_of_models_item1 + return not_required_nullable_one_of_models_type1 except: # noqa: E722 pass return cast(Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str], data) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py index 1baae4dd0..59b3ddb46 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties.py @@ -2,8 +2,8 @@ import attr -from ..models.model_with_any_json_properties_additional_property_item0 import ( - ModelWithAnyJsonPropertiesAdditionalPropertyItem0, +from ..models.model_with_any_json_properties_additional_property_type0 import ( + ModelWithAnyJsonPropertiesAdditionalPropertyType0, ) T = TypeVar("T", bound="ModelWithAnyJsonProperties") @@ -14,14 +14,14 @@ class ModelWithAnyJsonProperties: """ """ additional_properties: Dict[ - str, Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str] + str, Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str] ] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): - if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyItem0): + if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyType0): field_dict[prop_name] = prop.to_dict() elif isinstance(prop, list): @@ -44,27 +44,27 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: object, - ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str]: try: - additional_property_item0: ModelWithAnyJsonPropertiesAdditionalPropertyItem0 + additional_property_type0: ModelWithAnyJsonPropertiesAdditionalPropertyType0 if not isinstance(data, dict): raise TypeError() - additional_property_item0 = ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) + additional_property_type0 = ModelWithAnyJsonPropertiesAdditionalPropertyType0.from_dict(data) - return additional_property_item0 + return additional_property_type0 except: # noqa: E722 pass try: - additional_property_item1: List[str] + additional_property_type1: List[str] if not isinstance(data, list): raise TypeError() - additional_property_item1 = cast(List[str], data) + additional_property_type1 = cast(List[str], data) - return additional_property_item1 + return additional_property_type1 except: # noqa: E722 pass return cast( - Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str], data + Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str], data ) additional_property = _parse_additional_property(prop_dict) @@ -80,13 +80,13 @@ def additional_keys(self) -> List[str]: def __getitem__( self, key: str - ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str]: return self.additional_properties[key] def __setitem__( self, key: str, - value: Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str], + value: Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str], ) -> None: self.additional_properties[key] = value diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_item0.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_type0.py similarity index 84% rename from end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_item0.py rename to end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_type0.py index 3a8334ae4..76649bf90 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_item0.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_any_json_properties_additional_property_type0.py @@ -2,11 +2,11 @@ import attr -T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyItem0") +T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyType0") @attr.s(auto_attribs=True) -class ModelWithAnyJsonPropertiesAdditionalPropertyItem0: +class ModelWithAnyJsonPropertiesAdditionalPropertyType0: """ """ additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) @@ -22,10 +22,10 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - model_with_any_json_properties_additional_property_item0 = cls() + model_with_any_json_properties_additional_property_type0 = cls() - model_with_any_json_properties_additional_property_item0.additional_properties = d - return model_with_any_json_properties_additional_property_item0 + model_with_any_json_properties_additional_property_type0.additional_properties = d + return model_with_any_json_properties_additional_property_type0 @property def additional_keys(self) -> List[str]: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index a3aee4ef0..a3f049533 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -44,26 +44,26 @@ def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]: if isinstance(data, Unset): return data try: - a_property_item0: Union[Unset, AnEnum] + a_property_type0: Union[Unset, AnEnum] if not isinstance(data, str): raise TypeError() - a_property_item0 = UNSET - _a_property_item0 = data - if not isinstance(_a_property_item0, Unset): - a_property_item0 = AnEnum(_a_property_item0) + a_property_type0 = UNSET + _a_property_type0 = data + if not isinstance(_a_property_type0, Unset): + a_property_type0 = AnEnum(_a_property_type0) - return a_property_item0 + return a_property_type0 except: # noqa: E722 pass if not isinstance(data, int): raise TypeError() - a_property_item1: Union[Unset, AnIntEnum] - a_property_item1 = UNSET - _a_property_item1 = data - if not isinstance(_a_property_item1, Unset): - a_property_item1 = AnIntEnum(_a_property_item1) + a_property_type1: Union[Unset, AnIntEnum] + a_property_type1 = UNSET + _a_property_type1 = data + if not isinstance(_a_property_type1, Unset): + a_property_type1 = AnIntEnum(_a_property_type1) - return a_property_item1 + return a_property_type1 a_property = _parse_a_property(d.pop("a_property", UNSET)) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py index 6ff76a918..2349d541d 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined.py @@ -2,8 +2,8 @@ import attr -from ..models.model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 -from ..models.model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 +from ..models.model_with_union_property_inlined_fruit_type0 import ModelWithUnionPropertyInlinedFruitType0 +from ..models.model_with_union_property_inlined_fruit_type1 import ModelWithUnionPropertyInlinedFruitType1 from ..types import UNSET, Unset T = TypeVar("T", bound="ModelWithUnionPropertyInlined") @@ -13,13 +13,13 @@ class ModelWithUnionPropertyInlined: """ """ - fruit: Union[ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1, Unset] = UNSET + fruit: Union[ModelWithUnionPropertyInlinedFruitType0, ModelWithUnionPropertyInlinedFruitType1, Unset] = UNSET def to_dict(self) -> Dict[str, Any]: fruit: Union[Dict[str, Any], Unset] if isinstance(self.fruit, Unset): fruit = UNSET - elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitItem0): + elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitType0): fruit = UNSET if not isinstance(self.fruit, Unset): fruit = self.fruit.to_dict() @@ -42,30 +42,30 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_fruit( data: object, - ) -> Union[ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1, Unset]: + ) -> Union[ModelWithUnionPropertyInlinedFruitType0, ModelWithUnionPropertyInlinedFruitType1, Unset]: if isinstance(data, Unset): return data try: - fruit_item0: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0] + fruit_type0: Union[Unset, ModelWithUnionPropertyInlinedFruitType0] if not isinstance(data, dict): raise TypeError() - fruit_item0 = UNSET - _fruit_item0 = data - if not isinstance(_fruit_item0, Unset): - fruit_item0 = ModelWithUnionPropertyInlinedFruitItem0.from_dict(_fruit_item0) + fruit_type0 = UNSET + _fruit_type0 = data + if not isinstance(_fruit_type0, Unset): + fruit_type0 = ModelWithUnionPropertyInlinedFruitType0.from_dict(_fruit_type0) - return fruit_item0 + return fruit_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - fruit_item1: Union[Unset, ModelWithUnionPropertyInlinedFruitItem1] - fruit_item1 = UNSET - _fruit_item1 = data - if not isinstance(_fruit_item1, Unset): - fruit_item1 = ModelWithUnionPropertyInlinedFruitItem1.from_dict(_fruit_item1) + fruit_type1: Union[Unset, ModelWithUnionPropertyInlinedFruitType1] + fruit_type1 = UNSET + _fruit_type1 = data + if not isinstance(_fruit_type1, Unset): + fruit_type1 = ModelWithUnionPropertyInlinedFruitType1.from_dict(_fruit_type1) - return fruit_item1 + return fruit_type1 fruit = _parse_fruit(d.pop("fruit", UNSET)) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_type0.py similarity index 80% rename from end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py rename to end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_type0.py index ab82f5f01..da6d11826 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item0.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_type0.py @@ -4,11 +4,11 @@ from ..types import UNSET, Unset -T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem0") +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitType0") @attr.s(auto_attribs=True) -class ModelWithUnionPropertyInlinedFruitItem0: +class ModelWithUnionPropertyInlinedFruitType0: """ """ apples: Union[Unset, str] = UNSET @@ -30,12 +30,12 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() apples = d.pop("apples", UNSET) - model_with_union_property_inlined_fruit_item0 = cls( + model_with_union_property_inlined_fruit_type0 = cls( apples=apples, ) - model_with_union_property_inlined_fruit_item0.additional_properties = d - return model_with_union_property_inlined_fruit_item0 + model_with_union_property_inlined_fruit_type0.additional_properties = d + return model_with_union_property_inlined_fruit_type0 @property def additional_keys(self) -> List[str]: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item1.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_type1.py similarity index 81% rename from end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item1.py rename to end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_type1.py index df2f1c7bd..32a9b1727 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item1.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_type1.py @@ -4,11 +4,11 @@ from ..types import UNSET, Unset -T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem1") +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitType1") @attr.s(auto_attribs=True) -class ModelWithUnionPropertyInlinedFruitItem1: +class ModelWithUnionPropertyInlinedFruitType1: """ """ bananas: Union[Unset, str] = UNSET @@ -30,12 +30,12 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() bananas = d.pop("bananas", UNSET) - model_with_union_property_inlined_fruit_item1 = cls( + model_with_union_property_inlined_fruit_type1 = cls( bananas=bananas, ) - model_with_union_property_inlined_fruit_item1.additional_properties = d - return model_with_union_property_inlined_fruit_item1 + model_with_union_property_inlined_fruit_type1.additional_properties = d + return model_with_union_property_inlined_fruit_type1 @property def additional_keys(self) -> List[str]: 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 391bca440..2679739df 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 @@ -17,13 +17,13 @@ ) from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed from .model_with_any_json_properties import ModelWithAnyJsonProperties -from .model_with_any_json_properties_additional_property_item0 import ModelWithAnyJsonPropertiesAdditionalPropertyItem0 +from .model_with_any_json_properties_additional_property_type0 import ModelWithAnyJsonPropertiesAdditionalPropertyType0 from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder from .model_with_union_property import ModelWithUnionProperty from .model_with_union_property_inlined import ModelWithUnionPropertyInlined -from .model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 -from .model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 +from .model_with_union_property_inlined_fruit_type0 import ModelWithUnionPropertyInlinedFruitType0 +from .model_with_union_property_inlined_fruit_type1 import ModelWithUnionPropertyInlinedFruitType1 from .test_inline_objects_json_body import TestInlineObjectsJsonBody from .test_inline_objects_response_200 import TestInlineObjectsResponse_200 from .validation_error import ValidationError diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index f2e934910..91b62c01b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -176,20 +176,20 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_a_camel_date_time(data: object) -> Union[datetime.date, datetime.datetime]: try: - a_camel_date_time_item0: datetime.datetime + a_camel_date_time_type0: datetime.datetime if not isinstance(data, str): raise TypeError() - a_camel_date_time_item0 = isoparse(data) + a_camel_date_time_type0 = isoparse(data) - return a_camel_date_time_item0 + return a_camel_date_time_type0 except: # noqa: E722 pass if not isinstance(data, str): raise TypeError() - a_camel_date_time_item1: datetime.date - a_camel_date_time_item1 = isoparse(data).date() + a_camel_date_time_type1: datetime.date + a_camel_date_time_type1 = isoparse(data).date() - return a_camel_date_time_item1 + return a_camel_date_time_type1 a_camel_date_time = _parse_a_camel_date_time(d.pop("aCamelDateTime")) @@ -199,20 +199,20 @@ def _parse_a_camel_date_time(data: object) -> Union[datetime.date, datetime.date def _parse_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty]: try: - one_of_models_item0: FreeFormModel + one_of_models_type0: FreeFormModel if not isinstance(data, dict): raise TypeError() - one_of_models_item0 = FreeFormModel.from_dict(data) + one_of_models_type0 = FreeFormModel.from_dict(data) - return one_of_models_item0 + return one_of_models_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - one_of_models_item1: ModelWithUnionProperty - one_of_models_item1 = ModelWithUnionProperty.from_dict(data) + one_of_models_type1: ModelWithUnionProperty + one_of_models_type1 = ModelWithUnionProperty.from_dict(data) - return one_of_models_item1 + return one_of_models_type1 one_of_models = _parse_one_of_models(d.pop("one_of_models")) @@ -252,20 +252,20 @@ def _parse_nullable_one_of_models(data: object) -> Union[FreeFormModel, ModelWit if data is None: return data try: - nullable_one_of_models_item0: FreeFormModel + nullable_one_of_models_type0: FreeFormModel if not isinstance(data, dict): raise TypeError() - nullable_one_of_models_item0 = FreeFormModel.from_dict(data) + nullable_one_of_models_type0 = FreeFormModel.from_dict(data) - return nullable_one_of_models_item0 + return nullable_one_of_models_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - nullable_one_of_models_item1: ModelWithUnionProperty - nullable_one_of_models_item1 = ModelWithUnionProperty.from_dict(data) + nullable_one_of_models_type1: ModelWithUnionProperty + nullable_one_of_models_type1 = ModelWithUnionProperty.from_dict(data) - return nullable_one_of_models_item1 + return nullable_one_of_models_type1 nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models")) @@ -273,26 +273,26 @@ def _parse_not_required_one_of_models(data: object) -> Union[FreeFormModel, Mode if isinstance(data, Unset): return data try: - not_required_one_of_models_item0: Union[Unset, FreeFormModel] + not_required_one_of_models_type0: Union[Unset, FreeFormModel] if not isinstance(data, dict): raise TypeError() - not_required_one_of_models_item0 = UNSET - _not_required_one_of_models_item0 = data - if not isinstance(_not_required_one_of_models_item0, Unset): - not_required_one_of_models_item0 = FreeFormModel.from_dict(_not_required_one_of_models_item0) + not_required_one_of_models_type0 = UNSET + _not_required_one_of_models_type0 = data + if not isinstance(_not_required_one_of_models_type0, Unset): + not_required_one_of_models_type0 = FreeFormModel.from_dict(_not_required_one_of_models_type0) - return not_required_one_of_models_item0 + return not_required_one_of_models_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - not_required_one_of_models_item1: Union[Unset, ModelWithUnionProperty] - not_required_one_of_models_item1 = UNSET - _not_required_one_of_models_item1 = data - if not isinstance(_not_required_one_of_models_item1, Unset): - not_required_one_of_models_item1 = ModelWithUnionProperty.from_dict(_not_required_one_of_models_item1) + not_required_one_of_models_type1: Union[Unset, ModelWithUnionProperty] + not_required_one_of_models_type1 = UNSET + _not_required_one_of_models_type1 = data + if not isinstance(_not_required_one_of_models_type1, Unset): + not_required_one_of_models_type1 = ModelWithUnionProperty.from_dict(_not_required_one_of_models_type1) - return not_required_one_of_models_item1 + return not_required_one_of_models_type1 not_required_one_of_models = _parse_not_required_one_of_models(d.pop("not_required_one_of_models", UNSET)) @@ -304,31 +304,31 @@ def _parse_not_required_nullable_one_of_models( if isinstance(data, Unset): return data try: - not_required_nullable_one_of_models_item0: Union[Unset, FreeFormModel] + not_required_nullable_one_of_models_type0: Union[Unset, FreeFormModel] if not isinstance(data, dict): raise TypeError() - not_required_nullable_one_of_models_item0 = UNSET - _not_required_nullable_one_of_models_item0 = data - if not isinstance(_not_required_nullable_one_of_models_item0, Unset): - not_required_nullable_one_of_models_item0 = FreeFormModel.from_dict( - _not_required_nullable_one_of_models_item0 + not_required_nullable_one_of_models_type0 = UNSET + _not_required_nullable_one_of_models_type0 = data + if not isinstance(_not_required_nullable_one_of_models_type0, Unset): + not_required_nullable_one_of_models_type0 = FreeFormModel.from_dict( + _not_required_nullable_one_of_models_type0 ) - return not_required_nullable_one_of_models_item0 + return not_required_nullable_one_of_models_type0 except: # noqa: E722 pass try: - not_required_nullable_one_of_models_item1: Union[Unset, ModelWithUnionProperty] + not_required_nullable_one_of_models_type1: Union[Unset, ModelWithUnionProperty] if not isinstance(data, dict): raise TypeError() - not_required_nullable_one_of_models_item1 = UNSET - _not_required_nullable_one_of_models_item1 = data - if not isinstance(_not_required_nullable_one_of_models_item1, Unset): - not_required_nullable_one_of_models_item1 = ModelWithUnionProperty.from_dict( - _not_required_nullable_one_of_models_item1 + not_required_nullable_one_of_models_type1 = UNSET + _not_required_nullable_one_of_models_type1 = data + if not isinstance(_not_required_nullable_one_of_models_type1, Unset): + not_required_nullable_one_of_models_type1 = ModelWithUnionProperty.from_dict( + _not_required_nullable_one_of_models_type1 ) - return not_required_nullable_one_of_models_item1 + return not_required_nullable_one_of_models_type1 except: # noqa: E722 pass return cast(Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str], data) 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 1baae4dd0..59b3ddb46 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 @@ -2,8 +2,8 @@ import attr -from ..models.model_with_any_json_properties_additional_property_item0 import ( - ModelWithAnyJsonPropertiesAdditionalPropertyItem0, +from ..models.model_with_any_json_properties_additional_property_type0 import ( + ModelWithAnyJsonPropertiesAdditionalPropertyType0, ) T = TypeVar("T", bound="ModelWithAnyJsonProperties") @@ -14,14 +14,14 @@ class ModelWithAnyJsonProperties: """ """ additional_properties: Dict[ - str, Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str] + str, Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str] ] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): - if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyItem0): + if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyType0): field_dict[prop_name] = prop.to_dict() elif isinstance(prop, list): @@ -44,27 +44,27 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_additional_property( data: object, - ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str]: try: - additional_property_item0: ModelWithAnyJsonPropertiesAdditionalPropertyItem0 + additional_property_type0: ModelWithAnyJsonPropertiesAdditionalPropertyType0 if not isinstance(data, dict): raise TypeError() - additional_property_item0 = ModelWithAnyJsonPropertiesAdditionalPropertyItem0.from_dict(data) + additional_property_type0 = ModelWithAnyJsonPropertiesAdditionalPropertyType0.from_dict(data) - return additional_property_item0 + return additional_property_type0 except: # noqa: E722 pass try: - additional_property_item1: List[str] + additional_property_type1: List[str] if not isinstance(data, list): raise TypeError() - additional_property_item1 = cast(List[str], data) + additional_property_type1 = cast(List[str], data) - return additional_property_item1 + return additional_property_type1 except: # noqa: E722 pass return cast( - Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str], data + Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str], data ) additional_property = _parse_additional_property(prop_dict) @@ -80,13 +80,13 @@ def additional_keys(self) -> List[str]: def __getitem__( self, key: str - ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str]: + ) -> Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str]: return self.additional_properties[key] def __setitem__( self, key: str, - value: Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyItem0, bool, float, int, str], + value: Union[List[str], ModelWithAnyJsonPropertiesAdditionalPropertyType0, bool, float, int, str], ) -> None: self.additional_properties[key] = value diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_item0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type0.py similarity index 84% rename from end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_item0.py rename to end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type0.py index 3a8334ae4..76649bf90 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_item0.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type0.py @@ -2,11 +2,11 @@ import attr -T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyItem0") +T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyType0") @attr.s(auto_attribs=True) -class ModelWithAnyJsonPropertiesAdditionalPropertyItem0: +class ModelWithAnyJsonPropertiesAdditionalPropertyType0: """ """ additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) @@ -22,10 +22,10 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - model_with_any_json_properties_additional_property_item0 = cls() + model_with_any_json_properties_additional_property_type0 = cls() - model_with_any_json_properties_additional_property_item0.additional_properties = d - return model_with_any_json_properties_additional_property_item0 + model_with_any_json_properties_additional_property_type0.additional_properties = d + return model_with_any_json_properties_additional_property_type0 @property def additional_keys(self) -> List[str]: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index a3aee4ef0..a3f049533 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -44,26 +44,26 @@ def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]: if isinstance(data, Unset): return data try: - a_property_item0: Union[Unset, AnEnum] + a_property_type0: Union[Unset, AnEnum] if not isinstance(data, str): raise TypeError() - a_property_item0 = UNSET - _a_property_item0 = data - if not isinstance(_a_property_item0, Unset): - a_property_item0 = AnEnum(_a_property_item0) + a_property_type0 = UNSET + _a_property_type0 = data + if not isinstance(_a_property_type0, Unset): + a_property_type0 = AnEnum(_a_property_type0) - return a_property_item0 + return a_property_type0 except: # noqa: E722 pass if not isinstance(data, int): raise TypeError() - a_property_item1: Union[Unset, AnIntEnum] - a_property_item1 = UNSET - _a_property_item1 = data - if not isinstance(_a_property_item1, Unset): - a_property_item1 = AnIntEnum(_a_property_item1) + a_property_type1: Union[Unset, AnIntEnum] + a_property_type1 = UNSET + _a_property_type1 = data + if not isinstance(_a_property_type1, Unset): + a_property_type1 = AnIntEnum(_a_property_type1) - return a_property_item1 + return a_property_type1 a_property = _parse_a_property(d.pop("a_property", UNSET)) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py index 6ff76a918..2349d541d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py @@ -2,8 +2,8 @@ import attr -from ..models.model_with_union_property_inlined_fruit_item0 import ModelWithUnionPropertyInlinedFruitItem0 -from ..models.model_with_union_property_inlined_fruit_item1 import ModelWithUnionPropertyInlinedFruitItem1 +from ..models.model_with_union_property_inlined_fruit_type0 import ModelWithUnionPropertyInlinedFruitType0 +from ..models.model_with_union_property_inlined_fruit_type1 import ModelWithUnionPropertyInlinedFruitType1 from ..types import UNSET, Unset T = TypeVar("T", bound="ModelWithUnionPropertyInlined") @@ -13,13 +13,13 @@ class ModelWithUnionPropertyInlined: """ """ - fruit: Union[ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1, Unset] = UNSET + fruit: Union[ModelWithUnionPropertyInlinedFruitType0, ModelWithUnionPropertyInlinedFruitType1, Unset] = UNSET def to_dict(self) -> Dict[str, Any]: fruit: Union[Dict[str, Any], Unset] if isinstance(self.fruit, Unset): fruit = UNSET - elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitItem0): + elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitType0): fruit = UNSET if not isinstance(self.fruit, Unset): fruit = self.fruit.to_dict() @@ -42,30 +42,30 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def _parse_fruit( data: object, - ) -> Union[ModelWithUnionPropertyInlinedFruitItem0, ModelWithUnionPropertyInlinedFruitItem1, Unset]: + ) -> Union[ModelWithUnionPropertyInlinedFruitType0, ModelWithUnionPropertyInlinedFruitType1, Unset]: if isinstance(data, Unset): return data try: - fruit_item0: Union[Unset, ModelWithUnionPropertyInlinedFruitItem0] + fruit_type0: Union[Unset, ModelWithUnionPropertyInlinedFruitType0] if not isinstance(data, dict): raise TypeError() - fruit_item0 = UNSET - _fruit_item0 = data - if not isinstance(_fruit_item0, Unset): - fruit_item0 = ModelWithUnionPropertyInlinedFruitItem0.from_dict(_fruit_item0) + fruit_type0 = UNSET + _fruit_type0 = data + if not isinstance(_fruit_type0, Unset): + fruit_type0 = ModelWithUnionPropertyInlinedFruitType0.from_dict(_fruit_type0) - return fruit_item0 + return fruit_type0 except: # noqa: E722 pass if not isinstance(data, dict): raise TypeError() - fruit_item1: Union[Unset, ModelWithUnionPropertyInlinedFruitItem1] - fruit_item1 = UNSET - _fruit_item1 = data - if not isinstance(_fruit_item1, Unset): - fruit_item1 = ModelWithUnionPropertyInlinedFruitItem1.from_dict(_fruit_item1) + fruit_type1: Union[Unset, ModelWithUnionPropertyInlinedFruitType1] + fruit_type1 = UNSET + _fruit_type1 = data + if not isinstance(_fruit_type1, Unset): + fruit_type1 = ModelWithUnionPropertyInlinedFruitType1.from_dict(_fruit_type1) - return fruit_item1 + return fruit_type1 fruit = _parse_fruit(d.pop("fruit", UNSET)) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type0.py similarity index 80% rename from end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py rename to end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type0.py index ab82f5f01..da6d11826 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property_inlined_fruit_item0.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type0.py @@ -4,11 +4,11 @@ from ..types import UNSET, Unset -T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem0") +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitType0") @attr.s(auto_attribs=True) -class ModelWithUnionPropertyInlinedFruitItem0: +class ModelWithUnionPropertyInlinedFruitType0: """ """ apples: Union[Unset, str] = UNSET @@ -30,12 +30,12 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() apples = d.pop("apples", UNSET) - model_with_union_property_inlined_fruit_item0 = cls( + model_with_union_property_inlined_fruit_type0 = cls( apples=apples, ) - model_with_union_property_inlined_fruit_item0.additional_properties = d - return model_with_union_property_inlined_fruit_item0 + model_with_union_property_inlined_fruit_type0.additional_properties = d + return model_with_union_property_inlined_fruit_type0 @property def additional_keys(self) -> List[str]: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item1.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type1.py similarity index 81% rename from end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item1.py rename to end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type1.py index df2f1c7bd..32a9b1727 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_item1.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type1.py @@ -4,11 +4,11 @@ from ..types import UNSET, Unset -T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitItem1") +T = TypeVar("T", bound="ModelWithUnionPropertyInlinedFruitType1") @attr.s(auto_attribs=True) -class ModelWithUnionPropertyInlinedFruitItem1: +class ModelWithUnionPropertyInlinedFruitType1: """ """ bananas: Union[Unset, str] = UNSET @@ -30,12 +30,12 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() bananas = d.pop("bananas", UNSET) - model_with_union_property_inlined_fruit_item1 = cls( + model_with_union_property_inlined_fruit_type1 = cls( bananas=bananas, ) - model_with_union_property_inlined_fruit_item1.additional_properties = d - return model_with_union_property_inlined_fruit_item1 + model_with_union_property_inlined_fruit_type1.additional_properties = d + return model_with_union_property_inlined_fruit_type1 @property def additional_keys(self) -> List[str]: diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 162772b13..f3cfa7ff9 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -415,7 +415,7 @@ def build_union_property( sub_properties: List[Property] = [] for i, sub_prop_data in enumerate(chain(data.anyOf, data.oneOf)): sub_prop, schemas = property_from_data( - name=f"{name}_item{i}", required=required, data=sub_prop_data, schemas=schemas, parent_name=parent_name + name=f"{name}_type{i}", required=required, data=sub_prop_data, schemas=schemas, parent_name=parent_name ) if isinstance(sub_prop, PropertyError): return PropertyError(detail=f"Invalid property in union {name}", data=sub_prop_data), schemas From 0d90970ec363561ce055f2c969ef49a90939c58e Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Mon, 15 Mar 2021 10:02:36 -0400 Subject: [PATCH 17/17] Add another unit test --- tests/test_parser/test_properties/test_init.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 977282a56..03515ea63 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -313,6 +313,22 @@ def test_get_base_type_string(self, mocker): ) assert p.get_base_type_string() == "Union[inner_type_string_1, inner_type_string_2]" + def test_get_base_type_string_one_element(self, mocker): + from openapi_python_client.parser.properties import UnionProperty + + inner_property_1 = mocker.MagicMock() + inner_property_1.get_type_string.side_effect = ( + lambda no_optional=False, json=False: "inner_json_type_string_1" if json else "inner_type_string_1" + ) + p = UnionProperty( + name="test", + required=False, + default=None, + inner_properties=[inner_property_1], + nullable=True, + ) + assert p.get_base_type_string() == "inner_type_string_1" + def test_get_base_json_type_string(self, mocker): from openapi_python_client.parser.properties import UnionProperty