diff --git a/osidb_bindings/templates_0.22.0/client.py.jinja b/osidb_bindings/templates_0.22.0/client.py.jinja new file mode 100644 index 0000000..332fe41 --- /dev/null +++ b/osidb_bindings/templates_0.22.0/client.py.jinja @@ -0,0 +1,170 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/tree/v0.22.0/openapi_python_client/templates/client.py.jinja +#} +import ssl +from typing import Any, Union, Optional + +from attrs import define, field, evolve +import httpx + + +@define +class Client: + """A class for keeping track of data related to the API + +{% macro httpx_args_docstring() %} + 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. +{% endmacro %} +{{ httpx_args_docstring() }} + + 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. + """ +{% macro attributes() %} + 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) +{% endmacro %}{{ attributes() }} +{% macro builders(self) %} + def with_headers(self, headers: dict[str, str]) -> "{{ self }}": + """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]) -> "{{ self }}": + """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) -> "{{ self }}": + """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) +{% endmacro %}{{ builders("Client") }} +{% macro httpx_stuff(name, custom_constructor=None) %} + def set_httpx_client(self, client: httpx.Client) -> "{{ name }}": + """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: + {% if custom_constructor %} + {{ custom_constructor | indent(12) }} + {% endif %} + 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) -> "{{ name }}": + """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) -> "{{ name }}": + """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: + {% if custom_constructor %} + {{ custom_constructor | indent(12) }} + {% endif %} + 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) -> "{{ name }}": + """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) +{% endmacro %}{{ httpx_stuff("Client") }} + +@define +class AuthenticatedClient: + """A Client which has been authenticated for use on secured endpoints + +{{ httpx_args_docstring() }} + + 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 + """ + +{{ attributes() }} + token: str + prefix: str = "Bearer" + auth_header_name: str = "Authorization" + +{{ builders("AuthenticatedClient") }} +{{ httpx_stuff("AuthenticatedClient", "self._headers[self.auth_header_name] = f\"{self.prefix} {self.token}\" if self.prefix else self.token") }} diff --git a/osidb_bindings/templates_0.22.0/endpoint_init.py.jinja b/osidb_bindings/templates_0.22.0/endpoint_init.py.jinja new file mode 100644 index 0000000..fc98d76 --- /dev/null +++ b/osidb_bindings/templates_0.22.0/endpoint_init.py.jinja @@ -0,0 +1,4 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/tree/v0.22.0/openapi_python_client/templates/endpoint_init.py.jinja +#} diff --git a/osidb_bindings/templates_0.22.0/endpoint_macros.py.jinja b/osidb_bindings/templates_0.22.0/endpoint_macros.py.jinja new file mode 100644 index 0000000..add3e6c --- /dev/null +++ b/osidb_bindings/templates_0.22.0/endpoint_macros.py.jinja @@ -0,0 +1,190 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/endpoint_macros.py.jinja +#} +{% from "property_templates/helpers.jinja" import guarded_statement %} +{% from "helpers.jinja" import safe_docstring %} + +{% macro header_params(endpoint) %} +{% if endpoint.header_parameters or endpoint.bodies | length > 0 %} +headers: dict[str, Any] = {} +{% if endpoint.header_parameters %} + {% for parameter in endpoint.header_parameters %} + {% import "property_templates/" + parameter.template as param_template %} + {% if param_template.transform_header %} + {% set expression = param_template.transform_header(parameter.python_name) %} + {% else %} + {% set expression = parameter.python_name %} + {% endif %} + {% set statement = 'headers["' + parameter.name + '"]' + " = " + expression %} +{{ guarded_statement(parameter, parameter.python_name, statement) }} + {% endfor %} +{% endif %} +{% endif %} +{% endmacro %} + +{% macro cookie_params(endpoint) %} +{% if endpoint.cookie_parameters %} +cookies = {} + {% for parameter in endpoint.cookie_parameters %} + {% if parameter.required %} +cookies["{{ parameter.name}}"] = {{ parameter.python_name }} + {% else %} +if {{ parameter.python_name }} is not UNSET: + cookies["{{ parameter.name}}"] = {{ parameter.python_name }} + {% endif %} + + {% endfor %} +{% endif %} +{% endmacro %} + + +{% macro query_params(endpoint) %} +{% if endpoint.query_parameters %} +params: dict[str, Any] = {} + +{% for property in endpoint.query_parameters %} + {% set destination = property.python_name %} + {% import "property_templates/" + property.template as prop_template %} + {% if prop_template.transform %} + {% set destination = "json_" + property.python_name %} +{{ prop_template.transform(property, property.python_name, destination) }} + {% endif %} + {%- if not property.json_is_dict %} +params["{{ property.name }}"] = {{ destination }} + {% else %} +{{ guarded_statement(property, destination, "params.update(" + destination + ")") }} + {% endif %} + +{% endfor %} + +params = {k: v for k, v in params.items() if v is not UNSET and v is not None} +{% endif %} +{% endmacro %} + +{% macro body_to_kwarg(body, destination) %} +{% if body.body_type == "data" %} +{{ destination }} = body.to_dict() +{% elif body.body_type == "files"%} +{{ multipart_body(body, destination) }} +{% elif body.body_type == "json" %} +{{ json_body(body, destination) }} +{% elif body.body_type == "content" %} +{{ destination }} = body.payload +{% endif %} +{% endmacro %} + +{% macro json_body(body, destination) %} +{% set property = body.prop %} +{% import "property_templates/" + property.template as prop_template %} +{% if prop_template.transform %} +{{ prop_template.transform(property, property.python_name, destination) }} +{% else %} +{{ destination }} = {{ property.python_name }} +{% endif %} +{% endmacro %} + +{% macro multipart_body(body, destination) %} +{% set property = body.prop %} +{% import "property_templates/" + property.template as prop_template %} +{% if prop_template.transform_multipart_body %} +{{ prop_template.transform_multipart_body(property, property.python_name, destination) }} +{% endif %} +{% endmacro %} + +{# The all the kwargs passed into an endpoint (and variants thereof)) #} +{% macro arguments(endpoint, include_client=True) %} +{# path parameters #} +{% for parameter in endpoint.path_parameters %} +{{ parameter.to_string() }}, +{% endfor %} +{% if include_client or ((endpoint.list_all_parameters() | length) > (endpoint.path_parameters | length)) %} +*, +{% endif %} +{# Proper client based on whether or not the endpoint requires authentication #} +{% if include_client %} +{% if endpoint.requires_security %} +client: AuthenticatedClient, +{% else %} +client: Union[AuthenticatedClient, Client], +{% endif %} +{% endif %} +{# Any allowed bodies #} +{% if endpoint.bodies | length == 1 %} +body: {{ endpoint.bodies[0].prop.get_type_string() }}, +{% elif endpoint.bodies | length > 1 %} +body: Union[ + {% for body in endpoint.bodies %} + {{ body.prop.get_type_string() }}, + {% endfor %} +], +{% endif %} +{# query parameters #} +{% for parameter in endpoint.query_parameters %} +{{ parameter.to_string() }}, +{% endfor %} +{% for parameter in endpoint.header_parameters %} +{{ parameter.to_string() }}, +{% endfor %} +{# cookie parameters #} +{% for parameter in endpoint.cookie_parameters %} +{{ parameter.to_string() }}, +{% endfor %} +{% endmacro %} + +{# Just lists all kwargs to endpoints as name=name for passing to other functions #} +{% macro kwargs(endpoint, include_client=True) %} +{% for parameter in endpoint.path_parameters %} +{{ parameter.python_name }}={{ parameter.python_name }}, +{% endfor %} +{% if include_client %} +client=client, +{% endif %} +{% if endpoint.bodies | length > 0 %} +body=body, +{% endif %} +{% for parameter in endpoint.query_parameters %} +{{ parameter.python_name }}={{ parameter.python_name }}, +{% endfor %} +{% for parameter in endpoint.header_parameters %} +{{ parameter.python_name }}={{ parameter.python_name }}, +{% endfor %} +{% for parameter in endpoint.cookie_parameters %} +{{ parameter.python_name }}={{ parameter.python_name }}, +{% endfor %} +{% endmacro %} + +{% macro docstring_content(endpoint, return_string, is_detailed) %} +{% if endpoint.summary %}{{ endpoint.summary | wordwrap(100)}} + +{% endif -%} +{%- if endpoint.description %} {{ endpoint.description | wordwrap(100) }} + +{% endif %} +{% if not endpoint.summary and not endpoint.description %} +{# Leave extra space so that Args or Returns isn't at the top #} + +{% endif %} +{% set all_parameters = endpoint.list_all_parameters() %} +{% if all_parameters %} +Args: + {% for parameter in all_parameters %} + {{ parameter.to_docstring() | wordwrap(90) | indent(8) }} + {% endfor %} + +{% endif %} +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: +{% if is_detailed %} + Response[{{ return_string }}] +{% else %} + {{ return_string }} +{% endif %} +{% endmacro %} + +{% macro docstring(endpoint, return_string, is_detailed) %} +{{ safe_docstring(docstring_content(endpoint, return_string, is_detailed)) }} +{% endmacro %} diff --git a/osidb_bindings/templates_0.22.0/endpoint_module.py.jinja b/osidb_bindings/templates_0.22.0/endpoint_module.py.jinja new file mode 100644 index 0000000..ce120fb --- /dev/null +++ b/osidb_bindings/templates_0.22.0/endpoint_module.py.jinja @@ -0,0 +1,156 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/endpoint_module.py.jinja +#} +from http import HTTPStatus +from typing import Any, Optional, Union, cast + +import httpx + +from ...client import AuthenticatedClient, Client +from ...types import Response, UNSET +from ... import errors + +{% for relative in endpoint.relative_imports | sort %} +{{ relative }} +{% endfor %} + +{% from "endpoint_macros.py.jinja" import header_params, cookie_params, query_params, + arguments, client, kwargs, parse_response, docstring, body_to_kwarg %} + +{% set return_string = endpoint.response_type() %} +{% set parsed_responses = (endpoint.responses | length > 0) and return_string != "Any" %} + +def _get_kwargs( + {{ arguments(endpoint, include_client=False) | indent(4) }} +) -> dict[str, Any]: + {{ header_params(endpoint) | indent(4) }} + + {{ cookie_params(endpoint) | indent(4) }} + + {{ query_params(endpoint) | indent(4) }} + + _kwargs: dict[str, Any] = { + "method": "{{ endpoint.method }}", + {% if endpoint.path_parameters %} + "url": "{{ endpoint.path }}".format( + {%- for parameter in endpoint.path_parameters -%} + {{parameter.python_name}}={{parameter.python_name}}, + {%- endfor -%} + ), + {% else %} + "url": "{{ endpoint.path }}", + {% endif %} + {% if endpoint.query_parameters %} + "params": params, + {% endif %} + {% if endpoint.cookie_parameters %} + "cookies": cookies, + {% endif %} + } + +{% if endpoint.bodies | length > 1 %} +{% 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 %} +{% elif endpoint.bodies | length == 1 %} +{% set body = endpoint.bodies[0] %} + {{ body_to_kwarg(body, "_body") | indent(4) }} + _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 }}" + {% endif %} +{% endif %} + +{% if endpoint.header_parameters or endpoint.bodies | length > 0 %} + _kwargs["headers"] = headers +{% endif %} + return _kwargs + + +def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[{{ return_string }}]: + {% for response in endpoint.responses %} + if response.status_code == {{ response.status_code.value }}: + {% if parsed_responses %}{% import "property_templates/" + response.prop.template as prop_template %} + {% if prop_template.construct %} + {{ prop_template.construct(response.prop, response.source.attribute) | indent(8) }} + {% elif response.source.return_type == response.prop.get_type_string() %} + {{ response.prop.python_name }} = {{ response.source.attribute }} + {% else %} + {{ response.prop.python_name }} = cast({{ response.prop.get_type_string() }}, {{ response.source.attribute }}) + {% endif %} + return {{ response.prop.python_name }} + {% else %} + return None + {% endif %} + {% endfor %} + 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[{{ return_string }}]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + {{ arguments(endpoint) | indent(4) }} +) -> Response[{{ return_string }}]: + {{ docstring(endpoint, return_string, is_detailed=true) | indent(4) }} + + kwargs = _get_kwargs( + {{ kwargs(endpoint, include_client=False) }} + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + +{% if parsed_responses %} +def sync( + {{ arguments(endpoint) | indent(4) }} +) -> Optional[{{ return_string }}]: + {{ docstring(endpoint, return_string, is_detailed=false) | indent(4) }} + + return sync_detailed( + {{ kwargs(endpoint) }} + ).parsed +{% endif %} + +async def asyncio_detailed( + {{ arguments(endpoint) | indent(4) }} +) -> Response[{{ return_string }}]: + {{ docstring(endpoint, return_string, is_detailed=true) | indent(4) }} + + kwargs = _get_kwargs( + {{ kwargs(endpoint, include_client=False) }} + ) + + response = await client.get_async_httpx_client().request( + **kwargs + ) + + return _build_response(client=client, response=response) + +{% if parsed_responses %} +async def asyncio( + {{ arguments(endpoint) | indent(4) }} +) -> Optional[{{ return_string }}]: + {{ docstring(endpoint, return_string, is_detailed=false) | indent(4) }} + + return (await asyncio_detailed( + {{ kwargs(endpoint) }} + )).parsed +{% endif %} diff --git a/osidb_bindings/templates_0.22.0/model.py.jinja b/osidb_bindings/templates_0.22.0/model.py.jinja new file mode 100644 index 0000000..9bf2662 --- /dev/null +++ b/osidb_bindings/templates_0.22.0/model.py.jinja @@ -0,0 +1,204 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/model.py.jinja +#} +from typing import Any, TypeVar, Optional, BinaryIO, TextIO, TYPE_CHECKING + +from attrs import define as _attrs_define +from attrs import field as _attrs_field +{% if model.is_multipart_body %} +import json +{% endif %} + +from ..types import UNSET, Unset + +{% for relative in model.relative_imports | sort %} +{{ relative }} +{% endfor %} + +{% for lazy_import in model.lazy_imports %} +{% if loop.first %} +if TYPE_CHECKING: +{% endif %} + {{ lazy_import }} +{% endfor %} + + +{% if model.additional_properties %} +{% set additional_property_type = 'Any' if model.additional_properties == True else model.additional_properties.get_type_string(quoted=not model.additional_properties.is_base_type) %} +{% endif %} + +{% set class_name = model.class_info.name %} +{% set module_name = model.class_info.module_name %} + +{% from "helpers.jinja" import safe_docstring %} + +T = TypeVar("T", bound="{{ class_name }}") + +{% macro class_docstring_content(model) %} + {% if model.title %}{{ model.title | wordwrap(116) }} + + {% endif -%} + {%- if model.description %}{{ model.description | wordwrap(116) }} + + {% endif %} + {% if not model.title and not model.description %} + {# Leave extra space so that a section doesn't start on the first line #} + + {% endif %} + {% if model.example %} + Example: + {{ model.example | string | wordwrap(112) | indent(12) }} + + {% endif %} + {% if model.required_properties or model.optional_properties %} + Attributes: + {% for property in model.required_properties + model.optional_properties %} + {{ property.to_docstring() | wordwrap(112) | indent(12) }} + {% endfor %}{% endif %} +{% endmacro %} + +@_attrs_define +class {{ class_name }}: + {{ safe_docstring(class_docstring_content(model)) | indent(4) }} + + {% for property in model.required_properties + model.optional_properties %} + {% if property.default is none and property.required %} + {{ property.to_string() }} + {% endif %} + {% endfor %} + {% for property in model.required_properties + model.optional_properties %} + {% if property.default is not none or not property.required %} + {{ property.to_string() }} + {% endif %} + {% endfor %} + {% if model.additional_properties %} + additional_properties: dict[str, {{ additional_property_type }}] = _attrs_field(init=False, factory=dict) + {% endif %} + +{% macro _to_dict(multipart=False) %} +{% for property in model.required_properties + model.optional_properties %} +{% import "property_templates/" + property.template as prop_template %} +{% if multipart %} +{{ prop_template.transform_multipart(property, "self." + property.python_name, property.python_name) }} +{% elif prop_template.transform %} +{{ prop_template.transform(property=property, source="self." + property.python_name, destination=property.python_name) }} +{% else %} +{{ property.python_name }} = self.{{ property.python_name }} +{% endif %} + +{% endfor %} + +field_dict: dict[str, Any] = {} +{% if model.additional_properties %} +{% import "property_templates/" + model.additional_properties.template as prop_template %} +{% if multipart %} +for prop_name, prop in self.additional_properties.items(): + {{ prop_template.transform_multipart(model.additional_properties, "prop", "field_dict[prop_name]") | indent(4) }} +{% elif prop_template.transform %} +for prop_name, prop in self.additional_properties.items(): + {{ prop_template.transform(model.additional_properties, "prop", "field_dict[prop_name]", declare_type=false) | indent(4) }} +{% else %} +field_dict.update(self.additional_properties) +{% endif %} +{% endif %} +{% if model.required_properties | length > 0 or model.optional_properties | length > 0 %} +field_dict.update({ + {% for property in model.required_properties + model.optional_properties %} + {% if property.required %} + "{{ property.name }}": {{ property.python_name }}, + {% 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 %} + + def to_dict(self) -> dict[str, Any]: + {% for lazy_import in model.lazy_imports %} + {{ lazy_import }} + {% endfor %} + {{ _to_dict() | indent(8) }} + +{% if model.is_multipart_body %} + def to_multipart(self) -> dict[str, Any]: + {{ _to_dict(multipart=True) | indent(8) }} +{% endif %} + + @classmethod + def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T: + {% for lazy_import in model.lazy_imports %} + {{ lazy_import }} + {% endfor %} +{% if (model.required_properties or model.optional_properties or model.additional_properties) %} + d = src_dict.copy() +{% for property in model.required_properties + model.optional_properties %} + {% if property.required %} + {% set property_source = 'd.pop("' + property.name + '")' %} + {% else %} + {% set property_source = 'd.pop("' + property.name + '", UNSET)' %} + {% endif %} + {% import "property_templates/" + property.template as prop_template %} + {% if prop_template.construct %} + {{ prop_template.construct(property, property_source) | indent(8) }} + {% else %} + {{ property.python_name }} = {{ property_source }} + {% endif %} + +{% endfor %} +{% endif %} + {{ module_name }} = cls( +{% for property in model.required_properties + model.optional_properties %} + {{ property.python_name }}={{ property.python_name }}, +{% endfor %} + ) + +{% if model.additional_properties %} + {% if model.additional_properties.template %}{# Can be a bool instead of an object #} + {% import "property_templates/" + model.additional_properties.template as prop_template %} + +{% if model.additional_properties.lazy_imports %} + {% for lazy_import in model.additional_properties.lazy_imports %} + {{ lazy_import }} + {% endfor %} +{% endif %} + {% else %} + {% set prop_template = None %} + {% endif %} + {% if prop_template and prop_template.construct %} + additional_properties = {} + for prop_name, prop_dict in d.items(): + {{ prop_template.construct(model.additional_properties, "prop_dict") | indent(12) }} + additional_properties[prop_name] = {{ model.additional_properties.python_name }} + + {{ module_name }}.additional_properties = additional_properties + {% else %} + {{ module_name }}.additional_properties = d + {% endif %} +{% endif %} + return {{ module_name }} + + {% if model.additional_properties %} + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> {{ additional_property_type }}: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: {{ additional_property_type }}) -> 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 + {% endif %} diff --git a/osidb_bindings/templates_0.22.0/property_templates/date_property.py.jinja b/osidb_bindings/templates_0.22.0/property_templates/date_property.py.jinja new file mode 100644 index 0000000..d6a0241 --- /dev/null +++ b/osidb_bindings/templates_0.22.0/property_templates/date_property.py.jinja @@ -0,0 +1,43 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/property_templates/date_property.py.jinja +#} +{% macro construct_function(property, source) %} +isoparse({{ source }}).date() +{% endmacro %} + +{% from "property_templates/property_macros.py.jinja" import construct_template %} + +{% macro construct(property, source) %} +{{ construct_template(construct_function, property, source) }} +{% endmacro %} + +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, str){% endmacro %} + +{% macro transform(property, source, destination, declare_type=True) %} +{% set transformed = source + ".isoformat()" %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{% if declare_type %} +{% set type_annotation = property.get_type_string(json=True) %} +{{ destination }}: {{ type_annotation }} = UNSET +{% else %} +{{ destination }} = UNSET +{% endif %} +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{%- endif %} +{% endmacro %} + +{% macro transform_multipart(property, source, destination) %} +{% set transformed = source + ".isoformat().encode()" %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{% set type_annotation = property.get_type_string(json=True) | replace("str", "bytes") %} +{{ destination }}: {{ type_annotation }} = UNSET +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{%- endif %} +{% endmacro %} diff --git a/osidb_bindings/templates_0.22.0/property_templates/datetime_property.py.jinja b/osidb_bindings/templates_0.22.0/property_templates/datetime_property.py.jinja new file mode 100644 index 0000000..895e341 --- /dev/null +++ b/osidb_bindings/templates_0.22.0/property_templates/datetime_property.py.jinja @@ -0,0 +1,43 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/property_templates/datetime_property.py.jinja +#} +{% macro construct_function(property, source) %} +isoparse({{ source }}) +{% endmacro %} + +{% from "property_templates/property_macros.py.jinja" import construct_template %} + +{% macro construct(property, source) %} +{{ construct_template(construct_function, property, source) }} +{% endmacro %} + +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, str){% endmacro %} + +{% macro transform(property, source, destination, declare_type=True) %} +{% set transformed = source + ".isoformat()" %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{% if declare_type %} +{% set type_annotation = property.get_type_string(json=True) %} +{{ destination }}: {{ type_annotation }} = UNSET +{% else %} +{{ destination }} = UNSET +{% endif %} +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{%- endif %} +{% endmacro %} + +{% macro transform_multipart(property, source, destination) %} +{% set transformed = source + ".isoformat().encode()" %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{% set type_annotation = property.get_type_string(json=True) | replace("str", "bytes") %} +{{ destination }}: {{ type_annotation }} = UNSET +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{%- endif %} +{% endmacro %} diff --git a/osidb_bindings/templates_0.22.0/property_templates/enum_property.py.jinja b/osidb_bindings/templates_0.22.0/property_templates/enum_property.py.jinja new file mode 100644 index 0000000..dd1ae64 --- /dev/null +++ b/osidb_bindings/templates_0.22.0/property_templates/enum_property.py.jinja @@ -0,0 +1,43 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/property_templates/enum_property.py.jinja +#} +{% macro construct_function(property, source) %} +{{ property.class_info.name }}({{ source }}) +{% endmacro %} + +{% from "property_templates/property_macros.py.jinja" import construct_template %} + +{% macro construct(property, source) %} +{{ construct_template(construct_function, property, source) }} +{% endmacro %} + +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, {{ property.value_type.__name__ }}){% endmacro %} + +{% macro transform(property, source, destination, declare_type=True, multipart=False) %} +{% set transformed = source + ".value" %} +{% set type_string = property.get_type_string(json=True) %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{% endif %} +{% endmacro %} + +{% macro transform_multipart(property, source, destination) %} +{% set transformed = "(None, str(" + source + ".value" + ").encode(), \"text/plain\")" %} +{% set type_string = "Union[Unset, tuple[None, bytes, str]]" %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{{ destination }}: {{ type_string }} = UNSET +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{% endif %} +{% endmacro %} + +{% macro transform_header(source) %} +str({{ source }}) +{% endmacro %} diff --git a/osidb_bindings/templates_0.22.0/property_templates/list_property.py.jinja b/osidb_bindings/templates_0.22.0/property_templates/list_property.py.jinja new file mode 100644 index 0000000..4e31e3e --- /dev/null +++ b/osidb_bindings/templates_0.22.0/property_templates/list_property.py.jinja @@ -0,0 +1,81 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/property_templates/list_property.py.jinja +#} +{% macro construct(property, source) %} +{% set inner_property = property.inner_property %} +{% import "property_templates/" + inner_property.template as inner_template %} +{% if inner_template.construct %} +{% set inner_source = inner_property.python_name + "_data" %} +{{ property.python_name }} = [] +_{{ property.python_name }} = {{ source }} +{% if property.required %} +for {{ inner_source }} in (_{{ property.python_name }}): +{% else %} +for {{ inner_source }} in (_{{ property.python_name }} or []): +{% endif %} + {{ inner_template.construct(inner_property, inner_source) | indent(4) }} + {{ property.python_name }}.append({{ inner_property.python_name }}) +{% else %} +{{ property.python_name }} = cast({{ property.get_type_string(no_optional=True) }}, {{ source }}) +{% endif %} +{% endmacro %} + +{% macro _transform(property, source, destination, multipart, transform_method) %} +{% set inner_property = property.inner_property %} +{% if multipart %} +{% set multipart_destination = destination %} +{% set destination = "_temp_" + destination %} +{% endif %} +{% import "property_templates/" + inner_property.template as inner_template %} +{% if inner_template.transform %} +{% set inner_source = inner_property.python_name + "_data" %} +{{ destination }} = [] +for {{ inner_source }} in {{ source }}: + {{ inner_template.transform(inner_property, inner_source, inner_property.python_name, transform_method) | indent(4) }} + {{ destination }}.append({{ inner_property.python_name }}) +{% else %} +{{ destination }} = {{ source }} +{% endif %} +{% if multipart %} +{{ multipart_destination }} = (None, json.dumps({{ destination }}).encode(), 'application/json') +{% endif %} +{% endmacro %} + +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, list){% endmacro %} + +{% macro transform(property, source, destination, declare_type=True) %} +{% set inner_property = property.inner_property %} +{% set type_string = property.get_type_string(json=True) %} +{% if property.required %} +{{ _transform(property, source, destination, False, "to_dict") }} +{% else %} +{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET +if not isinstance({{ source }}, Unset): + {{ _transform(property, source, destination, False, "to_dict") | indent(4)}} +{% endif %} +{% endmacro %} + +{% macro transform_multipart(property, source, destination) %} +{% set inner_property = property.inner_property %} +{% set type_string = "Union[Unset, tuple[None, bytes, str]]" %} +{% if property.required %} +{{ _transform(property, source, destination, True, "to_dict") }} +{% else %} +{{ destination }}: {{ type_string }} = UNSET +if not isinstance({{ source }}, Unset): + {{ _transform(property, source, destination, True, "to_dict") | indent(4)}} +{% endif %} +{% endmacro %} + +{% macro transform_multipart_body(property, source, destination) %} +{% set inner_property = property.inner_property %} +{% set type_string = property.get_type_string(json=True) %} +{% if property.required %} +{{ _transform(property, source, destination, False, "to_multipart") }} +{% else %} +{{ destination }}: {{ type_string }} = UNSET +if not isinstance({{ source }}, Unset): + {{ _transform(property, source, destination, False, "to_multipart") | indent(4)}} +{% endif %} +{% endmacro %} diff --git a/osidb_bindings/templates_0.22.0/property_templates/model_property.py.jinja b/osidb_bindings/templates_0.22.0/property_templates/model_property.py.jinja new file mode 100644 index 0000000..9f0919d --- /dev/null +++ b/osidb_bindings/templates_0.22.0/property_templates/model_property.py.jinja @@ -0,0 +1,51 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/property_templates/model_property.py.jinja +#} +{% macro construct_function(property, source) %} +{{ property.class_info.name }}.from_dict({{ source }}) +{% endmacro %} + +{% from "property_templates/property_macros.py.jinja" import construct_template %} + +{% macro construct(property, source) %} +{{ construct_template(construct_function, property, source) }} +{% endmacro %} + +{% macro check_type_for_construct(property, source) %}isinstance({{ source }}, dict){% endmacro %} + +{% macro transform(property, source, destination, declare_type=True) %} +{% set transformed = source + ".to_dict()" %} +{% set type_string = property.get_type_string(json=True) %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{%- endif %} +{% endmacro %} + +{% macro transform_multipart_body(property, source, destination) %} +{% set transformed = source + ".to_multipart()" %} +{% set type_string = property.get_type_string(multipart=True) %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{{ destination }}: {{ type_string }} = UNSET +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{%- endif %} +{% endmacro %} + +{% macro transform_multipart(property, source, destination) %} +{% set transformed = "(None, json.dumps(" + source + ".to_dict()" + ").encode(), 'application/json')" %} +{% set type_string = property.get_type_string(multipart=True) %} +{% if property.required %} +{{ destination }} = {{ transformed }} +{%- else %} +{{ destination }}: {{ type_string }} = UNSET +if not isinstance({{ source }}, Unset): + {{ destination }} = {{ transformed }} +{%- endif %} +{% endmacro %} diff --git a/osidb_bindings/templates_0.22.0/property_templates/property_macros.py.jinja b/osidb_bindings/templates_0.22.0/property_templates/property_macros.py.jinja new file mode 100644 index 0000000..6359ddc --- /dev/null +++ b/osidb_bindings/templates_0.22.0/property_templates/property_macros.py.jinja @@ -0,0 +1,18 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/property_templates/property_macros.py.jinja +#} +{% macro construct_template(construct_function, property, source) %} +{% if property.required %} +{{ property.python_name }} = {{ construct_function(property, source) }} +{% else %}{# Must be non-required #} +_{{ property.python_name }} = {{ source }} +{{ property.python_name }}: {{ property.get_type_string() }} + {% if not property.required %} +if isinstance(_{{ property.python_name }}, Unset): + {{ property.python_name }} = UNSET + {% endif %} +else: + {{ property.python_name }} = {{ construct_function(property, "_" + property.python_name) }} +{% endif %} +{% endmacro %} diff --git a/osidb_bindings/templates_0.22.0/types.py.jinja b/osidb_bindings/templates_0.22.0/types.py.jinja new file mode 100644 index 0000000..d084a4c --- /dev/null +++ b/osidb_bindings/templates_0.22.0/types.py.jinja @@ -0,0 +1,51 @@ +{# + This is a custom template derived from: + https://github.com/openapi-generators/openapi-python-client/blob/v0.22.0/openapi_python_client/templates/types.py.jinja +#} +""" Contains some shared types for properties """ + +from collections.abc import MutableMapping +from http import HTTPStatus +from typing import BinaryIO, Generic, Optional, TypeVar, Literal + +from attrs import define + + +class Unset: + def __bool__(self) -> Literal[False]: + return False + + +UNSET: Unset = Unset() + +{# Used as `FileProperty._json_type_string` #} +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__ = ["UNSET", "File", "FileJsonType", "Response", "Unset"]