From 31199dcb764b1901918b5e5c9e0dd01283e7c108 Mon Sep 17 00:00:00 2001 From: Dan McNulty Date: Wed, 13 May 2026 11:20:43 -0500 Subject: [PATCH 1/7] chore: add support for non-discriminator, oneOf request parameters - Update `model_oneof.mustache` to generate a type alias rather than a container class when a `oneOf` construct does not use a discriminator. This allows additional types to be used for query parameters without breaking backward compatibility. - Update `partial_api_args.mustache` to generate type annotations for parameters that use `oneOf` construct without a discriminator. - Update `api.mustache` to handle query parameters that use a union type when their schema is a `oneOf` construct without a discriminator. - Update `model_doc.mustache` to document that a `oneOf` construct without a discriminator is a type alias. --- template/api.mustache | 43 ++++++++++++++++++++++++++++++ template/model_doc.mustache | 11 ++++++++ template/model_oneof.mustache | 11 ++++++++ template/partial_api_args.mustache | 2 +- 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/template/api.mustache b/template/api.mustache index e3372c7f..65143417 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -8,6 +8,23 @@ from typing_extensions import Annotated {{#imports}} {{import}} {{/imports}} +{{#operations.operation}} +{{! Workaround for missing imports for parameters that use oneOf }} +{{#allParams}} +{{^hasDiscriminatorWithNonEmptyMapping}} +{{#composedSchemas.oneOf}} +{{#-first}} +from {{packageName}} import {{schema.complexType}} +{{! +Workaround for missing imports for parmaeters that use a oneOf with a nested datetime. +The ruff check autofix will remove this import if it is unused +}} +from datetime import datetime, date +{{/-first}} +{{/composedSchemas.oneOf}} +{{/hasDiscriminatorWithNonEmptyMapping}} +{{/allParams}} +{{/operations.operation}} from {{packageName}}.api_client import ApiClient, RequestSerialized from {{packageName}}.api_response import ApiResponse from {{packageName}}.configuration import Configuration @@ -117,6 +134,7 @@ class {{classname}}: {{#queryParams}} # process the query parameters if {{paramName}} is not None: + {{^schema.composedSchemas.oneOf}} {{#isDateTime}} if isinstance({{paramName}}, datetime): _query_params.append( @@ -146,6 +164,31 @@ class {{classname}}: {{^isDateTime}}{{^isDate}} _query_params.append(('{{baseName}}', {{paramName}}{{#isEnumRef}}.value{{/isEnumRef}})) {{/isDate}}{{/isDateTime}} + {{/schema.composedSchemas.oneOf}} + {{#schema.composedSchemas.oneOf}} + {{#-first}} + if isinstance({{paramName}}, datetime): + _query_params.append( + ( + '{{schema.baseName}}', + {{paramName}}.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + elif isinstance({{paramName}}, date): + _query_params.append( + ( + '{{schema.baseName}}', + {{paramName}}.strftime( + self.api_client.configuration.date_format + ) + ) + ) + else: + _query_params.append(('{{schema.baseName}}', {{paramName}})) + {{/-first}} + {{/schema.composedSchemas.oneOf}} {{/queryParams}} {{#headerParams}} diff --git a/template/model_doc.mustache b/template/model_doc.mustache index 9bc9dd8b..054ad333 100644 --- a/template/model_doc.mustache +++ b/template/model_doc.mustache @@ -11,6 +11,17 @@ Name | Type | Description | Notes {{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{{description}}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} {{/vars}} {{/emptyVars}} +{{#emptyVars}} +{{^model.discriminator}} +{{#composedSchemas.oneOf}} +{{#-first}} +## Type alias + +`Union[{{#oneOf}}{{^-last}}{{.}},{{/-last}}{{#-last}}{{.}}{{/-last}}{{/oneOf}}]` +{{/-first}} +{{/composedSchemas.oneOf}} +{{/model.discriminator}} +{{/emptyVars}} {{/isEnum}} {{#isEnum}} ## Enum diff --git a/template/model_oneof.mustache b/template/model_oneof.mustache index 958812d7..34146487 100644 --- a/template/model_oneof.mustache +++ b/template/model_oneof.mustache @@ -1,3 +1,4 @@ +{{#hasDiscriminatorWithNonEmptyMapping}} from __future__ import annotations import json import pprint @@ -206,3 +207,13 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} # TODO: Rewrite to not use raise_errors {{classname}}.model_rebuild(raise_errors=False) {{/vendorExtensions.x-py-postponed-model-imports.size}} +{{/hasDiscriminatorWithNonEmptyMapping}} +{{^hasDiscriminatorWithNonEmptyMapping}} +from typing import Union +{{#composedSchemas.oneOf}} +{{#isDateTime}} +from datetime import datetime +{{/isDateTime}} +{{/composedSchemas.oneOf}} +{{classname}} = Union[{{#oneOf}}{{^-last}}{{.}},{{/-last}}{{#-last}}{{.}}{{/-last}}{{/oneOf}}] +{{/hasDiscriminatorWithNonEmptyMapping}} \ No newline at end of file diff --git a/template/partial_api_args.mustache b/template/partial_api_args.mustache index 21eea6ed..3d145a39 100644 --- a/template/partial_api_args.mustache +++ b/template/partial_api_args.mustache @@ -1,7 +1,7 @@ ( self, {{#allParams}} - {{paramName}}: {{{vendorExtensions.x-py-typing}}}{{^required}} = None{{/required}}, + {{paramName}}: {{^schema.composedSchemas}}{{{vendorExtensions.x-py-typing}}}{{/schema.composedSchemas}}{{#schema.composedSchemas}}Annotated[{{^required}}Optional[{{/required}}{{schema.complexType}}{{^required}}]{{/required}},Field(description="{{{description}}}",)]{{/schema.composedSchemas}}{{^required}} = None{{/required}}, {{/allParams}} _request_timeout: Union[ None, From c98cf803bf4c546e5717138b6be77a1a71932c60 Mon Sep 17 00:00:00 2001 From: Dan McNulty Date: Wed, 13 May 2026 15:00:06 -0500 Subject: [PATCH 2/7] chore: use more specific import for models to avoid circular import --- template/api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/api.mustache b/template/api.mustache index 65143417..789a647b 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -14,7 +14,7 @@ from typing_extensions import Annotated {{^hasDiscriminatorWithNonEmptyMapping}} {{#composedSchemas.oneOf}} {{#-first}} -from {{packageName}} import {{schema.complexType}} +from {{packageName}}.models import {{schema.complexType}} {{! Workaround for missing imports for parmaeters that use a oneOf with a nested datetime. The ruff check autofix will remove this import if it is unused From 2db0d69b0adda3ae8957722607ff371c8c0af4fd Mon Sep 17 00:00:00 2001 From: Dan McNulty Date: Wed, 13 May 2026 15:13:30 -0500 Subject: [PATCH 3/7] chore: fix import for oneOf models --- template/api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/api.mustache b/template/api.mustache index 789a647b..85ddd7f9 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -14,7 +14,7 @@ from typing_extensions import Annotated {{^hasDiscriminatorWithNonEmptyMapping}} {{#composedSchemas.oneOf}} {{#-first}} -from {{packageName}}.models import {{schema.complexType}} +from {{packageName}}.models.{{#lambda.snakecase}}{{schema.complexType}}{{/lambda.snakecase}} import {{schema.complexType}} {{! Workaround for missing imports for parmaeters that use a oneOf with a nested datetime. The ruff check autofix will remove this import if it is unused From b8fe4d82a320bdc826c7e94955cdc4407b1918df Mon Sep 17 00:00:00 2001 From: Dan McNulty <212590662+mcnulty-fp@users.noreply.github.com> Date: Wed, 13 May 2026 15:57:46 -0500 Subject: [PATCH 4/7] chore: fix typo in comment Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- template/api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/api.mustache b/template/api.mustache index 85ddd7f9..2ada0b37 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -16,7 +16,7 @@ from typing_extensions import Annotated {{#-first}} from {{packageName}}.models.{{#lambda.snakecase}}{{schema.complexType}}{{/lambda.snakecase}} import {{schema.complexType}} {{! -Workaround for missing imports for parmaeters that use a oneOf with a nested datetime. +Workaround for missing imports for parameters that use a oneOf with a nested datetime. The ruff check autofix will remove this import if it is unused }} from datetime import datetime, date From 12a50a86583ff18b0baaa2bd4639164c569dc185 Mon Sep 17 00:00:00 2001 From: Dan McNulty Date: Thu, 14 May 2026 08:22:07 -0500 Subject: [PATCH 5/7] chore: remove unnecessary comment --- template/api.mustache | 4 ---- 1 file changed, 4 deletions(-) diff --git a/template/api.mustache b/template/api.mustache index 2ada0b37..6a7a5f7b 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -15,10 +15,6 @@ from typing_extensions import Annotated {{#composedSchemas.oneOf}} {{#-first}} from {{packageName}}.models.{{#lambda.snakecase}}{{schema.complexType}}{{/lambda.snakecase}} import {{schema.complexType}} -{{! -Workaround for missing imports for parameters that use a oneOf with a nested datetime. -The ruff check autofix will remove this import if it is unused -}} from datetime import datetime, date {{/-first}} {{/composedSchemas.oneOf}} From 012dba3ad73a7f81ba16e47ac8520c9f9d2f86f0 Mon Sep 17 00:00:00 2001 From: Dan McNulty Date: Thu, 14 May 2026 08:49:51 -0500 Subject: [PATCH 6/7] chore: update date-time query parameter formatting for oneOf parameters --- template/api.mustache | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/template/api.mustache b/template/api.mustache index 6a7a5f7b..6594a54c 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -15,7 +15,7 @@ from typing_extensions import Annotated {{#composedSchemas.oneOf}} {{#-first}} from {{packageName}}.models.{{#lambda.snakecase}}{{schema.complexType}}{{/lambda.snakecase}} import {{schema.complexType}} -from datetime import datetime, date +from datetime import datetime, date, timezone {{/-first}} {{/composedSchemas.oneOf}} {{/hasDiscriminatorWithNonEmptyMapping}} @@ -167,18 +167,14 @@ class {{classname}}: _query_params.append( ( '{{schema.baseName}}', - {{paramName}}.strftime( - self.api_client.configuration.datetime_format - ) + {{paramName}}.replace(tzinfo={{paramName}}.tzinfo or timezone.utc).isoformat(timespec='microseconds') ) ) elif isinstance({{paramName}}, date): _query_params.append( ( '{{schema.baseName}}', - {{paramName}}.strftime( - self.api_client.configuration.date_format - ) + {{paramName}}.isoformat() ) ) else: From cf5c361d39712b9bb24186a9a4e190d5f5e5fb7b Mon Sep 17 00:00:00 2001 From: Dan McNulty Date: Thu, 14 May 2026 10:44:00 -0500 Subject: [PATCH 7/7] chore: use AwareDatetime for oneOf datetime types - Update `model_oneof` template to use AwareDatetime to require oneOf parameters to have a timezone. - Update `api` template to assume a timezone is set on the datetime query parameter. --- template/api.mustache | 2 +- template/model_oneof.mustache | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/template/api.mustache b/template/api.mustache index 6594a54c..50710e06 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -167,7 +167,7 @@ class {{classname}}: _query_params.append( ( '{{schema.baseName}}', - {{paramName}}.replace(tzinfo={{paramName}}.tzinfo or timezone.utc).isoformat(timespec='microseconds') + {{paramName}}.isoformat(timespec='microseconds') ) ) elif isinstance({{paramName}}, date): diff --git a/template/model_oneof.mustache b/template/model_oneof.mustache index 34146487..e04708a0 100644 --- a/template/model_oneof.mustache +++ b/template/model_oneof.mustache @@ -212,8 +212,8 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}} from typing import Union {{#composedSchemas.oneOf}} {{#isDateTime}} -from datetime import datetime +from pydantic import AwareDatetime {{/isDateTime}} {{/composedSchemas.oneOf}} -{{classname}} = Union[{{#oneOf}}{{^-last}}{{.}},{{/-last}}{{#-last}}{{.}}{{/-last}}{{/oneOf}}] +{{classname}} = Union[{{#composedSchemas.oneOf}}{{#isDateTime}}AwareDatetime{{/isDateTime}}{{^isDateTime}}{{dataType}}{{/isDateTime}}{{^-last}},{{/-last}}{{/composedSchemas.oneOf}}] {{/hasDiscriminatorWithNonEmptyMapping}} \ No newline at end of file