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..53e2d1def 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,8 @@ 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[ModelWithUnionProperty, Unset] = UNSET, + required_model_prop: ModelWithUnionProperty, ) -> Response[Union[None, HTTPValidationError]]: json_datetime_prop: Union[Unset, str] = UNSET @@ -89,6 +92,12 @@ def httpx_request( if not isinstance(enum_prop, Unset): json_enum_prop = enum_prop + json_model_prop: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(model_prop, Unset): + json_model_prop = model_prop.to_dict() + + json_required_model_prop = required_model_prop.to_dict() + params: Dict[str, Any] = { "string_prop": string_prop, "datetime_prop": json_datetime_prop, @@ -101,6 +110,9 @@ def httpx_request( "union_prop_with_ref": json_union_prop_with_ref, "enum_prop": json_enum_prop, } + if not isinstance(json_model_prop, Unset): + params.update(json_model_prop) + params.update(json_required_model_prop) params = {k: v for k, v in params.items() if v is not UNSET and v is not None} response = client.request( 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..5f5f5dac6 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,8 @@ 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[ModelWithUnionProperty, Unset] = UNSET, + required_model_prop: ModelWithUnionProperty, ) -> Dict[str, Any]: url = "{}/tests/defaults".format(client.base_url) @@ -65,6 +68,12 @@ def _get_kwargs( if not isinstance(enum_prop, Unset): json_enum_prop = enum_prop + json_model_prop: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(model_prop, Unset): + json_model_prop = model_prop.to_dict() + + json_required_model_prop = required_model_prop.to_dict() + params: Dict[str, Any] = { "string_prop": string_prop, "datetime_prop": json_datetime_prop, @@ -77,6 +86,9 @@ def _get_kwargs( "union_prop_with_ref": json_union_prop_with_ref, "enum_prop": json_enum_prop, } + if not isinstance(json_model_prop, Unset): + params.update(json_model_prop) + params.update(json_required_model_prop) params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { @@ -122,6 +134,8 @@ 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[ModelWithUnionProperty, Unset] = UNSET, + required_model_prop: ModelWithUnionProperty, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -135,6 +149,8 @@ def sync_detailed( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, + required_model_prop=required_model_prop, ) response = httpx.post( @@ -157,6 +173,8 @@ 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[ModelWithUnionProperty, Unset] = UNSET, + required_model_prop: ModelWithUnionProperty, ) -> Optional[Union[None, HTTPValidationError]]: """ """ @@ -172,6 +190,8 @@ def sync( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, + required_model_prop=required_model_prop, ).parsed @@ -188,6 +208,8 @@ 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[ModelWithUnionProperty, Unset] = UNSET, + required_model_prop: ModelWithUnionProperty, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -201,6 +223,8 @@ async def asyncio_detailed( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, + required_model_prop=required_model_prop, ) async with httpx.AsyncClient() as _client: @@ -222,6 +246,8 @@ 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[ModelWithUnionProperty, Unset] = UNSET, + required_model_prop: ModelWithUnionProperty, ) -> Optional[Union[None, HTTPValidationError]]: """ """ @@ -238,5 +264,7 @@ async def asyncio( union_prop=union_prop, union_prop_with_ref=union_prop_with_ref, enum_prop=enum_prop, + model_prop=model_prop, + required_model_prop=required_model_prop, ) ).parsed diff --git a/end_to_end_tests/openapi.json b/end_to_end_tests/openapi.json index 196538f19..881fe2be5 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -396,6 +396,22 @@ }, "name": "enum_prop", "in": "query" + }, + { + "required": false, + "schema": { + "$ref": "#/components/schemas/ModelWithUnionProperty" + }, + "name": "model_prop", + "in": "query" + }, + { + "required": true, + "schema": { + "$ref": "#/components/schemas/ModelWithUnionProperty" + }, + "name": "required_model_prop", + "in": "query" } ], "responses": { diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py index d5b15e866..1cf3e455c 100644 --- a/openapi_python_client/parser/properties/model_property.py +++ b/openapi_python_client/parser/properties/model_property.py @@ -19,6 +19,7 @@ class ModelProperty(Property): additional_properties: Union[bool, Property] template: ClassVar[str] = "model_property.py.jinja" + json_is_dict: ClassVar[bool] = True def get_type_string(self, no_optional: bool = False) -> str: """ Get a string representation of type that should be used when declaring this property """ diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index 0b7047551..a94af72ba 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -28,6 +28,7 @@ class Property: python_name: str = attr.ib(init=False) template: ClassVar[Optional[str]] = None + json_is_dict: ClassVar[bool] = False def __attrs_post_init__(self) -> None: object.__setattr__(self, "python_name", utils.to_valid_python_identifier(utils.snake_case(self.name))) diff --git a/openapi_python_client/templates/endpoint_macros.py.jinja b/openapi_python_client/templates/endpoint_macros.py.jinja index 2b86668e3..113c410e2 100644 --- a/openapi_python_client/templates/endpoint_macros.py.jinja +++ b/openapi_python_client/templates/endpoint_macros.py.jinja @@ -22,13 +22,26 @@ if {{ parameter.python_name }} is not UNSET: {% endfor %} params: Dict[str, Any] = { {% for property in endpoint.query_parameters %} - {% if property.template %} + {% if not property.json_is_dict %} + {% if property.template %} "{{ property.name }}": {{ "json_" + property.python_name }}, - {% else %} + {% else %} "{{ property.name }}": {{ property.python_name }}, + {% endif %} {% endif %} {% endfor %} } + {% for property in endpoint.query_parameters %} + {% if property.json_is_dict %} + {% set property_name = "json_" + property.python_name %} + {% if property.required and not property.nullable %} +params.update({{ property_name }}) + {% else %} +if {% if not property.required %}not isinstance({{ property_name }}, Unset){% endif %}{% if not property.required and property.nullable %} and {% endif %}{% if property.nullable %}{{ property_name }} is not None{% endif %}: + params.update({{ property_name }}) + {% endif %} + {% endif %} + {% endfor %} params = {k: v for k, v in params.items() if v is not UNSET and v is not None} {% endif %} {% endmacro %}