diff --git a/.changeset/read_only_props.md b/.changeset/read_only_props.md new file mode 100644 index 000000000..d2279e44a --- /dev/null +++ b/.changeset/read_only_props.md @@ -0,0 +1,11 @@ +--- +default: minor +--- + +# Omitting `readOnly` properties from request bodies + +OpenAPI allows any object property to be marked as `readOnly: true`, meaning that the server does not allow that property to be updated in a request. OpenAPI does not specifically define "updated", but some servers may interpret it to mean that no value should be serialized for the property at all. + +You can now tell `openapi-python-client` to omit read-only properties when serializing a schema, if and only if it is being serialized as part of a request body. This behavior is only enabled if you set `skip_sending_read_only_properties: true` in your configuration. + +Regardless of this option, read-only properties will still be deserialized normally in responses, and the behavior of the object's `to_dict` method is unchanged in all other contexts. diff --git a/README.md b/README.md index 871f3a296..ef489077f 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,14 @@ project_name_override: my-special-project-name package_name_override: my_extra_special_package_name ``` +### skip_sending_read_only_properties + +This option causes any properties that are marked with `readOnly: true` in the OpenAPI schema to be omitted from the JSON serialization of the schema, if and only if it is being serialized as part of a request body. + +```yaml +skip_sending_read_only_properties: true +``` + ### field_prefix When generating properties, the `name` attribute of the OpenAPI schema will be used. When the `name` is not a valid Python identifier (e.g. begins with a number) this string will be prepended. Defaults to "field\_". It will also be used to prefix fields in schema starting with "_" in order to avoid ambiguous semantics. diff --git a/end_to_end_tests/config-skip-read-only.yml b/end_to_end_tests/config-skip-read-only.yml new file mode 100644 index 000000000..46493122e --- /dev/null +++ b/end_to_end_tests/config-skip-read-only.yml @@ -0,0 +1 @@ +skip_sending_read_only_properties: true diff --git a/end_to_end_tests/golden-record-skip-read-only/.gitignore b/end_to_end_tests/golden-record-skip-read-only/.gitignore new file mode 100644 index 000000000..79a2c3d73 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/.gitignore @@ -0,0 +1,23 @@ +__pycache__/ +build/ +dist/ +*.egg-info/ +.pytest_cache/ + +# pyenv +.python-version + +# Environments +.env +.venv + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# JetBrains +.idea/ + +/coverage.xml +/.coverage diff --git a/end_to_end_tests/golden-record-skip-read-only/README.md b/end_to_end_tests/golden-record-skip-read-only/README.md new file mode 100644 index 000000000..909e04071 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/README.md @@ -0,0 +1,124 @@ +# my-read-only-properties-api-client +A client library for accessing My Read-Only Properties API + +## Usage +First, create a client: + +```python +from my_read_only_properties_api_client import Client + +client = Client(base_url="https://api.example.com") +``` + +If the endpoints you're going to hit require authentication, use `AuthenticatedClient` instead: + +```python +from my_read_only_properties_api_client import AuthenticatedClient + +client = AuthenticatedClient(base_url="https://api.example.com", token="SuperSecretToken") +``` + +Now call your endpoint and use your models: + +```python +from my_read_only_properties_api_client.models import MyDataModel +from my_read_only_properties_api_client.api.my_tag import get_my_data_model +from my_read_only_properties_api_client.types import Response + +with client as client: + my_data: MyDataModel = get_my_data_model.sync(client=client) + # or if you need more info (e.g. status_code) + response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client) +``` + +Or do the same thing with an async version: + +```python +from my_read_only_properties_api_client.models import MyDataModel +from my_read_only_properties_api_client.api.my_tag import get_my_data_model +from my_read_only_properties_api_client.types import Response + +async with client as client: + my_data: MyDataModel = await get_my_data_model.asyncio(client=client) + response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client) +``` + +By default, when you're calling an HTTPS API it will attempt to verify that SSL is working correctly. Using certificate verification is highly recommended most of the time, but sometimes you may need to authenticate to a server (especially an internal server) using a custom certificate bundle. + +```python +client = AuthenticatedClient( + base_url="https://internal_api.example.com", + token="SuperSecretToken", + verify_ssl="/path/to/certificate_bundle.pem", +) +``` + +You can also disable certificate validation altogether, but beware that **this is a security risk**. + +```python +client = AuthenticatedClient( + base_url="https://internal_api.example.com", + token="SuperSecretToken", + verify_ssl=False +) +``` + +Things to know: +1. Every path/method combo becomes a Python module with four functions: + 1. `sync`: Blocking request that returns parsed data (if successful) or `None` + 1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. + 1. `asyncio`: Like `sync` but async instead of blocking + 1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking + +1. All path/query params, and bodies become method arguments. +1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) +1. Any endpoint which did not have a tag will be in `my_read_only_properties_api_client.api.default` + +## Advanced customizations + +There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx.Client` or `httpx.AsyncClient` (depending on your use-case): + +```python +from my_read_only_properties_api_client import Client + +def log_request(request): + print(f"Request event hook: {request.method} {request.url} - Waiting for response") + +def log_response(response): + request = response.request + print(f"Response event hook: {request.method} {request.url} - Status {response.status_code}") + +client = Client( + base_url="https://api.example.com", + httpx_args={"event_hooks": {"request": [log_request], "response": [log_response]}}, +) + +# Or get the underlying httpx client to modify directly with client.get_httpx_client() or client.get_async_httpx_client() +``` + +You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url): + +```python +import httpx +from my_read_only_properties_api_client import Client + +client = Client( + base_url="https://api.example.com", +) +# Note that base_url needs to be re-set, as would any shared cookies, headers, etc. +client.set_httpx_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030")) +``` + +## Building / publishing this package +This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics: +1. Update the metadata in pyproject.toml (e.g. authors, version) +1. If you're using a private repository, configure it with Poetry + 1. `poetry config repositories. ` + 1. `poetry config http-basic. ` +1. Publish the client with `poetry publish --build -r ` or, if for public PyPI, just `poetry publish --build` + +If you want to install this client into another project without publishing it (e.g. for development) then: +1. If that project **is using Poetry**, you can simply do `poetry add ` from that project +1. If that project is not using Poetry: + 1. Build a wheel with `poetry build -f wheel` + 1. Install that wheel from the other project `pip install ` diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/__init__.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/__init__.py new file mode 100644 index 000000000..0f715317a --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/__init__.py @@ -0,0 +1,8 @@ +"""A client library for accessing My Read-Only Properties API""" + +from .client import AuthenticatedClient, Client + +__all__ = ( + "AuthenticatedClient", + "Client", +) diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/__init__.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/__init__.py new file mode 100644 index 000000000..81f9fa241 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/__init__.py @@ -0,0 +1 @@ +"""Contains methods for accessing the API""" diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/__init__.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/post_thing_json.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/post_thing_json.py new file mode 100644 index 000000000..ad2c0d0fc --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/post_thing_json.py @@ -0,0 +1,109 @@ +import threading +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.thing import Thing +from ...types import Response + + +def _get_kwargs( + *, + body: Thing, +) -> Dict[str, Any]: + headers: Dict[str, Any] = {} + + _kwargs: Dict[str, Any] = { + "method": "post", + "url": "/thing/json", + } + + try: + threading.local.openapi_serialization_context = {"request_body": True} + _body = body.to_dict() + + _kwargs["json"] = _body + headers["Content-Type"] = "application/json" + + finally: + del threading.local.openapi_serialization_context + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: + if response.status_code == 200: + return None + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: Union[AuthenticatedClient, Client], + body: Thing, +) -> Response[Any]: + """Post a thing in JSON + + Args: + body (Thing): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +async def asyncio_detailed( + *, + client: Union[AuthenticatedClient, Client], + body: Thing, +) -> Response[Any]: + """Post a thing in JSON + + Args: + body (Thing): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/post_thing_multipart.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/post_thing_multipart.py new file mode 100644 index 000000000..2b6457bac --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/api/things/post_thing_multipart.py @@ -0,0 +1,108 @@ +import threading +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.thing import Thing +from ...types import Response + + +def _get_kwargs( + *, + body: Thing, +) -> Dict[str, Any]: + headers: Dict[str, Any] = {} + + _kwargs: Dict[str, Any] = { + "method": "post", + "url": "/thing/multipart", + } + + try: + threading.local.openapi_serialization_context = {"request_body": True} + _body = body.to_multipart() + + _kwargs["files"] = _body + + finally: + del threading.local.openapi_serialization_context + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]: + if response.status_code == 200: + return None + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: Union[AuthenticatedClient, Client], + body: Thing, +) -> Response[Any]: + """Post a thing in multipart form data + + Args: + body (Thing): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +async def asyncio_detailed( + *, + client: Union[AuthenticatedClient, Client], + body: Thing, +) -> Response[Any]: + """Post a thing in multipart form data + + Args: + body (Thing): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/client.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/client.py new file mode 100644 index 000000000..0f6d15e84 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/client.py @@ -0,0 +1,268 @@ +import ssl +from typing import Any, Dict, Optional, Union + +import httpx +from attrs import define, evolve, field + + +@define +class Client: + """A class for keeping track of data related to the API + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str = field(alias="base_url") + _cookies: Dict[str, str] = field(factory=dict, kw_only=True, alias="cookies") + _headers: Dict[str, str] = field(factory=dict, kw_only=True, alias="headers") + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout") + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl") + _follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects") + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args") + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + def with_headers(self, headers: Dict[str, str]) -> "Client": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "Client": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: httpx.Timeout) -> "Client": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_httpx_client(self, client: httpx.Client) -> "Client": + """Manually set the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_httpx_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_httpx_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for internal httpx.Client (see httpx docs)""" + self.get_httpx_client().__exit__(*args, **kwargs) + + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_httpx_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._async_client + + async def __aenter__(self) -> "Client": + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" + await self.get_async_httpx_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" + await self.get_async_httpx_client().__aexit__(*args, **kwargs) + + +@define +class AuthenticatedClient: + """A Client which has been authenticated for use on secured endpoints + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + token: The token to use for authentication + prefix: The prefix to use for the Authorization header + auth_header_name: The name of the Authorization header + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str = field(alias="base_url") + _cookies: Dict[str, str] = field(factory=dict, kw_only=True, alias="cookies") + _headers: Dict[str, str] = field(factory=dict, kw_only=True, alias="headers") + _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout") + _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl") + _follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects") + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args") + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + token: str + prefix: str = "Bearer" + auth_header_name: str = "Authorization" + + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": + """Manually set the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_httpx_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._client + + def __enter__(self) -> "AuthenticatedClient": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_httpx_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for internal httpx.Client (see httpx docs)""" + self.get_httpx_client().__exit__(*args, **kwargs) + + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_httpx_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._async_client + + async def __aenter__(self) -> "AuthenticatedClient": + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" + await self.get_async_httpx_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" + await self.get_async_httpx_client().__aexit__(*args, **kwargs) diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/errors.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/errors.py new file mode 100644 index 000000000..5f92e76ac --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/errors.py @@ -0,0 +1,16 @@ +"""Contains shared errors types that can be raised from API functions""" + + +class UnexpectedStatus(Exception): + """Raised by api functions when the response status an undocumented status and Client.raise_on_unexpected_status is True""" + + def __init__(self, status_code: int, content: bytes): + self.status_code = status_code + self.content = content + + super().__init__( + f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}" + ) + + +__all__ = ["UnexpectedStatus"] diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/models/__init__.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/models/__init__.py new file mode 100644 index 000000000..80a3357a5 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/models/__init__.py @@ -0,0 +1,5 @@ +"""Contains all the data models used in inputs/outputs""" + +from .thing import Thing + +__all__ = ("Thing",) diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/models/thing.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/models/thing.py new file mode 100644 index 000000000..67e6c3d80 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/models/thing.py @@ -0,0 +1,116 @@ +import threading +from typing import Any, Dict, List, Type, TypeVar, Union + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="Thing") + + +@_attrs_define +class Thing: + """ + Attributes: + req_prop_1_read_write (str): + req_prop_2_read_only (str): + opt_prop_1_read_write (Union[Unset, str]): + opt_prop_2_read_only (Union[Unset, str]): + """ + + req_prop_1_read_write: str + req_prop_2_read_only: str + opt_prop_1_read_write: Union[Unset, str] = UNSET + opt_prop_2_read_only: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + serialization_context = threading.local.openapi_serialization_context or {} + skip_read_only = serialization_context.get("request_body", False) + prop1 = self.req_prop_1_read_write + prop2 = self.req_prop_2_read_only + prop3 = self.opt_prop_1_read_write + prop4 = self.opt_prop_2_read_only + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict = { + **field_dict, + "reqProp1ReadWrite": prop1, + **({} if skip_read_only else {"reqProp2ReadOnly": prop2}), + **({} if prop3 is UNSET else {"optProp1ReadWrite": prop3}), + **({} if prop4 is UNSET or skip_read_only else {"optProp2ReadOnly": prop4}), + } + + return field_dict + + def to_multipart(self) -> Dict[str, Any]: + serialization_context = threading.local.openapi_serialization_context or {} + skip_read_only = serialization_context.get("request_body", False) + prop1 = (None, str(self.req_prop_1_read_write).encode(), "text/plain") + + prop2 = (None, str(self.req_prop_2_read_only).encode(), "text/plain") + + prop3 = ( + self.opt_prop_1_read_write + if isinstance(self.opt_prop_1_read_write, Unset) + else (None, str(self.opt_prop_1_read_write).encode(), "text/plain") + ) + + prop4 = ( + self.opt_prop_2_read_only + if isinstance(self.opt_prop_2_read_only, Unset) + else (None, str(self.opt_prop_2_read_only).encode(), "text/plain") + ) + + field_dict: Dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = (None, str(prop).encode(), "text/plain") + + field_dict = { + **field_dict, + "reqProp1ReadWrite": prop1, + **({} if skip_read_only else {"reqProp2ReadOnly": prop2}), + **({} if prop3 is UNSET else {"optProp1ReadWrite": prop3}), + **({} if prop4 is UNSET or skip_read_only else {"optProp2ReadOnly": prop4}), + } + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + req_prop_1_read_write = d.pop("reqProp1ReadWrite") + + req_prop_2_read_only = d.pop("reqProp2ReadOnly") + + opt_prop_1_read_write = d.pop("optProp1ReadWrite", UNSET) + + opt_prop_2_read_only = d.pop("optProp2ReadOnly", UNSET) + + thing = cls( + req_prop_1_read_write=req_prop_1_read_write, + req_prop_2_read_only=req_prop_2_read_only, + opt_prop_1_read_write=opt_prop_1_read_write, + opt_prop_2_read_only=opt_prop_2_read_only, + ) + + thing.additional_properties = d + return thing + + @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-skip-read-only/my_read_only_properties_api_client/py.typed b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/py.typed new file mode 100644 index 000000000..1aad32711 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 \ No newline at end of file diff --git a/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/types.py b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/types.py new file mode 100644 index 000000000..21fac106f --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/my_read_only_properties_api_client/types.py @@ -0,0 +1,45 @@ +"""Contains some shared types for properties""" + +from http import HTTPStatus +from typing import BinaryIO, Generic, Literal, MutableMapping, Optional, Tuple, TypeVar + +from attrs import define + + +class Unset: + def __bool__(self) -> Literal[False]: + return False + + +UNSET: Unset = Unset() + +FileJsonType = Tuple[Optional[str], BinaryIO, Optional[str]] + + +@define +class File: + """Contains information for file uploads""" + + payload: BinaryIO + file_name: Optional[str] = None + mime_type: Optional[str] = None + + 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 + + +T = TypeVar("T") + + +@define +class Response(Generic[T]): + """A response from an endpoint""" + + status_code: HTTPStatus + content: bytes + headers: MutableMapping[str, str] + parsed: Optional[T] + + +__all__ = ["File", "Response", "FileJsonType", "Unset", "UNSET"] diff --git a/end_to_end_tests/golden-record-skip-read-only/pyproject.toml b/end_to_end_tests/golden-record-skip-read-only/pyproject.toml new file mode 100644 index 000000000..90a0c7bf6 --- /dev/null +++ b/end_to_end_tests/golden-record-skip-read-only/pyproject.toml @@ -0,0 +1,27 @@ +[tool.poetry] +name = "my-read-only-properties-api-client" +version = "0.1.0" +description = "A client library for accessing My Read-Only Properties API" +authors = [] +readme = "README.md" +packages = [ + {include = "my_read_only_properties_api_client"}, +] +include = ["CHANGELOG.md", "my_read_only_properties_api_client/py.typed"] + + +[tool.poetry.dependencies] +python = "^3.8" +httpx = ">=0.20.0,<0.28.0" +attrs = ">=21.3.0" +python-dateutil = "^2.8.0" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.ruff] +line-length = 120 + +[tool.ruff.lint] +select = ["F", "I", "UP"] diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py index cb1184b18..acfb26d65 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_1.py @@ -19,13 +19,14 @@ class ADiscriminatedUnionType1: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - model_type = self.model_type + prop1 = self.model_type field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if model_type is not UNSET: - field_dict["modelType"] = model_type + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"modelType": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py index 734f3bef4..e702f0e87 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_discriminated_union_type_2.py @@ -19,13 +19,14 @@ class ADiscriminatedUnionType2: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - model_type = self.model_type + prop1 = self.model_type field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if model_type is not UNSET: - field_dict["modelType"] = model_type + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"modelType": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py index a4c5cd8a7..a36d62ebd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_form_data.py @@ -21,19 +21,16 @@ class AFormData: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - an_required_field = self.an_required_field - - an_optional_field = self.an_optional_field + prop1 = self.an_required_field + prop2 = self.an_optional_field field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "an_required_field": an_required_field, - } - ) - if an_optional_field is not UNSET: - field_dict["an_optional_field"] = an_optional_field + field_dict = { + **field_dict, + "an_required_field": prop1, + **({} if prop2 is UNSET else {"an_optional_field": prop2}), + } return field_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 a14400c9d..083ff489b 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 @@ -82,172 +82,137 @@ def to_dict(self) -> Dict[str, Any]: from ..models.free_form_model import FreeFormModel from ..models.model_with_union_property import ModelWithUnionProperty - an_enum_value = self.an_enum_value.value - - an_allof_enum_with_overridden_default = self.an_allof_enum_with_overridden_default.value - - a_camel_date_time: str + prop1 = self.an_enum_value.value + prop2 = self.an_allof_enum_with_overridden_default.value + prop3: str if isinstance(self.a_camel_date_time, datetime.datetime): - a_camel_date_time = self.a_camel_date_time.isoformat() + prop3 = self.a_camel_date_time.isoformat() else: - a_camel_date_time = self.a_camel_date_time.isoformat() - - a_date = self.a_date.isoformat() + prop3 = self.a_camel_date_time.isoformat() - a_nullable_date: Union[None, str] + prop4 = self.a_date.isoformat() + prop5: Union[None, str] if isinstance(self.a_nullable_date, datetime.date): - a_nullable_date = self.a_nullable_date.isoformat() + prop5 = self.a_nullable_date.isoformat() else: - a_nullable_date = self.a_nullable_date - - a_uuid = str(self.a_uuid) - - a_nullable_uuid: Union[None, str] + prop5 = self.a_nullable_date + prop6 = str(self.a_uuid) + prop7: Union[None, str] if isinstance(self.a_nullable_uuid, UUID): - a_nullable_uuid = str(self.a_nullable_uuid) + prop7 = str(self.a_nullable_uuid) else: - a_nullable_uuid = self.a_nullable_uuid - - required_nullable: Union[None, str] - required_nullable = self.required_nullable - - required_not_nullable = self.required_not_nullable - - one_of_models: Union[Any, Dict[str, Any]] + prop7 = self.a_nullable_uuid + prop8: Union[None, str] + prop8 = self.required_nullable + prop9 = self.required_not_nullable + prop10: Union[Any, Dict[str, Any]] if isinstance(self.one_of_models, FreeFormModel): - one_of_models = self.one_of_models.to_dict() + prop10 = self.one_of_models.to_dict() elif isinstance(self.one_of_models, ModelWithUnionProperty): - one_of_models = self.one_of_models.to_dict() + prop10 = self.one_of_models.to_dict() else: - one_of_models = self.one_of_models - - nullable_one_of_models: Union[Dict[str, Any], None] + prop10 = self.one_of_models + prop11: Union[Dict[str, Any], None] if isinstance(self.nullable_one_of_models, FreeFormModel): - nullable_one_of_models = self.nullable_one_of_models.to_dict() + prop11 = self.nullable_one_of_models.to_dict() elif isinstance(self.nullable_one_of_models, ModelWithUnionProperty): - nullable_one_of_models = self.nullable_one_of_models.to_dict() + prop11 = self.nullable_one_of_models.to_dict() else: - nullable_one_of_models = self.nullable_one_of_models - - model = self.model.to_dict() - - nullable_model: Union[Dict[str, Any], None] + prop11 = self.nullable_one_of_models + prop12 = self.model.to_dict() + prop13: Union[Dict[str, Any], None] if isinstance(self.nullable_model, ModelWithUnionProperty): - nullable_model = self.nullable_model.to_dict() + prop13 = self.nullable_model.to_dict() else: - nullable_model = self.nullable_model - - any_value = self.any_value - - an_optional_allof_enum: Union[Unset, str] = UNSET + prop13 = self.nullable_model + prop14 = self.any_value + prop15: Union[Unset, str] = UNSET if not isinstance(self.an_optional_allof_enum, Unset): - an_optional_allof_enum = self.an_optional_allof_enum.value + prop15 = self.an_optional_allof_enum.value - nested_list_of_enums: Union[Unset, List[List[str]]] = UNSET + prop16: Union[Unset, List[List[str]]] = UNSET if not isinstance(self.nested_list_of_enums, Unset): - nested_list_of_enums = [] + prop16 = [] for nested_list_of_enums_item_data in self.nested_list_of_enums: nested_list_of_enums_item = [] for nested_list_of_enums_item_item_data in nested_list_of_enums_item_data: nested_list_of_enums_item_item = nested_list_of_enums_item_item_data.value nested_list_of_enums_item.append(nested_list_of_enums_item_item) - nested_list_of_enums.append(nested_list_of_enums_item) + prop16.append(nested_list_of_enums_item) - a_not_required_date: Union[Unset, str] = UNSET + prop17: Union[Unset, str] = UNSET if not isinstance(self.a_not_required_date, Unset): - a_not_required_date = self.a_not_required_date.isoformat() - - a_not_required_uuid: Union[Unset, str] = UNSET + prop17 = self.a_not_required_date.isoformat() + prop18: Union[Unset, str] = UNSET if not isinstance(self.a_not_required_uuid, Unset): - a_not_required_uuid = str(self.a_not_required_uuid) - - attr_1_leading_digit = self.attr_1_leading_digit - - attr_leading_underscore = self.attr_leading_underscore - - not_required_nullable: Union[None, Unset, str] + prop18 = str(self.a_not_required_uuid) + prop19 = self.attr_1_leading_digit + prop20 = self.attr_leading_underscore + prop21: Union[None, Unset, str] if isinstance(self.not_required_nullable, Unset): - not_required_nullable = UNSET + prop21 = UNSET else: - not_required_nullable = self.not_required_nullable - - not_required_not_nullable = self.not_required_not_nullable - - not_required_one_of_models: Union[Dict[str, Any], Unset] + prop21 = self.not_required_nullable + prop22 = self.not_required_not_nullable + prop23: Union[Dict[str, Any], Unset] if isinstance(self.not_required_one_of_models, Unset): - not_required_one_of_models = UNSET + prop23 = UNSET elif isinstance(self.not_required_one_of_models, FreeFormModel): - not_required_one_of_models = self.not_required_one_of_models.to_dict() + prop23 = self.not_required_one_of_models.to_dict() else: - not_required_one_of_models = self.not_required_one_of_models.to_dict() + prop23 = self.not_required_one_of_models.to_dict() - not_required_nullable_one_of_models: Union[Dict[str, Any], None, Unset, str] + prop24: Union[Dict[str, Any], None, Unset, str] if isinstance(self.not_required_nullable_one_of_models, Unset): - not_required_nullable_one_of_models = UNSET + prop24 = UNSET elif isinstance(self.not_required_nullable_one_of_models, FreeFormModel): - not_required_nullable_one_of_models = self.not_required_nullable_one_of_models.to_dict() + prop24 = 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 = self.not_required_nullable_one_of_models.to_dict() + prop24 = self.not_required_nullable_one_of_models.to_dict() else: - not_required_nullable_one_of_models = self.not_required_nullable_one_of_models - - not_required_model: Union[Unset, Dict[str, Any]] = UNSET + prop24 = self.not_required_nullable_one_of_models + prop25: 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[Dict[str, Any], None, Unset] + prop25 = self.not_required_model.to_dict() + prop26: Union[Dict[str, Any], None, Unset] if isinstance(self.not_required_nullable_model, Unset): - not_required_nullable_model = UNSET + prop26 = UNSET elif isinstance(self.not_required_nullable_model, ModelWithUnionProperty): - not_required_nullable_model = self.not_required_nullable_model.to_dict() + prop26 = self.not_required_nullable_model.to_dict() else: - not_required_nullable_model = self.not_required_nullable_model + prop26 = self.not_required_nullable_model field_dict: Dict[str, Any] = {} - field_dict.update( - { - "an_enum_value": an_enum_value, - "an_allof_enum_with_overridden_default": an_allof_enum_with_overridden_default, - "aCamelDateTime": a_camel_date_time, - "a_date": a_date, - "a_nullable_date": a_nullable_date, - "a_uuid": a_uuid, - "a_nullable_uuid": a_nullable_uuid, - "required_nullable": required_nullable, - "required_not_nullable": required_not_nullable, - "one_of_models": one_of_models, - "nullable_one_of_models": nullable_one_of_models, - "model": model, - "nullable_model": nullable_model, - } - ) - if any_value is not UNSET: - field_dict["any_value"] = any_value - if an_optional_allof_enum is not UNSET: - field_dict["an_optional_allof_enum"] = an_optional_allof_enum - if nested_list_of_enums is not UNSET: - field_dict["nested_list_of_enums"] = nested_list_of_enums - if a_not_required_date is not UNSET: - field_dict["a_not_required_date"] = a_not_required_date - if a_not_required_uuid is not UNSET: - field_dict["a_not_required_uuid"] = a_not_required_uuid - if attr_1_leading_digit is not UNSET: - field_dict["1_leading_digit"] = attr_1_leading_digit - if attr_leading_underscore is not UNSET: - field_dict["_leading_underscore"] = attr_leading_underscore - if not_required_nullable is not UNSET: - 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: - field_dict["not_required_nullable_model"] = not_required_nullable_model + field_dict = { + **field_dict, + "an_enum_value": prop1, + "an_allof_enum_with_overridden_default": prop2, + "aCamelDateTime": prop3, + "a_date": prop4, + "a_nullable_date": prop5, + "a_uuid": prop6, + "a_nullable_uuid": prop7, + "required_nullable": prop8, + "required_not_nullable": prop9, + "one_of_models": prop10, + "nullable_one_of_models": prop11, + "model": prop12, + "nullable_model": prop13, + **({} if prop14 is UNSET else {"any_value": prop14}), + **({} if prop15 is UNSET else {"an_optional_allof_enum": prop15}), + **({} if prop16 is UNSET else {"nested_list_of_enums": prop16}), + **({} if prop17 is UNSET else {"a_not_required_date": prop17}), + **({} if prop18 is UNSET else {"a_not_required_uuid": prop18}), + **({} if prop19 is UNSET else {"1_leading_digit": prop19}), + **({} if prop20 is UNSET else {"_leading_underscore": prop20}), + **({} if prop21 is UNSET else {"not_required_nullable": prop21}), + **({} if prop22 is UNSET else {"not_required_not_nullable": prop22}), + **({} if prop23 is UNSET else {"not_required_one_of_models": prop23}), + **({} if prop24 is UNSET else {"not_required_nullable_one_of_models": prop24}), + **({} if prop25 is UNSET else {"not_required_model": prop25}), + **({} if prop26 is UNSET else {"not_required_nullable_model": prop26}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py index 88ffd349f..9888b1a66 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model_with_properties_reference_that_are_not_object.py @@ -81,134 +81,125 @@ class AModelWithPropertiesReferenceThatAreNotObject: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - enum_properties_ref = [] + prop1 = [] for componentsschemas_an_other_array_of_enum_item_data in self.enum_properties_ref: componentsschemas_an_other_array_of_enum_item = componentsschemas_an_other_array_of_enum_item_data.value - enum_properties_ref.append(componentsschemas_an_other_array_of_enum_item) + prop1.append(componentsschemas_an_other_array_of_enum_item) - str_properties_ref = self.str_properties_ref + prop2 = self.str_properties_ref - date_properties_ref = [] + prop3 = [] for componentsschemas_an_other_array_of_date_item_data in self.date_properties_ref: componentsschemas_an_other_array_of_date_item = ( componentsschemas_an_other_array_of_date_item_data.isoformat() ) - date_properties_ref.append(componentsschemas_an_other_array_of_date_item) + prop3.append(componentsschemas_an_other_array_of_date_item) - datetime_properties_ref = [] + prop4 = [] for componentsschemas_an_other_array_of_date_time_item_data in self.datetime_properties_ref: componentsschemas_an_other_array_of_date_time_item = ( componentsschemas_an_other_array_of_date_time_item_data.isoformat() ) - datetime_properties_ref.append(componentsschemas_an_other_array_of_date_time_item) + prop4.append(componentsschemas_an_other_array_of_date_time_item) - int32_properties_ref = self.int32_properties_ref + prop5 = self.int32_properties_ref - int64_properties_ref = self.int64_properties_ref + prop6 = self.int64_properties_ref - float_properties_ref = self.float_properties_ref + prop7 = self.float_properties_ref - double_properties_ref = self.double_properties_ref + prop8 = self.double_properties_ref - file_properties_ref = [] + prop9 = [] for componentsschemas_an_other_array_of_file_item_data in self.file_properties_ref: componentsschemas_an_other_array_of_file_item = ( componentsschemas_an_other_array_of_file_item_data.to_tuple() ) - file_properties_ref.append(componentsschemas_an_other_array_of_file_item) + prop9.append(componentsschemas_an_other_array_of_file_item) - bytestream_properties_ref = self.bytestream_properties_ref + prop10 = self.bytestream_properties_ref - enum_properties = [] + prop11 = [] for componentsschemas_an_array_of_enum_item_data in self.enum_properties: componentsschemas_an_array_of_enum_item = componentsschemas_an_array_of_enum_item_data.value - enum_properties.append(componentsschemas_an_array_of_enum_item) + prop11.append(componentsschemas_an_array_of_enum_item) - str_properties = self.str_properties + prop12 = self.str_properties - date_properties = [] + prop13 = [] for componentsschemas_an_array_of_date_item_data in self.date_properties: componentsschemas_an_array_of_date_item = componentsschemas_an_array_of_date_item_data.isoformat() - date_properties.append(componentsschemas_an_array_of_date_item) + prop13.append(componentsschemas_an_array_of_date_item) - datetime_properties = [] + prop14 = [] for componentsschemas_an_array_of_date_time_item_data in self.datetime_properties: componentsschemas_an_array_of_date_time_item = componentsschemas_an_array_of_date_time_item_data.isoformat() - datetime_properties.append(componentsschemas_an_array_of_date_time_item) + prop14.append(componentsschemas_an_array_of_date_time_item) - int32_properties = self.int32_properties + prop15 = self.int32_properties - int64_properties = self.int64_properties + prop16 = self.int64_properties - float_properties = self.float_properties + prop17 = self.float_properties - double_properties = self.double_properties + prop18 = self.double_properties - file_properties = [] + prop19 = [] for componentsschemas_an_array_of_file_item_data in self.file_properties: componentsschemas_an_array_of_file_item = componentsschemas_an_array_of_file_item_data.to_tuple() - file_properties.append(componentsschemas_an_array_of_file_item) - - bytestream_properties = self.bytestream_properties - - enum_property_ref = self.enum_property_ref.value - - str_property_ref = self.str_property_ref + prop19.append(componentsschemas_an_array_of_file_item) - date_property_ref = self.date_property_ref.isoformat() + prop20 = self.bytestream_properties - datetime_property_ref = self.datetime_property_ref.isoformat() + prop21 = self.enum_property_ref.value + prop22 = self.str_property_ref + prop23 = self.date_property_ref.isoformat() + prop24 = self.datetime_property_ref.isoformat() + prop25 = self.int32_property_ref + prop26 = self.int64_property_ref + prop27 = self.float_property_ref + prop28 = self.double_property_ref + prop29 = self.file_property_ref.to_tuple() - int32_property_ref = self.int32_property_ref - - int64_property_ref = self.int64_property_ref - - float_property_ref = self.float_property_ref - - double_property_ref = self.double_property_ref - - file_property_ref = self.file_property_ref.to_tuple() - - bytestream_property_ref = self.bytestream_property_ref + prop30 = self.bytestream_property_ref field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "enum_properties_ref": enum_properties_ref, - "str_properties_ref": str_properties_ref, - "date_properties_ref": date_properties_ref, - "datetime_properties_ref": datetime_properties_ref, - "int32_properties_ref": int32_properties_ref, - "int64_properties_ref": int64_properties_ref, - "float_properties_ref": float_properties_ref, - "double_properties_ref": double_properties_ref, - "file_properties_ref": file_properties_ref, - "bytestream_properties_ref": bytestream_properties_ref, - "enum_properties": enum_properties, - "str_properties": str_properties, - "date_properties": date_properties, - "datetime_properties": datetime_properties, - "int32_properties": int32_properties, - "int64_properties": int64_properties, - "float_properties": float_properties, - "double_properties": double_properties, - "file_properties": file_properties, - "bytestream_properties": bytestream_properties, - "enum_property_ref": enum_property_ref, - "str_property_ref": str_property_ref, - "date_property_ref": date_property_ref, - "datetime_property_ref": datetime_property_ref, - "int32_property_ref": int32_property_ref, - "int64_property_ref": int64_property_ref, - "float_property_ref": float_property_ref, - "double_property_ref": double_property_ref, - "file_property_ref": file_property_ref, - "bytestream_property_ref": bytestream_property_ref, - } - ) + field_dict = { + **field_dict, + "enum_properties_ref": prop1, + "str_properties_ref": prop2, + "date_properties_ref": prop3, + "datetime_properties_ref": prop4, + "int32_properties_ref": prop5, + "int64_properties_ref": prop6, + "float_properties_ref": prop7, + "double_properties_ref": prop8, + "file_properties_ref": prop9, + "bytestream_properties_ref": prop10, + "enum_properties": prop11, + "str_properties": prop12, + "date_properties": prop13, + "datetime_properties": prop14, + "int32_properties": prop15, + "int64_properties": prop16, + "float_properties": prop17, + "double_properties": prop18, + "file_properties": prop19, + "bytestream_properties": prop20, + "enum_property_ref": prop21, + "str_property_ref": prop22, + "date_property_ref": prop23, + "datetime_property_ref": prop24, + "int32_property_ref": prop25, + "int64_property_ref": prop26, + "float_property_ref": prop27, + "double_property_ref": prop28, + "file_property_ref": prop29, + "bytestream_property_ref": prop30, + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py index 245a1b04a..2860d7040 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_has_properties_but_no_type.py @@ -24,23 +24,20 @@ class AllOfHasPropertiesButNoType: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a_sub_property = self.a_sub_property - - type = self.type - - type_enum: Union[Unset, int] = UNSET + prop1 = self.a_sub_property + prop2 = self.type + prop3: Union[Unset, int] = UNSET if not isinstance(self.type_enum, Unset): - type_enum = self.type_enum.value + prop3 = self.type_enum.value field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a_sub_property is not UNSET: - field_dict["a_sub_property"] = a_sub_property - if type is not UNSET: - field_dict["type"] = type - if type_enum is not UNSET: - field_dict["type_enum"] = type_enum + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_sub_property": prop1}), + **({} if prop2 is UNSET else {"type": prop2}), + **({} if prop3 is UNSET else {"type_enum": prop3}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py index 550b9b9c4..8767442af 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/all_of_sub_model.py @@ -24,23 +24,20 @@ class AllOfSubModel: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a_sub_property = self.a_sub_property - - type = self.type - - type_enum: Union[Unset, int] = UNSET + prop1 = self.a_sub_property + prop2 = self.type + prop3: Union[Unset, int] = UNSET if not isinstance(self.type_enum, Unset): - type_enum = self.type_enum.value + prop3 = self.type_enum.value field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a_sub_property is not UNSET: - field_dict["a_sub_property"] = a_sub_property - if type is not UNSET: - field_dict["type"] = type - if type_enum is not UNSET: - field_dict["type_enum"] = type_enum + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_sub_property": prop1}), + **({} if prop2 is UNSET else {"type": prop2}), + **({} if prop3 is UNSET else {"type_enum": prop3}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py index b7792fefc..a393258c2 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_a_item.py @@ -23,20 +23,21 @@ class AnArrayWithACircularRefInItemsObjectAItem: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - circular: Union[Unset, List[Dict[str, Any]]] = UNSET + prop1: Union[Unset, List[Dict[str, Any]]] = UNSET if not isinstance(self.circular, Unset): - circular = [] + prop1 = [] for componentsschemas_an_array_with_a_circular_ref_in_items_object_b_item_data in self.circular: componentsschemas_an_array_with_a_circular_ref_in_items_object_b_item = ( componentsschemas_an_array_with_a_circular_ref_in_items_object_b_item_data.to_dict() ) - circular.append(componentsschemas_an_array_with_a_circular_ref_in_items_object_b_item) + prop1.append(componentsschemas_an_array_with_a_circular_ref_in_items_object_b_item) field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if circular is not UNSET: - field_dict["circular"] = circular + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"circular": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py index 622d5d999..cfb968d91 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_circular_ref_in_items_object_b_item.py @@ -23,20 +23,21 @@ class AnArrayWithACircularRefInItemsObjectBItem: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - circular: Union[Unset, List[Dict[str, Any]]] = UNSET + prop1: Union[Unset, List[Dict[str, Any]]] = UNSET if not isinstance(self.circular, Unset): - circular = [] + prop1 = [] for componentsschemas_an_array_with_a_circular_ref_in_items_object_a_item_data in self.circular: componentsschemas_an_array_with_a_circular_ref_in_items_object_a_item = ( componentsschemas_an_array_with_a_circular_ref_in_items_object_a_item_data.to_dict() ) - circular.append(componentsschemas_an_array_with_a_circular_ref_in_items_object_a_item) + prop1.append(componentsschemas_an_array_with_a_circular_ref_in_items_object_a_item) field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if circular is not UNSET: - field_dict["circular"] = circular + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"circular": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py index 6b12b9b5d..854098397 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_array_with_a_recursive_ref_in_items_object_item.py @@ -19,20 +19,21 @@ class AnArrayWithARecursiveRefInItemsObjectItem: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - recursive: Union[Unset, List[Dict[str, Any]]] = UNSET + prop1: Union[Unset, List[Dict[str, Any]]] = UNSET if not isinstance(self.recursive, Unset): - recursive = [] + prop1 = [] for componentsschemas_an_array_with_a_recursive_ref_in_items_object_item_data in self.recursive: componentsschemas_an_array_with_a_recursive_ref_in_items_object_item = ( componentsschemas_an_array_with_a_recursive_ref_in_items_object_item_data.to_dict() ) - recursive.append(componentsschemas_an_array_with_a_recursive_ref_in_items_object_item) + prop1.append(componentsschemas_an_array_with_a_recursive_ref_in_items_object_item) field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if recursive is not UNSET: - field_dict["recursive"] = recursive + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"recursive": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py index fde2bb6f8..f6bd6396a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/another_all_of_sub_model.py @@ -25,25 +25,23 @@ class AnotherAllOfSubModel: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - another_sub_property = self.another_sub_property - - type: Union[Unset, str] = UNSET + prop1 = self.another_sub_property + prop2: Union[Unset, str] = UNSET if not isinstance(self.type, Unset): - type = self.type.value + prop2 = self.type.value - type_enum: Union[Unset, int] = UNSET + prop3: Union[Unset, int] = UNSET if not isinstance(self.type_enum, Unset): - type_enum = self.type_enum.value + prop3 = self.type_enum.value field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if another_sub_property is not UNSET: - field_dict["another_sub_property"] = another_sub_property - if type is not UNSET: - field_dict["type"] = type - if type_enum is not UNSET: - field_dict["type_enum"] = type_enum + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"another_sub_property": prop1}), + **({} if prop2 is UNSET else {"type": prop2}), + **({} if prop3 is UNSET else {"type_enum": prop3}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py index d7fbbf835..1b9e30f21 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py @@ -70,210 +70,174 @@ def to_dict(self) -> Dict[str, Any]: BodyUploadFileTestsUploadPostSomeNullableObject, ) - some_file = self.some_file.to_tuple() + prop1 = self.some_file.to_tuple() - some_required_number = self.some_required_number - - some_object = self.some_object.to_dict() - - some_nullable_object: Union[Dict[str, Any], None] + prop2 = self.some_required_number + prop3 = self.some_object.to_dict() + prop4: Union[Dict[str, Any], None] if isinstance(self.some_nullable_object, BodyUploadFileTestsUploadPostSomeNullableObject): - some_nullable_object = self.some_nullable_object.to_dict() + prop4 = self.some_nullable_object.to_dict() else: - some_nullable_object = self.some_nullable_object - - some_optional_file: Union[Unset, FileJsonType] = UNSET + prop4 = self.some_nullable_object + prop5: Union[Unset, FileJsonType] = UNSET if not isinstance(self.some_optional_file, Unset): - some_optional_file = self.some_optional_file.to_tuple() - - some_string = self.some_string + prop5 = self.some_optional_file.to_tuple() - a_datetime: Union[Unset, str] = UNSET + prop6 = self.some_string + prop7: Union[Unset, str] = UNSET if not isinstance(self.a_datetime, Unset): - a_datetime = self.a_datetime.isoformat() - - a_date: Union[Unset, str] = UNSET + prop7 = self.a_datetime.isoformat() + prop8: Union[Unset, str] = UNSET if not isinstance(self.a_date, Unset): - a_date = self.a_date.isoformat() - - some_number = self.some_number - - some_nullable_number: Union[None, Unset, float] + prop8 = self.a_date.isoformat() + prop9 = self.some_number + prop10: Union[None, Unset, float] if isinstance(self.some_nullable_number, Unset): - some_nullable_number = UNSET + prop10 = UNSET else: - some_nullable_number = self.some_nullable_number - - some_int_array: Union[Unset, List[Union[None, int]]] = UNSET + prop10 = self.some_nullable_number + prop11: Union[Unset, List[Union[None, int]]] = UNSET if not isinstance(self.some_int_array, Unset): - some_int_array = [] + prop11 = [] for some_int_array_item_data in self.some_int_array: some_int_array_item: Union[None, int] some_int_array_item = some_int_array_item_data - some_int_array.append(some_int_array_item) + prop11.append(some_int_array_item) - some_array: Union[List[Dict[str, Any]], None, Unset] + prop12: Union[List[Dict[str, Any]], None, Unset] if isinstance(self.some_array, Unset): - some_array = UNSET + prop12 = UNSET elif isinstance(self.some_array, list): - some_array = [] + prop12 = [] for some_array_type_0_item_data in self.some_array: some_array_type_0_item = some_array_type_0_item_data.to_dict() - some_array.append(some_array_type_0_item) + prop12.append(some_array_type_0_item) else: - some_array = self.some_array - - some_optional_object: Union[Unset, Dict[str, Any]] = UNSET + prop12 = self.some_array + prop13: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.some_optional_object, Unset): - some_optional_object = self.some_optional_object.to_dict() - - some_enum: Union[Unset, str] = UNSET + prop13 = self.some_optional_object.to_dict() + prop14: Union[Unset, str] = UNSET if not isinstance(self.some_enum, Unset): - some_enum = self.some_enum.value + prop14 = self.some_enum.value field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = prop.to_dict() - field_dict.update( - { - "some_file": some_file, - "some_required_number": some_required_number, - "some_object": some_object, - "some_nullable_object": some_nullable_object, - } - ) - if some_optional_file is not UNSET: - field_dict["some_optional_file"] = some_optional_file - if some_string is not UNSET: - field_dict["some_string"] = some_string - if a_datetime is not UNSET: - field_dict["a_datetime"] = a_datetime - if a_date is not UNSET: - field_dict["a_date"] = a_date - if some_number is not UNSET: - field_dict["some_number"] = some_number - if some_nullable_number is not UNSET: - field_dict["some_nullable_number"] = some_nullable_number - if some_int_array is not UNSET: - field_dict["some_int_array"] = some_int_array - if some_array is not UNSET: - field_dict["some_array"] = some_array - if some_optional_object is not UNSET: - field_dict["some_optional_object"] = some_optional_object - if some_enum is not UNSET: - field_dict["some_enum"] = some_enum + field_dict = { + **field_dict, + "some_file": prop1, + "some_required_number": prop2, + "some_object": prop3, + "some_nullable_object": prop4, + **({} if prop5 is UNSET else {"some_optional_file": prop5}), + **({} if prop6 is UNSET else {"some_string": prop6}), + **({} if prop7 is UNSET else {"a_datetime": prop7}), + **({} if prop8 is UNSET else {"a_date": prop8}), + **({} if prop9 is UNSET else {"some_number": prop9}), + **({} if prop10 is UNSET else {"some_nullable_number": prop10}), + **({} if prop11 is UNSET else {"some_int_array": prop11}), + **({} if prop12 is UNSET else {"some_array": prop12}), + **({} if prop13 is UNSET else {"some_optional_object": prop13}), + **({} if prop14 is UNSET else {"some_enum": prop14}), + } return field_dict def to_multipart(self) -> Dict[str, Any]: - some_file = self.some_file.to_tuple() - - some_required_number = (None, str(self.some_required_number).encode(), "text/plain") + prop1 = self.some_file.to_tuple() - some_object = (None, json.dumps(self.some_object.to_dict()).encode(), "application/json") + prop2 = (None, str(self.some_required_number).encode(), "text/plain") - some_nullable_object: Tuple[None, bytes, str] + prop3 = (None, json.dumps(self.some_object.to_dict()).encode(), "application/json") + prop4: Tuple[None, bytes, str] if isinstance(self.some_nullable_object, BodyUploadFileTestsUploadPostSomeNullableObject): - some_nullable_object = (None, json.dumps(self.some_nullable_object.to_dict()).encode(), "application/json") + prop4 = (None, json.dumps(self.some_nullable_object.to_dict()).encode(), "application/json") else: - some_nullable_object = (None, str(self.some_nullable_object).encode(), "text/plain") + prop4 = (None, str(self.some_nullable_object).encode(), "text/plain") - some_optional_file: Union[Unset, FileJsonType] = UNSET + prop5: Union[Unset, FileJsonType] = UNSET if not isinstance(self.some_optional_file, Unset): - some_optional_file = self.some_optional_file.to_tuple() + prop5 = self.some_optional_file.to_tuple() - some_string = ( + prop6 = ( self.some_string if isinstance(self.some_string, Unset) else (None, str(self.some_string).encode(), "text/plain") ) - a_datetime: Union[Unset, bytes] = UNSET + prop7: Union[Unset, bytes] = UNSET if not isinstance(self.a_datetime, Unset): - a_datetime = self.a_datetime.isoformat().encode() - - a_date: Union[Unset, bytes] = UNSET + prop7 = self.a_datetime.isoformat().encode() + prop8: Union[Unset, bytes] = UNSET if not isinstance(self.a_date, Unset): - a_date = self.a_date.isoformat().encode() - - some_number = ( + prop8 = self.a_date.isoformat().encode() + prop9 = ( self.some_number if isinstance(self.some_number, Unset) else (None, str(self.some_number).encode(), "text/plain") ) - some_nullable_number: Union[Tuple[None, bytes, str], Unset] + prop10: Union[Tuple[None, bytes, str], Unset] if isinstance(self.some_nullable_number, Unset): - some_nullable_number = UNSET + prop10 = UNSET elif isinstance(self.some_nullable_number, float): - some_nullable_number = (None, str(self.some_nullable_number).encode(), "text/plain") + prop10 = (None, str(self.some_nullable_number).encode(), "text/plain") else: - some_nullable_number = (None, str(self.some_nullable_number).encode(), "text/plain") + prop10 = (None, str(self.some_nullable_number).encode(), "text/plain") - some_int_array: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop11: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.some_int_array, Unset): - _temp_some_int_array = [] + _temp_prop11 = [] for some_int_array_item_data in self.some_int_array: some_int_array_item: Union[None, int] some_int_array_item = some_int_array_item_data - _temp_some_int_array.append(some_int_array_item) - some_int_array = (None, json.dumps(_temp_some_int_array).encode(), "application/json") + _temp_prop11.append(some_int_array_item) + prop11 = (None, json.dumps(_temp_prop11).encode(), "application/json") - some_array: Union[Tuple[None, bytes, str], Unset] + prop12: Union[Tuple[None, bytes, str], Unset] if isinstance(self.some_array, Unset): - some_array = UNSET + prop12 = UNSET elif isinstance(self.some_array, list): - _temp_some_array = [] + _temp_prop12 = [] for some_array_type_0_item_data in self.some_array: some_array_type_0_item = some_array_type_0_item_data.to_dict() - _temp_some_array.append(some_array_type_0_item) - some_array = (None, json.dumps(_temp_some_array).encode(), "application/json") + _temp_prop12.append(some_array_type_0_item) + prop12 = (None, json.dumps(_temp_prop12).encode(), "application/json") else: - some_array = (None, str(self.some_array).encode(), "text/plain") + prop12 = (None, str(self.some_array).encode(), "text/plain") - some_optional_object: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop13: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.some_optional_object, Unset): - some_optional_object = (None, json.dumps(self.some_optional_object.to_dict()).encode(), "application/json") - - some_enum: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop13 = (None, json.dumps(self.some_optional_object.to_dict()).encode(), "application/json") + prop14: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.some_enum, Unset): - some_enum = (None, str(self.some_enum.value).encode(), "text/plain") + prop14 = (None, str(self.some_enum.value).encode(), "text/plain") field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = (None, json.dumps(prop.to_dict()).encode(), "application/json") - field_dict.update( - { - "some_file": some_file, - "some_required_number": some_required_number, - "some_object": some_object, - "some_nullable_object": some_nullable_object, - } - ) - if some_optional_file is not UNSET: - field_dict["some_optional_file"] = some_optional_file - if some_string is not UNSET: - field_dict["some_string"] = some_string - if a_datetime is not UNSET: - field_dict["a_datetime"] = a_datetime - if a_date is not UNSET: - field_dict["a_date"] = a_date - if some_number is not UNSET: - field_dict["some_number"] = some_number - if some_nullable_number is not UNSET: - field_dict["some_nullable_number"] = some_nullable_number - if some_int_array is not UNSET: - field_dict["some_int_array"] = some_int_array - if some_array is not UNSET: - field_dict["some_array"] = some_array - if some_optional_object is not UNSET: - field_dict["some_optional_object"] = some_optional_object - if some_enum is not UNSET: - field_dict["some_enum"] = some_enum + field_dict = { + **field_dict, + "some_file": prop1, + "some_required_number": prop2, + "some_object": prop3, + "some_nullable_object": prop4, + **({} if prop5 is UNSET else {"some_optional_file": prop5}), + **({} if prop6 is UNSET else {"some_string": prop6}), + **({} if prop7 is UNSET else {"a_datetime": prop7}), + **({} if prop8 is UNSET else {"a_date": prop8}), + **({} if prop9 is UNSET else {"some_number": prop9}), + **({} if prop10 is UNSET else {"some_nullable_number": prop10}), + **({} if prop11 is UNSET else {"some_int_array": prop11}), + **({} if prop12 is UNSET else {"some_array": prop12}), + **({} if prop13 is UNSET else {"some_optional_object": prop13}), + **({} if prop14 is UNSET else {"some_enum": prop14}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py index f855d9c61..161de7304 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_additional_property.py @@ -19,13 +19,14 @@ class BodyUploadFileTestsUploadPostAdditionalProperty: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - foo = self.foo + prop1 = self.foo field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if foo is not UNSET: - field_dict["foo"] = foo + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"foo": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py index 9762b7efa..7cd852a40 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_nullable_object.py @@ -19,13 +19,14 @@ class BodyUploadFileTestsUploadPostSomeNullableObject: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - bar = self.bar + prop1 = self.bar field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if bar is not UNSET: - field_dict["bar"] = bar + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"bar": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py index 25c2c0a6a..fe8086b22 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_object.py @@ -19,18 +19,16 @@ class BodyUploadFileTestsUploadPostSomeObject: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - num = self.num - - text = self.text + prop1 = self.num + prop2 = self.text field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "num": num, - "text": text, - } - ) + field_dict = { + **field_dict, + "num": prop1, + "text": prop2, + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py index 711b34e63..c76d93ef7 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post_some_optional_object.py @@ -17,15 +17,14 @@ class BodyUploadFileTestsUploadPostSomeOptionalObject: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - foo = self.foo + prop1 = self.foo field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "foo": foo, - } - ) + field_dict = { + **field_dict, + "foo": prop1, + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/extended.py b/end_to_end_tests/golden-record/my_test_api_client/models/extended.py index 324513d3a..629ca4046 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/extended.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/extended.py @@ -85,177 +85,140 @@ def to_dict(self) -> Dict[str, Any]: from ..models.free_form_model import FreeFormModel from ..models.model_with_union_property import ModelWithUnionProperty - an_enum_value = self.an_enum_value.value - - an_allof_enum_with_overridden_default = self.an_allof_enum_with_overridden_default.value - - a_camel_date_time: str + prop1 = self.an_enum_value.value + prop2 = self.an_allof_enum_with_overridden_default.value + prop3: str if isinstance(self.a_camel_date_time, datetime.datetime): - a_camel_date_time = self.a_camel_date_time.isoformat() + prop3 = self.a_camel_date_time.isoformat() else: - a_camel_date_time = self.a_camel_date_time.isoformat() - - a_date = self.a_date.isoformat() + prop3 = self.a_camel_date_time.isoformat() - a_nullable_date: Union[None, str] + prop4 = self.a_date.isoformat() + prop5: Union[None, str] if isinstance(self.a_nullable_date, datetime.date): - a_nullable_date = self.a_nullable_date.isoformat() + prop5 = self.a_nullable_date.isoformat() else: - a_nullable_date = self.a_nullable_date - - a_uuid = str(self.a_uuid) - - a_nullable_uuid: Union[None, str] + prop5 = self.a_nullable_date + prop6 = str(self.a_uuid) + prop7: Union[None, str] if isinstance(self.a_nullable_uuid, UUID): - a_nullable_uuid = str(self.a_nullable_uuid) + prop7 = str(self.a_nullable_uuid) else: - a_nullable_uuid = self.a_nullable_uuid - - required_nullable: Union[None, str] - required_nullable = self.required_nullable - - required_not_nullable = self.required_not_nullable - - one_of_models: Union[Any, Dict[str, Any]] + prop7 = self.a_nullable_uuid + prop8: Union[None, str] + prop8 = self.required_nullable + prop9 = self.required_not_nullable + prop10: Union[Any, Dict[str, Any]] if isinstance(self.one_of_models, FreeFormModel): - one_of_models = self.one_of_models.to_dict() + prop10 = self.one_of_models.to_dict() elif isinstance(self.one_of_models, ModelWithUnionProperty): - one_of_models = self.one_of_models.to_dict() + prop10 = self.one_of_models.to_dict() else: - one_of_models = self.one_of_models - - nullable_one_of_models: Union[Dict[str, Any], None] + prop10 = self.one_of_models + prop11: Union[Dict[str, Any], None] if isinstance(self.nullable_one_of_models, FreeFormModel): - nullable_one_of_models = self.nullable_one_of_models.to_dict() + prop11 = self.nullable_one_of_models.to_dict() elif isinstance(self.nullable_one_of_models, ModelWithUnionProperty): - nullable_one_of_models = self.nullable_one_of_models.to_dict() + prop11 = self.nullable_one_of_models.to_dict() else: - nullable_one_of_models = self.nullable_one_of_models - - model = self.model.to_dict() - - nullable_model: Union[Dict[str, Any], None] + prop11 = self.nullable_one_of_models + prop12 = self.model.to_dict() + prop13: Union[Dict[str, Any], None] if isinstance(self.nullable_model, ModelWithUnionProperty): - nullable_model = self.nullable_model.to_dict() + prop13 = self.nullable_model.to_dict() else: - nullable_model = self.nullable_model - - any_value = self.any_value - - an_optional_allof_enum: Union[Unset, str] = UNSET + prop13 = self.nullable_model + prop14 = self.any_value + prop15: Union[Unset, str] = UNSET if not isinstance(self.an_optional_allof_enum, Unset): - an_optional_allof_enum = self.an_optional_allof_enum.value + prop15 = self.an_optional_allof_enum.value - nested_list_of_enums: Union[Unset, List[List[str]]] = UNSET + prop16: Union[Unset, List[List[str]]] = UNSET if not isinstance(self.nested_list_of_enums, Unset): - nested_list_of_enums = [] + prop16 = [] for nested_list_of_enums_item_data in self.nested_list_of_enums: nested_list_of_enums_item = [] for nested_list_of_enums_item_item_data in nested_list_of_enums_item_data: nested_list_of_enums_item_item = nested_list_of_enums_item_item_data.value nested_list_of_enums_item.append(nested_list_of_enums_item_item) - nested_list_of_enums.append(nested_list_of_enums_item) + prop16.append(nested_list_of_enums_item) - a_not_required_date: Union[Unset, str] = UNSET + prop17: Union[Unset, str] = UNSET if not isinstance(self.a_not_required_date, Unset): - a_not_required_date = self.a_not_required_date.isoformat() - - a_not_required_uuid: Union[Unset, str] = UNSET + prop17 = self.a_not_required_date.isoformat() + prop18: Union[Unset, str] = UNSET if not isinstance(self.a_not_required_uuid, Unset): - a_not_required_uuid = str(self.a_not_required_uuid) - - attr_1_leading_digit = self.attr_1_leading_digit - - attr_leading_underscore = self.attr_leading_underscore - - not_required_nullable: Union[None, Unset, str] + prop18 = str(self.a_not_required_uuid) + prop19 = self.attr_1_leading_digit + prop20 = self.attr_leading_underscore + prop21: Union[None, Unset, str] if isinstance(self.not_required_nullable, Unset): - not_required_nullable = UNSET + prop21 = UNSET else: - not_required_nullable = self.not_required_nullable - - not_required_not_nullable = self.not_required_not_nullable - - not_required_one_of_models: Union[Dict[str, Any], Unset] + prop21 = self.not_required_nullable + prop22 = self.not_required_not_nullable + prop23: Union[Dict[str, Any], Unset] if isinstance(self.not_required_one_of_models, Unset): - not_required_one_of_models = UNSET + prop23 = UNSET elif isinstance(self.not_required_one_of_models, FreeFormModel): - not_required_one_of_models = self.not_required_one_of_models.to_dict() + prop23 = self.not_required_one_of_models.to_dict() else: - not_required_one_of_models = self.not_required_one_of_models.to_dict() + prop23 = self.not_required_one_of_models.to_dict() - not_required_nullable_one_of_models: Union[Dict[str, Any], None, Unset, str] + prop24: Union[Dict[str, Any], None, Unset, str] if isinstance(self.not_required_nullable_one_of_models, Unset): - not_required_nullable_one_of_models = UNSET + prop24 = UNSET elif isinstance(self.not_required_nullable_one_of_models, FreeFormModel): - not_required_nullable_one_of_models = self.not_required_nullable_one_of_models.to_dict() + prop24 = 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 = self.not_required_nullable_one_of_models.to_dict() + prop24 = self.not_required_nullable_one_of_models.to_dict() else: - not_required_nullable_one_of_models = self.not_required_nullable_one_of_models - - not_required_model: Union[Unset, Dict[str, Any]] = UNSET + prop24 = self.not_required_nullable_one_of_models + prop25: 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[Dict[str, Any], None, Unset] + prop25 = self.not_required_model.to_dict() + prop26: Union[Dict[str, Any], None, Unset] if isinstance(self.not_required_nullable_model, Unset): - not_required_nullable_model = UNSET + prop26 = UNSET elif isinstance(self.not_required_nullable_model, ModelWithUnionProperty): - not_required_nullable_model = self.not_required_nullable_model.to_dict() + prop26 = self.not_required_nullable_model.to_dict() else: - not_required_nullable_model = self.not_required_nullable_model - - from_extended = self.from_extended + prop26 = self.not_required_nullable_model + prop27 = self.from_extended field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "an_enum_value": an_enum_value, - "an_allof_enum_with_overridden_default": an_allof_enum_with_overridden_default, - "aCamelDateTime": a_camel_date_time, - "a_date": a_date, - "a_nullable_date": a_nullable_date, - "a_uuid": a_uuid, - "a_nullable_uuid": a_nullable_uuid, - "required_nullable": required_nullable, - "required_not_nullable": required_not_nullable, - "one_of_models": one_of_models, - "nullable_one_of_models": nullable_one_of_models, - "model": model, - "nullable_model": nullable_model, - } - ) - if any_value is not UNSET: - field_dict["any_value"] = any_value - if an_optional_allof_enum is not UNSET: - field_dict["an_optional_allof_enum"] = an_optional_allof_enum - if nested_list_of_enums is not UNSET: - field_dict["nested_list_of_enums"] = nested_list_of_enums - if a_not_required_date is not UNSET: - field_dict["a_not_required_date"] = a_not_required_date - if a_not_required_uuid is not UNSET: - field_dict["a_not_required_uuid"] = a_not_required_uuid - if attr_1_leading_digit is not UNSET: - field_dict["1_leading_digit"] = attr_1_leading_digit - if attr_leading_underscore is not UNSET: - field_dict["_leading_underscore"] = attr_leading_underscore - if not_required_nullable is not UNSET: - 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: - field_dict["not_required_nullable_model"] = not_required_nullable_model - if from_extended is not UNSET: - field_dict["fromExtended"] = from_extended + field_dict = { + **field_dict, + "an_enum_value": prop1, + "an_allof_enum_with_overridden_default": prop2, + "aCamelDateTime": prop3, + "a_date": prop4, + "a_nullable_date": prop5, + "a_uuid": prop6, + "a_nullable_uuid": prop7, + "required_nullable": prop8, + "required_not_nullable": prop9, + "one_of_models": prop10, + "nullable_one_of_models": prop11, + "model": prop12, + "nullable_model": prop13, + **({} if prop14 is UNSET else {"any_value": prop14}), + **({} if prop15 is UNSET else {"an_optional_allof_enum": prop15}), + **({} if prop16 is UNSET else {"nested_list_of_enums": prop16}), + **({} if prop17 is UNSET else {"a_not_required_date": prop17}), + **({} if prop18 is UNSET else {"a_not_required_uuid": prop18}), + **({} if prop19 is UNSET else {"1_leading_digit": prop19}), + **({} if prop20 is UNSET else {"_leading_underscore": prop20}), + **({} if prop21 is UNSET else {"not_required_nullable": prop21}), + **({} if prop22 is UNSET else {"not_required_not_nullable": prop22}), + **({} if prop23 is UNSET else {"not_required_one_of_models": prop23}), + **({} if prop24 is UNSET else {"not_required_nullable_one_of_models": prop24}), + **({} if prop25 is UNSET else {"not_required_model": prop25}), + **({} if prop26 is UNSET else {"not_required_nullable_model": prop26}), + **({} if prop27 is UNSET else {"fromExtended": prop27}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/get_models_allof_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/get_models_allof_response_200.py index 2662dc1f4..c1abe58d8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/get_models_allof_response_200.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/get_models_allof_response_200.py @@ -28,27 +28,24 @@ class GetModelsAllofResponse200: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - aliased: Union[Unset, Dict[str, Any]] = UNSET + prop1: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.aliased, Unset): - aliased = self.aliased.to_dict() - - extended: Union[Unset, Dict[str, Any]] = UNSET + prop1 = self.aliased.to_dict() + prop2: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.extended, Unset): - extended = self.extended.to_dict() - - model: Union[Unset, Dict[str, Any]] = UNSET + prop2 = self.extended.to_dict() + prop3: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.model, Unset): - model = self.model.to_dict() + prop3 = self.model.to_dict() field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if aliased is not UNSET: - field_dict["aliased"] = aliased - if extended is not UNSET: - field_dict["extended"] = extended - if model is not UNSET: - field_dict["model"] = model + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"aliased": prop1}), + **({} if prop2 is UNSET else {"extended": prop2}), + **({} if prop3 is UNSET else {"model": prop3}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_0.py b/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_0.py index 972e1c765..c0dc4090b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_0.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_0.py @@ -21,19 +21,16 @@ class GetModelsOneofWithRequiredConstResponse200Type0: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - type = self.type - - color = self.color + prop1 = self.type + prop2 = self.color field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "type": type, - } - ) - if color is not UNSET: - field_dict["color"] = color + field_dict = { + **field_dict, + "type": prop1, + **({} if prop2 is UNSET else {"color": prop2}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_1.py index 4596c3cc4..97273abf7 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_1.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/get_models_oneof_with_required_const_response_200_type_1.py @@ -21,19 +21,16 @@ class GetModelsOneofWithRequiredConstResponse200Type1: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - type = self.type - - texture = self.texture + prop1 = self.type + prop2 = self.texture field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "type": type, - } - ) - if texture is not UNSET: - field_dict["texture"] = texture + field_dict = { + **field_dict, + "type": prop1, + **({} if prop2 is UNSET else {"texture": prop2}), + } return field_dict 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 1f04c29d0..f9a2e268a 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 @@ -21,17 +21,18 @@ class HTTPValidationError: detail: Union[Unset, List["ValidationError"]] = UNSET def to_dict(self) -> Dict[str, Any]: - detail: Union[Unset, List[Dict[str, Any]]] = UNSET + prop1: Union[Unset, List[Dict[str, Any]]] = UNSET if not isinstance(self.detail, Unset): - detail = [] + prop1 = [] for detail_item_data in self.detail: detail_item = detail_item_data.to_dict() - detail.append(detail_item) + prop1.append(detail_item) field_dict: Dict[str, Any] = {} - field_dict.update({}) - if detail is not UNSET: - field_dict["detail"] = detail + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"detail": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/json_like_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/json_like_body.py index 623dcd848..7dcdb6c8c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/json_like_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/json_like_body.py @@ -19,13 +19,14 @@ class JsonLikeBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a = self.a + prop1 = self.a field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a is not UNSET: - field_dict["a"] = a + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/mixed_case_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/mixed_case_response_200.py index 21bdd918d..3367ddd2d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/mixed_case_response_200.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/mixed_case_response_200.py @@ -21,17 +21,16 @@ class MixedCaseResponse200: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - mixed_case = self.mixed_case - - mixedCase = self.mixedCase + prop1 = self.mixed_case + prop2 = self.mixedCase field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if mixed_case is not UNSET: - field_dict["mixed_case"] = mixed_case - if mixedCase is not UNSET: - field_dict["mixedCase"] = mixedCase + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"mixed_case": prop1}), + **({} if prop2 is UNSET else {"mixedCase": prop2}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py index 6414b790d..789125c94 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_from_all_of.py @@ -27,29 +27,26 @@ class ModelFromAllOf: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a_sub_property = self.a_sub_property - - type: Union[Unset, str] = UNSET + prop1 = self.a_sub_property + prop2: Union[Unset, str] = UNSET if not isinstance(self.type, Unset): - type = self.type.value + prop2 = self.type.value - type_enum: Union[Unset, int] = UNSET + prop3: Union[Unset, int] = UNSET if not isinstance(self.type_enum, Unset): - type_enum = self.type_enum.value + prop3 = self.type_enum.value - another_sub_property = self.another_sub_property + prop4 = self.another_sub_property field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a_sub_property is not UNSET: - field_dict["a_sub_property"] = a_sub_property - if type is not UNSET: - field_dict["type"] = type - if type_enum is not UNSET: - field_dict["type_enum"] = type_enum - if another_sub_property is not UNSET: - field_dict["another_sub_property"] = another_sub_property + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_sub_property": prop1}), + **({} if prop2 is UNSET else {"type": prop2}), + **({} if prop3 is UNSET else {"type_enum": prop3}), + **({} if prop4 is UNSET else {"another_sub_property": prop4}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py index 761a43e54..e5fd04dd1 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py @@ -27,14 +27,15 @@ class ModelWithAdditionalPropertiesInlined: ) def to_dict(self) -> Dict[str, Any]: - a_number = self.a_number + prop1 = self.a_number field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = prop.to_dict() - field_dict.update({}) - if a_number is not UNSET: - field_dict["a_number"] = a_number + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_number": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py index e06a94bfc..00376e963 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py @@ -19,13 +19,14 @@ class ModelWithAdditionalPropertiesInlinedAdditionalProperty: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - extra_props_prop = self.extra_props_prop + prop1 = self.extra_props_prop field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if extra_props_prop is not UNSET: - field_dict["extra_props_prop"] = extra_props_prop + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"extra_props_prop": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py index 73cfb1287..9fa220898 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_a.py @@ -23,15 +23,16 @@ class ModelWithCircularRefA: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - circular: Union[Unset, Dict[str, Any]] = UNSET + prop1: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.circular, Unset): - circular = self.circular.to_dict() + prop1 = self.circular.to_dict() field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if circular is not UNSET: - field_dict["circular"] = circular + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"circular": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py index 0628d89ae..4297f1900 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_circular_ref_b.py @@ -23,15 +23,16 @@ class ModelWithCircularRefB: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - circular: Union[Unset, Dict[str, Any]] = UNSET + prop1: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.circular, Unset): - circular = self.circular.to_dict() + prop1 = self.circular.to_dict() field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if circular is not UNSET: - field_dict["circular"] = circular + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"circular": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py index 658b2352d..f396fd2fc 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_date_time_property.py @@ -21,15 +21,16 @@ class ModelWithDateTimeProperty: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - datetime_: Union[Unset, str] = UNSET + prop1: Union[Unset, str] = UNSET if not isinstance(self.datetime_, Unset): - datetime_ = self.datetime_.isoformat() + prop1 = self.datetime_.isoformat() field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if datetime_ is not UNSET: - field_dict["datetime"] = datetime_ + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"datetime": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py index e03a6e698..ef720e851 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_discriminated_union.py @@ -27,21 +27,22 @@ def to_dict(self) -> Dict[str, Any]: from ..models.a_discriminated_union_type_1 import ADiscriminatedUnionType1 from ..models.a_discriminated_union_type_2 import ADiscriminatedUnionType2 - discriminated_union: Union[Dict[str, Any], None, Unset] + prop1: Union[Dict[str, Any], None, Unset] if isinstance(self.discriminated_union, Unset): - discriminated_union = UNSET + prop1 = UNSET elif isinstance(self.discriminated_union, ADiscriminatedUnionType1): - discriminated_union = self.discriminated_union.to_dict() + prop1 = self.discriminated_union.to_dict() elif isinstance(self.discriminated_union, ADiscriminatedUnionType2): - discriminated_union = self.discriminated_union.to_dict() + prop1 = self.discriminated_union.to_dict() else: - discriminated_union = self.discriminated_union + prop1 = self.discriminated_union field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if discriminated_union is not UNSET: - field_dict["discriminated_union"] = discriminated_union + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"discriminated_union": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_merged_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_merged_properties.py index bcf1efa88..2c7252b50 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_merged_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_merged_properties.py @@ -31,33 +31,27 @@ class ModelWithMergedProperties: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - simple_string = self.simple_string - - string_to_enum: Union[Unset, str] = UNSET + prop1 = self.simple_string + prop2: Union[Unset, str] = UNSET if not isinstance(self.string_to_enum, Unset): - string_to_enum = self.string_to_enum.value + prop2 = self.string_to_enum.value - string_to_date: Union[Unset, str] = UNSET + prop3: Union[Unset, str] = UNSET if not isinstance(self.string_to_date, Unset): - string_to_date = self.string_to_date.isoformat() - - number_to_int = self.number_to_int - - any_to_string = self.any_to_string + prop3 = self.string_to_date.isoformat() + prop4 = self.number_to_int + prop5 = self.any_to_string field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if simple_string is not UNSET: - field_dict["simpleString"] = simple_string - if string_to_enum is not UNSET: - field_dict["stringToEnum"] = string_to_enum - if string_to_date is not UNSET: - field_dict["stringToDate"] = string_to_date - if number_to_int is not UNSET: - field_dict["numberToInt"] = number_to_int - if any_to_string is not UNSET: - field_dict["anyToString"] = any_to_string + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"simpleString": prop1}), + **({} if prop2 is UNSET else {"stringToEnum": prop2}), + **({} if prop3 is UNSET else {"stringToDate": prop3}), + **({} if prop4 is UNSET else {"numberToInt": prop4}), + **({} if prop5 is UNSET else {"anyToString": prop5}), + } return field_dict 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 94afa7653..53a67a1a3 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 @@ -25,15 +25,16 @@ class ModelWithPrimitiveAdditionalProperties: additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a_date_holder: Union[Unset, Dict[str, Any]] = UNSET + prop1: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.a_date_holder, Unset): - a_date_holder = self.a_date_holder.to_dict() + prop1 = self.a_date_holder.to_dict() field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a_date_holder is not UNSET: - field_dict["a_date_holder"] = a_date_holder + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_date_holder": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py index f54afdee8..580b7ffd0 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_property_ref.py @@ -23,15 +23,16 @@ class ModelWithPropertyRef: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - inner: Union[Unset, Dict[str, Any]] = UNSET + prop1: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.inner, Unset): - inner = self.inner.to_dict() + prop1 = self.inner.to_dict() field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if inner is not UNSET: - field_dict["inner"] = inner + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"inner": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py index 578bca7e0..efaa63d23 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_recursive_ref.py @@ -19,15 +19,16 @@ class ModelWithRecursiveRef: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - recursive: Union[Unset, Dict[str, Any]] = UNSET + prop1: Union[Unset, Dict[str, Any]] = UNSET if not isinstance(self.recursive, Unset): - recursive = self.recursive.to_dict() + prop1 = self.recursive.to_dict() field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if recursive is not UNSET: - field_dict["recursive"] = recursive + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"recursive": prop1}), + } return field_dict 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 890010b78..6a64c2319 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 @@ -19,18 +19,19 @@ class ModelWithUnionProperty: a_property: Union[AnEnum, AnIntEnum, Unset] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, int, str] + prop1: Union[Unset, int, str] if isinstance(self.a_property, Unset): - a_property = UNSET + prop1 = UNSET elif isinstance(self.a_property, AnEnum): - a_property = self.a_property.value + prop1 = self.a_property.value else: - a_property = self.a_property.value + prop1 = self.a_property.value field_dict: Dict[str, Any] = {} - field_dict.update({}) - if a_property is not UNSET: - field_dict["a_property"] = a_property + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_property": prop1}), + } return field_dict 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 2a832e21a..13b05061b 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 @@ -24,18 +24,19 @@ class ModelWithUnionPropertyInlined: def to_dict(self) -> Dict[str, Any]: from ..models.model_with_union_property_inlined_fruit_type_0 import ModelWithUnionPropertyInlinedFruitType0 - fruit: Union[Dict[str, Any], Unset] + prop1: Union[Dict[str, Any], Unset] if isinstance(self.fruit, Unset): - fruit = UNSET + prop1 = UNSET elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitType0): - fruit = self.fruit.to_dict() + prop1 = self.fruit.to_dict() else: - fruit = self.fruit.to_dict() + prop1 = self.fruit.to_dict() field_dict: Dict[str, Any] = {} - field_dict.update({}) - if fruit is not UNSET: - field_dict["fruit"] = fruit + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"fruit": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py index b0f25360a..2bebe7fc6 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_0.py @@ -19,13 +19,14 @@ class ModelWithUnionPropertyInlinedFruitType0: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - apples = self.apples + prop1 = 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 + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"apples": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py index 1a32f2445..73b169a50 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined_fruit_type_1.py @@ -19,13 +19,14 @@ class ModelWithUnionPropertyInlinedFruitType1: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - bananas = self.bananas + prop1 = 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 + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"bananas": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_data_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_data_body.py index adc78cd6f..64028287d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_data_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_data_body.py @@ -19,13 +19,14 @@ class PostBodiesMultipleDataBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a = self.a + prop1 = self.a field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a is not UNSET: - field_dict["a"] = a + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_files_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_files_body.py index c81dc7636..0005f4550 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_files_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_files_body.py @@ -19,26 +19,28 @@ class PostBodiesMultipleFilesBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a = self.a + prop1 = self.a field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a is not UNSET: - field_dict["a"] = a + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a": prop1}), + } return field_dict def to_multipart(self) -> Dict[str, Any]: - a = self.a if isinstance(self.a, Unset) else (None, str(self.a).encode(), "text/plain") + prop1 = self.a if isinstance(self.a, Unset) else (None, str(self.a).encode(), "text/plain") field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = (None, str(prop).encode(), "text/plain") - field_dict.update({}) - if a is not UNSET: - field_dict["a"] = a + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_json_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_json_body.py index 88e5ec6f9..5e3231971 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_json_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_bodies_multiple_json_body.py @@ -19,13 +19,14 @@ class PostBodiesMultipleJsonBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a = self.a + prop1 = self.a field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if a is not UNSET: - field_dict["a"] = a + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_body.py index 08a7bbc3a..9919a1fdb 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_form_data_inline_body.py @@ -21,19 +21,16 @@ class PostFormDataInlineBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a_required_field = self.a_required_field - - an_optional_field = self.an_optional_field + prop1 = self.a_required_field + prop2 = self.an_optional_field field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "a_required_field": a_required_field, - } - ) - if an_optional_field is not UNSET: - field_dict["an_optional_field"] = an_optional_field + field_dict = { + **field_dict, + "a_required_field": prop1, + **({} if prop2 is UNSET else {"an_optional_field": prop2}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_body.py index ed2f8efa1..7bb08337f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_body.py @@ -21,17 +21,16 @@ class PostNamingPropertyConflictWithImportBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - field = self.field - - define = self.define + prop1 = self.field + prop2 = self.define field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if field is not UNSET: - field_dict["Field"] = field - if define is not UNSET: - field_dict["Define"] = define + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"Field": prop1}), + **({} if prop2 is UNSET else {"Define": prop2}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_response_200.py index 9bdd79a02..eb2966530 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_response_200.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_naming_property_conflict_with_import_response_200.py @@ -21,17 +21,16 @@ class PostNamingPropertyConflictWithImportResponse200: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - field = self.field - - define = self.define + prop1 = self.field + prop2 = self.define field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if field is not UNSET: - field_dict["Field"] = field - if define is not UNSET: - field_dict["Define"] = define + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"Field": prop1}), + **({} if prop2 is UNSET else {"Define": prop2}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py index 0b6a29243..362c75069 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py @@ -27,19 +27,18 @@ def to_dict(self) -> Dict[str, Any]: PostResponsesUnionsSimpleBeforeComplexResponse200AType1, ) - a: Union[Dict[str, Any], str] + prop1: Union[Dict[str, Any], str] if isinstance(self.a, PostResponsesUnionsSimpleBeforeComplexResponse200AType1): - a = self.a.to_dict() + prop1 = self.a.to_dict() else: - a = self.a + prop1 = self.a field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "a": a, - } - ) + field_dict = { + **field_dict, + "a": prop1, + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_body.py index 8c1843b41..958727f76 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_body.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_body.py @@ -17,12 +17,13 @@ class TestInlineObjectsBody: a_property: Union[Unset, str] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property = self.a_property + prop1 = self.a_property field_dict: Dict[str, Any] = {} - field_dict.update({}) - if a_property is not UNSET: - field_dict["a_property"] = a_property + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_property": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py index 6a0ade77f..61e3cda1b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py @@ -17,12 +17,13 @@ class TestInlineObjectsResponse200: a_property: Union[Unset, str] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property = self.a_property + prop1 = self.a_property field_dict: Dict[str, Any] = {} - field_dict.update({}) - if a_property is not UNSET: - field_dict["a_property"] = a_property + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"a_property": prop1}), + } return field_dict diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py index 6ff5d4790..cb3044349 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py @@ -19,20 +19,18 @@ class ValidationError: type: str def to_dict(self) -> Dict[str, Any]: - loc = self.loc + prop1 = self.loc - msg = self.msg - - type = self.type + prop2 = self.msg + prop3 = self.type field_dict: Dict[str, Any] = {} - field_dict.update( - { - "loc": loc, - "msg": msg, - "type": type, - } - ) + field_dict = { + **field_dict, + "loc": prop1, + "msg": prop2, + "type": prop3, + } return field_dict diff --git a/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/a_model.py b/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/a_model.py index e05fdaa6d..400e42dbe 100644 --- a/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/a_model.py +++ b/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/a_model.py @@ -29,40 +29,33 @@ class AModel: nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET def to_dict(self) -> Dict[str, Any]: - an_enum_value: str = self.an_enum_value - - an_allof_enum_with_overridden_default: str = self.an_allof_enum_with_overridden_default - - any_value = self.any_value - - an_optional_allof_enum: Union[Unset, str] = UNSET + prop1: str = self.an_enum_value + prop2: str = self.an_allof_enum_with_overridden_default + prop3 = self.any_value + prop4: Union[Unset, str] = UNSET if not isinstance(self.an_optional_allof_enum, Unset): - an_optional_allof_enum = self.an_optional_allof_enum + prop4 = self.an_optional_allof_enum - nested_list_of_enums: Union[Unset, List[List[str]]] = UNSET + prop5: Union[Unset, List[List[str]]] = UNSET if not isinstance(self.nested_list_of_enums, Unset): - nested_list_of_enums = [] + prop5 = [] for nested_list_of_enums_item_data in self.nested_list_of_enums: nested_list_of_enums_item = [] for nested_list_of_enums_item_item_data in nested_list_of_enums_item_data: nested_list_of_enums_item_item: str = nested_list_of_enums_item_item_data nested_list_of_enums_item.append(nested_list_of_enums_item_item) - nested_list_of_enums.append(nested_list_of_enums_item) + prop5.append(nested_list_of_enums_item) field_dict: Dict[str, Any] = {} - field_dict.update( - { - "an_enum_value": an_enum_value, - "an_allof_enum_with_overridden_default": an_allof_enum_with_overridden_default, - } - ) - if any_value is not UNSET: - field_dict["any_value"] = any_value - if an_optional_allof_enum is not UNSET: - field_dict["an_optional_allof_enum"] = an_optional_allof_enum - if nested_list_of_enums is not UNSET: - field_dict["nested_list_of_enums"] = nested_list_of_enums + field_dict = { + **field_dict, + "an_enum_value": prop1, + "an_allof_enum_with_overridden_default": prop2, + **({} if prop3 is UNSET else {"any_value": prop3}), + **({} if prop4 is UNSET else {"an_optional_allof_enum": prop4}), + **({} if prop5 is UNSET else {"nested_list_of_enums": prop5}), + } return field_dict diff --git a/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py b/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py index e61cb4183..e8bb4bf25 100644 --- a/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py +++ b/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py @@ -34,136 +34,120 @@ class PostUserListBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - an_enum_value: Union[Unset, List[str]] = UNSET + prop1: Union[Unset, List[str]] = UNSET if not isinstance(self.an_enum_value, Unset): - an_enum_value = [] + prop1 = [] for an_enum_value_item_data in self.an_enum_value: an_enum_value_item: str = an_enum_value_item_data - an_enum_value.append(an_enum_value_item) + prop1.append(an_enum_value_item) - an_enum_value_with_null: Union[Unset, List[Union[None, str]]] = UNSET + prop2: Union[Unset, List[Union[None, str]]] = UNSET if not isinstance(self.an_enum_value_with_null, Unset): - an_enum_value_with_null = [] + prop2 = [] for an_enum_value_with_null_item_data in self.an_enum_value_with_null: an_enum_value_with_null_item: Union[None, str] if isinstance(an_enum_value_with_null_item_data, str): an_enum_value_with_null_item = an_enum_value_with_null_item_data else: an_enum_value_with_null_item = an_enum_value_with_null_item_data - an_enum_value_with_null.append(an_enum_value_with_null_item) + prop2.append(an_enum_value_with_null_item) - an_enum_value_with_only_null: Union[Unset, List[None]] = UNSET + prop3: Union[Unset, List[None]] = UNSET if not isinstance(self.an_enum_value_with_only_null, Unset): - an_enum_value_with_only_null = self.an_enum_value_with_only_null + prop3 = self.an_enum_value_with_only_null - an_allof_enum_with_overridden_default: Union[Unset, str] = UNSET + prop4: Union[Unset, str] = UNSET if not isinstance(self.an_allof_enum_with_overridden_default, Unset): - an_allof_enum_with_overridden_default = self.an_allof_enum_with_overridden_default + prop4 = self.an_allof_enum_with_overridden_default - an_optional_allof_enum: Union[Unset, str] = UNSET + prop5: Union[Unset, str] = UNSET if not isinstance(self.an_optional_allof_enum, Unset): - an_optional_allof_enum = self.an_optional_allof_enum + prop5 = self.an_optional_allof_enum - nested_list_of_enums: Union[Unset, List[List[str]]] = UNSET + prop6: Union[Unset, List[List[str]]] = UNSET if not isinstance(self.nested_list_of_enums, Unset): - nested_list_of_enums = [] + prop6 = [] for nested_list_of_enums_item_data in self.nested_list_of_enums: nested_list_of_enums_item = [] for nested_list_of_enums_item_item_data in nested_list_of_enums_item_data: nested_list_of_enums_item_item: str = nested_list_of_enums_item_item_data nested_list_of_enums_item.append(nested_list_of_enums_item_item) - nested_list_of_enums.append(nested_list_of_enums_item) + prop6.append(nested_list_of_enums_item) field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if an_enum_value is not UNSET: - field_dict["an_enum_value"] = an_enum_value - if an_enum_value_with_null is not UNSET: - field_dict["an_enum_value_with_null"] = an_enum_value_with_null - if an_enum_value_with_only_null is not UNSET: - field_dict["an_enum_value_with_only_null"] = an_enum_value_with_only_null - if an_allof_enum_with_overridden_default is not UNSET: - field_dict["an_allof_enum_with_overridden_default"] = an_allof_enum_with_overridden_default - if an_optional_allof_enum is not UNSET: - field_dict["an_optional_allof_enum"] = an_optional_allof_enum - if nested_list_of_enums is not UNSET: - field_dict["nested_list_of_enums"] = nested_list_of_enums + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"an_enum_value": prop1}), + **({} if prop2 is UNSET else {"an_enum_value_with_null": prop2}), + **({} if prop3 is UNSET else {"an_enum_value_with_only_null": prop3}), + **({} if prop4 is UNSET else {"an_allof_enum_with_overridden_default": prop4}), + **({} if prop5 is UNSET else {"an_optional_allof_enum": prop5}), + **({} if prop6 is UNSET else {"nested_list_of_enums": prop6}), + } return field_dict def to_multipart(self) -> Dict[str, Any]: - an_enum_value: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop1: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.an_enum_value, Unset): - _temp_an_enum_value = [] + _temp_prop1 = [] for an_enum_value_item_data in self.an_enum_value: an_enum_value_item: str = an_enum_value_item_data - _temp_an_enum_value.append(an_enum_value_item) - an_enum_value = (None, json.dumps(_temp_an_enum_value).encode(), "application/json") + _temp_prop1.append(an_enum_value_item) + prop1 = (None, json.dumps(_temp_prop1).encode(), "application/json") - an_enum_value_with_null: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop2: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.an_enum_value_with_null, Unset): - _temp_an_enum_value_with_null = [] + _temp_prop2 = [] for an_enum_value_with_null_item_data in self.an_enum_value_with_null: an_enum_value_with_null_item: Union[None, str] if isinstance(an_enum_value_with_null_item_data, str): an_enum_value_with_null_item = an_enum_value_with_null_item_data else: an_enum_value_with_null_item = an_enum_value_with_null_item_data - _temp_an_enum_value_with_null.append(an_enum_value_with_null_item) - an_enum_value_with_null = (None, json.dumps(_temp_an_enum_value_with_null).encode(), "application/json") + _temp_prop2.append(an_enum_value_with_null_item) + prop2 = (None, json.dumps(_temp_prop2).encode(), "application/json") - an_enum_value_with_only_null: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop3: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.an_enum_value_with_only_null, Unset): - _temp_an_enum_value_with_only_null = self.an_enum_value_with_only_null - an_enum_value_with_only_null = ( - None, - json.dumps(_temp_an_enum_value_with_only_null).encode(), - "application/json", - ) - - an_allof_enum_with_overridden_default: Union[Unset, Tuple[None, bytes, str]] = UNSET + _temp_prop3 = self.an_enum_value_with_only_null + prop3 = (None, json.dumps(_temp_prop3).encode(), "application/json") + + prop4: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.an_allof_enum_with_overridden_default, Unset): - an_allof_enum_with_overridden_default = ( - None, - str(self.an_allof_enum_with_overridden_default).encode(), - "text/plain", - ) + prop4 = (None, str(self.an_allof_enum_with_overridden_default).encode(), "text/plain") - an_optional_allof_enum: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop5: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.an_optional_allof_enum, Unset): - an_optional_allof_enum = (None, str(self.an_optional_allof_enum).encode(), "text/plain") + prop5 = (None, str(self.an_optional_allof_enum).encode(), "text/plain") - nested_list_of_enums: Union[Unset, Tuple[None, bytes, str]] = UNSET + prop6: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.nested_list_of_enums, Unset): - _temp_nested_list_of_enums = [] + _temp_prop6 = [] for nested_list_of_enums_item_data in self.nested_list_of_enums: nested_list_of_enums_item = [] for nested_list_of_enums_item_item_data in nested_list_of_enums_item_data: nested_list_of_enums_item_item: str = nested_list_of_enums_item_item_data nested_list_of_enums_item.append(nested_list_of_enums_item_item) - _temp_nested_list_of_enums.append(nested_list_of_enums_item) - nested_list_of_enums = (None, json.dumps(_temp_nested_list_of_enums).encode(), "application/json") + _temp_prop6.append(nested_list_of_enums_item) + prop6 = (None, json.dumps(_temp_prop6).encode(), "application/json") field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = (None, str(prop).encode(), "text/plain") - field_dict.update({}) - if an_enum_value is not UNSET: - field_dict["an_enum_value"] = an_enum_value - if an_enum_value_with_null is not UNSET: - field_dict["an_enum_value_with_null"] = an_enum_value_with_null - if an_enum_value_with_only_null is not UNSET: - field_dict["an_enum_value_with_only_null"] = an_enum_value_with_only_null - if an_allof_enum_with_overridden_default is not UNSET: - field_dict["an_allof_enum_with_overridden_default"] = an_allof_enum_with_overridden_default - if an_optional_allof_enum is not UNSET: - field_dict["an_optional_allof_enum"] = an_optional_allof_enum - if nested_list_of_enums is not UNSET: - field_dict["nested_list_of_enums"] = nested_list_of_enums + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"an_enum_value": prop1}), + **({} if prop2 is UNSET else {"an_enum_value_with_null": prop2}), + **({} if prop3 is UNSET else {"an_enum_value_with_only_null": prop3}), + **({} if prop4 is UNSET else {"an_allof_enum_with_overridden_default": prop4}), + **({} if prop5 is UNSET else {"an_optional_allof_enum": prop5}), + **({} if prop6 is UNSET else {"nested_list_of_enums": prop6}), + } return field_dict diff --git a/end_to_end_tests/openapi_3.1_skip-read-only.yaml b/end_to_end_tests/openapi_3.1_skip-read-only.yaml new file mode 100644 index 000000000..236b1191c --- /dev/null +++ b/end_to_end_tests/openapi_3.1_skip-read-only.yaml @@ -0,0 +1,54 @@ +openapi: 3.1.0 +info: + title: My Read-Only Properties API + description: An API for testing the skip_read_only_properties option + version: 0.1.0 +paths: + /thing/json: + post: + tags: + - things + description: Post a thing in JSON + operationId: postThingJson + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Thing" + responses: + '200': + description: OK + /thing/multipart: + post: + tags: + - things + description: Post a thing in multipart form data + operationId: postThingMultipart + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/Thing" + responses: + '200': + description: OK +components: + schemas: + Thing: + type: object + properties: + reqProp1ReadWrite: + type: string + reqProp2ReadOnly: + type: string + readOnly: true + optProp1ReadWrite: + type: string + optProp2ReadOnly: + type: string + readOnly: true + required: + - reqProp1ReadWrite + - reqProp2ReadOnly +tags: + - name: things diff --git a/end_to_end_tests/regen_golden_record.py b/end_to_end_tests/regen_golden_record.py index 2471e1340..35648b50d 100644 --- a/end_to_end_tests/regen_golden_record.py +++ b/end_to_end_tests/regen_golden_record.py @@ -10,20 +10,28 @@ from openapi_python_client.cli import app -def regen_golden_record(): +def regen( + spec_file_name: str, + config_file_name: str, + golden_record_dir_name: str, + output_dir_name: str, +): runner = CliRunner() - openapi_path = Path(__file__).parent / "baseline_openapi_3.0.json" + openapi_path = Path(__file__).parent / spec_file_name - gr_path = Path(__file__).parent / "golden-record" - output_path = Path.cwd() / "my-test-api-client" - config_path = Path(__file__).parent / "config.yml" + gr_path = Path(__file__).parent / golden_record_dir_name + output_path = Path.cwd() / output_dir_name + config_path = Path(__file__).parent / config_file_name if config_file_name else None shutil.rmtree(gr_path, ignore_errors=True) shutil.rmtree(output_path, ignore_errors=True) - result = runner.invoke( - app, ["generate", f"--config={config_path}", f"--path={openapi_path}"] - ) + args = [ + "generate", + f"--path={openapi_path}", + *([f"--config={config_path}"] if config_path else []), + ] + result = runner.invoke(app, args) if result.stdout: print(result.stdout) @@ -32,43 +40,16 @@ def regen_golden_record(): output_path.rename(gr_path) -def regen_golden_record_3_1_features(): - runner = CliRunner() - openapi_path = Path(__file__).parent / "3.1_specific.openapi.yaml" - - gr_path = Path(__file__).parent / "test-3-1-golden-record" - output_path = Path.cwd() / "test-3-1-features-client" - - shutil.rmtree(gr_path, ignore_errors=True) - shutil.rmtree(output_path, ignore_errors=True) +def regen_golden_record(): + regen("baseline_openapi_3.0.json", "config.yml", "golden-record", "my-test-api-client") - result = runner.invoke(app, ["generate", f"--path={openapi_path}"]) - if result.stdout: - print(result.stdout) - if result.exception: - raise result.exception - output_path.rename(gr_path) +def regen_golden_record_3_1_features(): + regen("3.1_specific.openapi.yaml", "", "test-3-1-golden-record", "test-3-1-features-client") def regen_literal_enums_golden_record(): - runner = CliRunner() - openapi_path = Path(__file__).parent / "openapi_3.1_enums.yaml" - - gr_path = Path(__file__).parent / "literal-enums-golden-record" - output_path = Path.cwd() / "my-enum-api-client" - config_path = Path(__file__).parent / "literal_enums.config.yml" - - shutil.rmtree(gr_path, ignore_errors=True) - shutil.rmtree(output_path, ignore_errors=True) - - result = runner.invoke(app, ["generate", f"--path={openapi_path}", f"--config={config_path}"]) - - if result.stdout: - print(result.stdout) - if result.exception: - raise result.exception - output_path.rename(gr_path) + regen("openapi_3.1_enums.yaml", "literal_enums.config.yml", "literal-enums-golden-record", "my-enum-api-client") def regen_metadata_snapshots(): @@ -139,9 +120,19 @@ def regen_custom_template_golden_record(): raise result.exception +def regen_skip_read_only_golden_record(): + regen( + "openapi_3.1_skip-read-only.yaml", + "config-skip-read-only.yml", + "golden-record-skip-read-only", + "my-read-only-properties-api-client", + ) + + if __name__ == "__main__": regen_golden_record() regen_golden_record_3_1_features() regen_metadata_snapshots() regen_custom_template_golden_record() regen_literal_enums_golden_record() + regen_skip_read_only_golden_record() diff --git a/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_const_path_body.py b/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_const_path_body.py index 9ac2f9102..46ccbbcad 100644 --- a/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_const_path_body.py +++ b/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_const_path_body.py @@ -23,23 +23,19 @@ class PostConstPathBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - required = self.required - - nullable: Union[Literal["this or null goes in the body"], None] - nullable = self.nullable - - optional = self.optional + prop1 = self.required + prop2: Union[Literal["this or null goes in the body"], None] + prop2 = self.nullable + prop3 = self.optional field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "required": required, - "nullable": nullable, - } - ) - if optional is not UNSET: - field_dict["optional"] = optional + field_dict = { + **field_dict, + "required": prop1, + "nullable": prop2, + **({} if prop3 is UNSET else {"optional": prop3}), + } return field_dict diff --git a/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_prefix_items_body.py b/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_prefix_items_body.py index f3edd841d..2748ade7d 100644 --- a/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_prefix_items_body.py +++ b/end_to_end_tests/test-3-1-golden-record/test_3_1_features_client/models/post_prefix_items_body.py @@ -21,29 +21,29 @@ class PostPrefixItemsBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - prefix_items_and_items: Union[Unset, List[Union[Literal["prefix"], float, str]]] = UNSET + prop1: Union[Unset, List[Union[Literal["prefix"], float, str]]] = UNSET if not isinstance(self.prefix_items_and_items, Unset): - prefix_items_and_items = [] + prop1 = [] for prefix_items_and_items_item_data in self.prefix_items_and_items: prefix_items_and_items_item: Union[Literal["prefix"], float, str] prefix_items_and_items_item = prefix_items_and_items_item_data - prefix_items_and_items.append(prefix_items_and_items_item) + prop1.append(prefix_items_and_items_item) - prefix_items_only: Union[Unset, List[Union[float, str]]] = UNSET + prop2: Union[Unset, List[Union[float, str]]] = UNSET if not isinstance(self.prefix_items_only, Unset): - prefix_items_only = [] + prop2 = [] for prefix_items_only_item_data in self.prefix_items_only: prefix_items_only_item: Union[float, str] prefix_items_only_item = prefix_items_only_item_data - prefix_items_only.append(prefix_items_only_item) + prop2.append(prefix_items_only_item) field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if prefix_items_and_items is not UNSET: - field_dict["prefixItemsAndItems"] = prefix_items_and_items - if prefix_items_only is not UNSET: - field_dict["prefixItemsOnly"] = prefix_items_only + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"prefixItemsAndItems": prop1}), + **({} if prop2 is UNSET else {"prefixItemsOnly": prop2}), + } return field_dict diff --git a/integration-tests/integration_tests/models/post_body_multipart_body.py b/integration-tests/integration_tests/models/post_body_multipart_body.py index f0272a34e..3f84d28e4 100644 --- a/integration-tests/integration_tests/models/post_body_multipart_body.py +++ b/integration-tests/integration_tests/models/post_body_multipart_body.py @@ -25,31 +25,28 @@ class PostBodyMultipartBody: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a_string = self.a_string + prop1 = self.a_string + prop2 = self.file.to_tuple() - file = self.file.to_tuple() - - description = self.description + prop3 = self.description field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "a_string": a_string, - "file": file, - } - ) - if description is not UNSET: - field_dict["description"] = description + field_dict = { + **field_dict, + "a_string": prop1, + "file": prop2, + **({} if prop3 is UNSET else {"description": prop3}), + } return field_dict def to_multipart(self) -> Dict[str, Any]: - a_string = (None, str(self.a_string).encode(), "text/plain") + prop1 = (None, str(self.a_string).encode(), "text/plain") - file = self.file.to_tuple() + prop2 = self.file.to_tuple() - description = ( + prop3 = ( self.description if isinstance(self.description, Unset) else (None, str(self.description).encode(), "text/plain") @@ -59,14 +56,12 @@ def to_multipart(self) -> Dict[str, Any]: for prop_name, prop in self.additional_properties.items(): field_dict[prop_name] = (None, str(prop).encode(), "text/plain") - field_dict.update( - { - "a_string": a_string, - "file": file, - } - ) - if description is not UNSET: - field_dict["description"] = description + field_dict = { + **field_dict, + "a_string": prop1, + "file": prop2, + **({} if prop3 is UNSET else {"description": prop3}), + } return field_dict diff --git a/integration-tests/integration_tests/models/post_body_multipart_response_200.py b/integration-tests/integration_tests/models/post_body_multipart_response_200.py index 79359ec41..e23b157ce 100644 --- a/integration-tests/integration_tests/models/post_body_multipart_response_200.py +++ b/integration-tests/integration_tests/models/post_body_multipart_response_200.py @@ -25,27 +25,22 @@ class PostBodyMultipartResponse200: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - a_string = self.a_string - - file_data = self.file_data - - description = self.description - - file_name = self.file_name - - file_content_type = self.file_content_type + prop1 = self.a_string + prop2 = self.file_data + prop3 = self.description + prop4 = self.file_name + prop5 = self.file_content_type field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "a_string": a_string, - "file_data": file_data, - "description": description, - "file_name": file_name, - "file_content_type": file_content_type, - } - ) + field_dict = { + **field_dict, + "a_string": prop1, + "file_data": prop2, + "description": prop3, + "file_name": prop4, + "file_content_type": prop5, + } return field_dict diff --git a/integration-tests/integration_tests/models/post_parameters_header_response_200.py b/integration-tests/integration_tests/models/post_parameters_header_response_200.py index 03e688ba1..17e800b79 100644 --- a/integration-tests/integration_tests/models/post_parameters_header_response_200.py +++ b/integration-tests/integration_tests/models/post_parameters_header_response_200.py @@ -23,24 +23,20 @@ class PostParametersHeaderResponse200: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - boolean = self.boolean - - string = self.string - - number = self.number - - integer = self.integer + prop1 = self.boolean + prop2 = self.string + prop3 = self.number + prop4 = self.integer field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "boolean": boolean, - "string": string, - "number": number, - "integer": integer, - } - ) + field_dict = { + **field_dict, + "boolean": prop1, + "string": prop2, + "number": prop3, + "integer": prop4, + } return field_dict diff --git a/integration-tests/integration_tests/models/problem.py b/integration-tests/integration_tests/models/problem.py index bde5b6d37..85815a56d 100644 --- a/integration-tests/integration_tests/models/problem.py +++ b/integration-tests/integration_tests/models/problem.py @@ -21,17 +21,16 @@ class Problem: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - parameter_name = self.parameter_name - - description = self.description + prop1 = self.parameter_name + prop2 = self.description field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if parameter_name is not UNSET: - field_dict["parameter_name"] = parameter_name - if description is not UNSET: - field_dict["description"] = description + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"parameter_name": prop1}), + **({} if prop2 is UNSET else {"description": prop2}), + } return field_dict diff --git a/integration-tests/integration_tests/models/public_error.py b/integration-tests/integration_tests/models/public_error.py index 993bd8ad3..cdd88d454 100644 --- a/integration-tests/integration_tests/models/public_error.py +++ b/integration-tests/integration_tests/models/public_error.py @@ -29,36 +29,34 @@ class PublicError: additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: - errors: Union[Unset, List[str]] = UNSET + prop1: Union[Unset, List[str]] = UNSET if not isinstance(self.errors, Unset): - errors = self.errors + prop1 = self.errors - extra_parameters: Union[Unset, List[str]] = UNSET + prop2: Union[Unset, List[str]] = UNSET if not isinstance(self.extra_parameters, Unset): - extra_parameters = self.extra_parameters + prop2 = self.extra_parameters - invalid_parameters: Union[Unset, List[Dict[str, Any]]] = UNSET + prop3: Union[Unset, List[Dict[str, Any]]] = UNSET if not isinstance(self.invalid_parameters, Unset): - invalid_parameters = [] + prop3 = [] for invalid_parameters_item_data in self.invalid_parameters: invalid_parameters_item = invalid_parameters_item_data.to_dict() - invalid_parameters.append(invalid_parameters_item) + prop3.append(invalid_parameters_item) - missing_parameters: Union[Unset, List[str]] = UNSET + prop4: Union[Unset, List[str]] = UNSET if not isinstance(self.missing_parameters, Unset): - missing_parameters = self.missing_parameters + prop4 = self.missing_parameters field_dict: Dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({}) - if errors is not UNSET: - field_dict["errors"] = errors - if extra_parameters is not UNSET: - field_dict["extra_parameters"] = extra_parameters - if invalid_parameters is not UNSET: - field_dict["invalid_parameters"] = invalid_parameters - if missing_parameters is not UNSET: - field_dict["missing_parameters"] = missing_parameters + field_dict = { + **field_dict, + **({} if prop1 is UNSET else {"errors": prop1}), + **({} if prop2 is UNSET else {"extra_parameters": prop2}), + **({} if prop3 is UNSET else {"invalid_parameters": prop3}), + **({} if prop4 is UNSET else {"missing_parameters": prop4}), + } return field_dict diff --git a/openapi_python_client/__init__.py b/openapi_python_client/__init__.py index f2cfb40ec..951dda92b 100644 --- a/openapi_python_client/__init__.py +++ b/openapi_python_client/__init__.py @@ -100,6 +100,7 @@ def __init__( project_dir=self.project_dir, openapi=self.openapi, endpoint_collections_by_tag=self.openapi.endpoint_collections_by_tag, + config=config, ) self.errors: List[GeneratorError] = [] diff --git a/openapi_python_client/config.py b/openapi_python_client/config.py index 6625bda1f..648f0710b 100644 --- a/openapi_python_client/config.py +++ b/openapi_python_client/config.py @@ -44,6 +44,7 @@ class ConfigFile(BaseModel): field_prefix: str = "field_" http_timeout: int = 5 literal_enums: bool = False + skip_sending_read_only_properties: bool = False @staticmethod def load_from_path(path: Path) -> "ConfigFile": @@ -72,6 +73,7 @@ class Config: field_prefix: str http_timeout: int literal_enums: bool + skip_sending_read_only_properties: bool document_source: Union[Path, str] file_encoding: str content_type_overrides: Dict[str, str] @@ -112,6 +114,7 @@ def from_sources( field_prefix=config_file.field_prefix, http_timeout=config_file.http_timeout, literal_enums=config_file.literal_enums, + skip_sending_read_only_properties=config_file.skip_sending_read_only_properties, document_source=document_source, file_encoding=file_encoding, overwrite=overwrite, diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 94c6e3d08..f50136462 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -137,7 +137,7 @@ def _property_from_ref( return prop, schemas -def property_from_data( # noqa: PLR0911, PLR0912 +def property_from_data( name: str, required: bool, data: oai.Reference | oai.Schema, @@ -161,6 +161,24 @@ def property_from_data( # noqa: PLR0911, PLR0912 roots=roots, ) + prop, schemas = _property_from_data(name, required, data, schemas, parent_name, config, process_properties, roots) + if not isinstance(prop, PropertyError) and isinstance(data, oai.Schema): + updated_prop = evolve(prop, read_only=data.readOnly or False) + schemas = _replace_schema(schemas, prop, updated_prop) + prop = updated_prop + return prop, schemas + + +def _property_from_data( # noqa: PLR0911, PLR0912 + name: str, + required: bool, + data: oai.Schema, + schemas: Schemas, + parent_name: str, + config: Config, + process_properties: bool, + roots: set[ReferencePath | utils.ClassName], +) -> tuple[Property | PropertyError, Schemas]: sub_data: list[oai.Schema | oai.Reference] = data.allOf + data.anyOf + data.oneOf # A union of a single reference should just be passed through to that reference (don't create copy class) if len(sub_data) == 1 and isinstance(sub_data[0], oai.Reference): @@ -405,6 +423,29 @@ def _process_models(*, schemas: Schemas, config: Config) -> Schemas: return evolve(schemas, errors=[*schemas.errors, *errors], models_to_process=to_process) +def _replace_schema(schemas: Schemas, original_prop: Property, updated_prop: Property) -> Schemas: + if isinstance(original_prop, (ModelProperty, EnumProperty)): + # TODO: replace that check with a protocol method like "has_class_info" + class_info = original_prop.class_info + if class_info.name in schemas.classes_by_name: + schemas = evolve( + schemas, + classes_by_name={**schemas.classes_by_name, class_info.name: updated_prop}, + ) + # We don't have to worry about classes_by_reference, because that gets populated at + # a higher level after property_from_data has returned. + if isinstance(original_prop, ModelProperty) and isinstance(updated_prop, ModelProperty): + # TODO: if models_to_process is generalized to hold other types, replace that check + # with a protocol method like "needs_post_processing" + updated_list = schemas.models_to_process.copy() + # Currently models_to_process is defined as a list of ModelProperty only, but that will + # change, so for now let's do this step for all + updated_list.remove(original_prop) + updated_list.append(updated_prop) + schemas = evolve(schemas, models_to_process=updated_list) + return schemas + + def build_schemas( *, components: dict[str, oai.Reference | oai.Schema], diff --git a/openapi_python_client/parser/properties/any.py b/openapi_python_client/parser/properties/any.py index b760a1568..88040d583 100644 --- a/openapi_python_client/parser/properties/any.py +++ b/openapi_python_client/parser/properties/any.py @@ -47,5 +47,6 @@ def convert_value(cls, value: Any) -> Value | None: python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "Any" _json_type_string: ClassVar[str] = "Any" diff --git a/openapi_python_client/parser/properties/boolean.py b/openapi_python_client/parser/properties/boolean.py index 5fd4235d7..b409ee5dc 100644 --- a/openapi_python_client/parser/properties/boolean.py +++ b/openapi_python_client/parser/properties/boolean.py @@ -20,6 +20,7 @@ class BooleanProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "bool" _json_type_string: ClassVar[str] = "bool" diff --git a/openapi_python_client/parser/properties/const.py b/openapi_python_client/parser/properties/const.py index 8b9967f19..1c1492498 100644 --- a/openapi_python_client/parser/properties/const.py +++ b/openapi_python_client/parser/properties/const.py @@ -21,6 +21,7 @@ class ConstProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: None + read_only: bool = False template: ClassVar[str] = "const_property.py.jinja" @classmethod diff --git a/openapi_python_client/parser/properties/date.py b/openapi_python_client/parser/properties/date.py index 7261698ea..fc9d0f4d9 100644 --- a/openapi_python_client/parser/properties/date.py +++ b/openapi_python_client/parser/properties/date.py @@ -20,6 +20,7 @@ class DateProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "datetime.date" _json_type_string: ClassVar[str] = "str" diff --git a/openapi_python_client/parser/properties/datetime.py b/openapi_python_client/parser/properties/datetime.py index 5924d173c..d9c05e242 100644 --- a/openapi_python_client/parser/properties/datetime.py +++ b/openapi_python_client/parser/properties/datetime.py @@ -22,6 +22,7 @@ class DateTimeProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "datetime.datetime" _json_type_string: ClassVar[str] = "str" diff --git a/openapi_python_client/parser/properties/enum_property.py b/openapi_python_client/parser/properties/enum_property.py index 29609864f..e4e2f5538 100644 --- a/openapi_python_client/parser/properties/enum_property.py +++ b/openapi_python_client/parser/properties/enum_property.py @@ -32,6 +32,7 @@ class EnumProperty(PropertyProtocol): values: dict[str, ValueType] class_info: Class value_type: type[ValueType] + read_only: bool = False template: ClassVar[str] = "enum_property.py.jinja" diff --git a/openapi_python_client/parser/properties/file.py b/openapi_python_client/parser/properties/file.py index 505876b63..954a01422 100644 --- a/openapi_python_client/parser/properties/file.py +++ b/openapi_python_client/parser/properties/file.py @@ -19,6 +19,7 @@ class FileProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "File" # Return type of File.to_tuple() diff --git a/openapi_python_client/parser/properties/float.py b/openapi_python_client/parser/properties/float.py index a785db6d4..4fe2ece65 100644 --- a/openapi_python_client/parser/properties/float.py +++ b/openapi_python_client/parser/properties/float.py @@ -20,6 +20,7 @@ class FloatProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "float" _json_type_string: ClassVar[str] = "float" diff --git a/openapi_python_client/parser/properties/int.py b/openapi_python_client/parser/properties/int.py index 1cd340fbd..40fc98a2c 100644 --- a/openapi_python_client/parser/properties/int.py +++ b/openapi_python_client/parser/properties/int.py @@ -20,6 +20,7 @@ class IntProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "int" _json_type_string: ClassVar[str] = "int" diff --git a/openapi_python_client/parser/properties/list_property.py b/openapi_python_client/parser/properties/list_property.py index 47a52cda3..c482b3303 100644 --- a/openapi_python_client/parser/properties/list_property.py +++ b/openapi_python_client/parser/properties/list_property.py @@ -22,6 +22,7 @@ class ListProperty(PropertyProtocol): description: str | None example: str | None inner_property: PropertyProtocol + read_only: bool = False template: ClassVar[str] = "list_property.py.jinja" @classmethod diff --git a/openapi_python_client/parser/properties/literal_enum_property.py b/openapi_python_client/parser/properties/literal_enum_property.py index c305a9a41..0cfebcfe6 100644 --- a/openapi_python_client/parser/properties/literal_enum_property.py +++ b/openapi_python_client/parser/properties/literal_enum_property.py @@ -32,6 +32,7 @@ class LiteralEnumProperty(PropertyProtocol): values: set[ValueType] class_info: Class value_type: type[ValueType] + read_only: bool = False template: ClassVar[str] = "literal_enum_property.py.jinja" diff --git a/openapi_python_client/parser/properties/merge_properties.py b/openapi_python_client/parser/properties/merge_properties.py index db6424a7c..1c98ec989 100644 --- a/openapi_python_client/parser/properties/merge_properties.py +++ b/openapi_python_client/parser/properties/merge_properties.py @@ -190,6 +190,7 @@ def _merge_common_attributes(base: PropertyT, *extend_with: PropertyProtocol) -> default=override_default or current.default, description=override.description or current.description, example=override.example or current.example, + read_only=override.read_only or current.read_only, ) return current diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py index 0dc13be54..2354c4846 100644 --- a/openapi_python_client/parser/properties/model_property.py +++ b/openapi_python_client/parser/properties/model_property.py @@ -32,6 +32,7 @@ class ModelProperty(PropertyProtocol): relative_imports: set[str] | None lazy_imports: set[str] | None additional_properties: Property | None + read_only: bool = False _json_type_string: ClassVar[str] = "Dict[str, Any]" template: ClassVar[str] = "model_property.py.jinja" diff --git a/openapi_python_client/parser/properties/none.py b/openapi_python_client/parser/properties/none.py index 9c473693d..ea09ff232 100644 --- a/openapi_python_client/parser/properties/none.py +++ b/openapi_python_client/parser/properties/none.py @@ -20,6 +20,7 @@ class NoneProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _allowed_locations: ClassVar[set[oai.ParameterLocation]] = { oai.ParameterLocation.QUERY, diff --git a/openapi_python_client/parser/properties/protocol.py b/openapi_python_client/parser/properties/protocol.py index c9555949d..1bf28d3f5 100644 --- a/openapi_python_client/parser/properties/protocol.py +++ b/openapi_python_client/parser/properties/protocol.py @@ -58,6 +58,7 @@ class PropertyProtocol(Protocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool template: ClassVar[str] = "any_property.py.jinja" json_is_dict: ClassVar[bool] = False diff --git a/openapi_python_client/parser/properties/string.py b/openapi_python_client/parser/properties/string.py index e40c1eee6..64142e8b3 100644 --- a/openapi_python_client/parser/properties/string.py +++ b/openapi_python_client/parser/properties/string.py @@ -21,6 +21,7 @@ class StringProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "str" _json_type_string: ClassVar[str] = "str" _allowed_locations: ClassVar[set[oai.ParameterLocation]] = { diff --git a/openapi_python_client/parser/properties/union.py b/openapi_python_client/parser/properties/union.py index 8b7b02a48..db0225c17 100644 --- a/openapi_python_client/parser/properties/union.py +++ b/openapi_python_client/parser/properties/union.py @@ -24,6 +24,7 @@ class UnionProperty(PropertyProtocol): description: str | None example: str | None inner_properties: list[PropertyProtocol] + read_only: bool = False template: ClassVar[str] = "union_property.py.jinja" @classmethod diff --git a/openapi_python_client/parser/properties/uuid.py b/openapi_python_client/parser/properties/uuid.py index 86d7d6a0a..71c5760b0 100644 --- a/openapi_python_client/parser/properties/uuid.py +++ b/openapi_python_client/parser/properties/uuid.py @@ -21,6 +21,7 @@ class UuidProperty(PropertyProtocol): python_name: PythonIdentifier description: str | None example: str | None + read_only: bool = False _type_string: ClassVar[str] = "UUID" _json_type_string: ClassVar[str] = "str" diff --git a/openapi_python_client/templates/endpoint_module.py.jinja b/openapi_python_client/templates/endpoint_module.py.jinja index d89f09367..2ed55ace0 100644 --- a/openapi_python_client/templates/endpoint_module.py.jinja +++ b/openapi_python_client/templates/endpoint_module.py.jinja @@ -1,4 +1,5 @@ from http import HTTPStatus +import threading from typing import Any, Dict, List, Optional, Union, cast import httpx @@ -45,20 +46,34 @@ def _get_kwargs( {% endif %} } +{% macro set_body(endpoint) %} {% if endpoint.bodies | length > 1 %} -{% for body in endpoint.bodies %} - if isinstance(body, {{body.prop.get_type_string() }}): + {% for body in endpoint.bodies %} +if isinstance(body, {{body.prop.get_type_string() }}): {% set destination = "_" + body.body_type + "_body" %} - {{ body_to_kwarg(body, destination) | indent(8) }} - _kwargs["{{ body.body_type.value }}"] = {{ destination }} - headers["Content-Type"] = "{{ body.content_type }}" -{% endfor %} +{{ body_to_kwarg(body, destination) | indent(4, True) }} + _kwargs["{{ body.body_type.value }}"] = {{ destination }} + headers["Content-Type"] = "{{ body.content_type }}" + {% endfor %} {% elif endpoint.bodies | length == 1 %} -{% set body = endpoint.bodies[0] %} - {{ body_to_kwarg(body, "_body") | indent(4) }} - _kwargs["{{ body.body_type.value }}"] = _body + {% set body = endpoint.bodies[0] %} +{{ body_to_kwarg(body, "_body") }} +_kwargs["{{ body.body_type.value }}"] = _body {% if body.content_type != "multipart/form-data" %}{# Need httpx to set the boundary automatically #} - headers["Content-Type"] = "{{ body.content_type }}" +headers["Content-Type"] = "{{ body.content_type }}" + {% endif %} +{% endif %} +{% endmacro %} + +{% if endpoint.bodies %} + {% if config.skip_sending_read_only_properties %} + try: + threading.local.openapi_serialization_context = {"request_body": True} +{{ set_body(endpoint) | indent(8, True) }} + finally: + del(threading.local.openapi_serialization_context) + {% else %} +{{ set_body(endpoint) | indent(4, True) }} {% endif %} {% endif %} diff --git a/openapi_python_client/templates/model.py.jinja b/openapi_python_client/templates/model.py.jinja index 012201426..711cbbb5b 100644 --- a/openapi_python_client/templates/model.py.jinja +++ b/openapi_python_client/templates/model.py.jinja @@ -1,3 +1,4 @@ +import threading from typing import Any, Dict, Type, TypeVar, Tuple, Optional, BinaryIO, TextIO, TYPE_CHECKING {% if model.additional_properties %} @@ -77,17 +78,27 @@ class {{ class_name }}: additional_properties: Dict[str, {{ additional_property_type }}] = _attrs_field(init=False, factory=dict) {% endif %} +{% macro _has_any_read_only_properties() -%} +{%- for property in model.required_properties + model.optional_properties -%} +{%- if property.read_only -%}x{%- endif -%} +{%- endfor -%} +{%- endmacro -%} + {% macro _to_dict(multipart=False) %} +{% if config.skip_sending_read_only_properties and _has_any_read_only_properties() %} +serialization_context = threading.local.openapi_serialization_context or {} +skip_read_only = serialization_context.get("request_body", False) +{% endif %} {% for property in model.required_properties + model.optional_properties %} +{% set prop_var %}prop{{ loop.index }}{% endset %} {% import "property_templates/" + property.template as prop_template %} {% if multipart %} -{{ prop_template.transform_multipart(property, "self." + property.python_name, property.python_name) }} +{{ prop_template.transform_multipart(property, "self." + property.python_name, prop_var) }} {% elif prop_template.transform %} -{{ prop_template.transform(property=property, source="self." + property.python_name, destination=property.python_name) }} +{{ prop_template.transform(property=property, source="self." + property.python_name, destination=prop_var) }} {% else %} -{{ property.python_name }} = self.{{ property.python_name }} +{{ prop_var }} = self.{{ property.python_name }} {% endif %} - {% endfor %} field_dict: Dict[str, Any] = {} @@ -103,21 +114,27 @@ for prop_name, prop in self.additional_properties.items(): field_dict.update(self.additional_properties) {% endif %} {% endif %} -{% if model.required_properties | length > 0 or model.optional_properties | length > 0 %} -field_dict.update({ +{% if model.required_properties or model.optional_properties %} +field_dict = { + **field_dict, {% for property in model.required_properties + model.optional_properties %} - {% if property.required %} - "{{ property.name }}": {{ property.python_name }}, + {% set prop_var_name %}prop{{ loop.index }}{% endset %} + {% set prop_dict_entry %}"{{ property.name }}": {{ prop_var_name }}{% endset %} + {% set prop_skip_conditions=[] -%} + {% if not property.required %} + {{ prop_skip_conditions.append(prop_var_name + " is UNSET") or "" }} + {% endif %} + {% if config.skip_sending_read_only_properties and property.read_only %} + {{ prop_skip_conditions.append("skip_read_only") or "" }} + {% endif %} + {% if prop_skip_conditions %} + **({} if {{ prop_skip_conditions | join(" or ") }} else { {{ prop_dict_entry }} }), + {% else %} + {{ prop_dict_entry }}, {% endif %} {% endfor %} -}) -{% endif %} -{% for property in model.optional_properties %} -{% if not property.required %} -if {{ property.python_name }} is not UNSET: - field_dict["{{ property.name }}"] = {{ property.python_name }} +} {% endif %} -{% endfor %} return field_dict {% endmacro %}