Skip to content

Make RFC compliance default - #25098

Open
anystubbs wants to merge 2 commits into
OpenAPITools:masterfrom
anystubbs:fix-20961-python-datetime-rfc3339
Open

anystubbs wants to merge 2 commits into
OpenAPITools:masterfrom
anystubbs:fix-20961-python-datetime-rfc3339

Conversation

@anystubbs

@anystubbs anystubbs commented Oct 2, 2026 •

Copy link
Copy Markdown

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.
    cc Python technical committee: @cbornet @tomplus @krjakbrjak @fa0311

Summary by cubic

Changes the generated Python client to serialize datetime query parameters with RFC 3339 compliant output by default. datetime_format now defaults to None, in which case parameters are formatted with datetime.isoformat() instead of the previous default %Y-%m-%dT%H:%M:%S.%f%z via strftime, so timezone offsets render as -05:00 rather than -0500. Setting datetime_format explicitly still uses that format string.

Migration

  • Set datetimeFormat explicitly to keep the old default format output.
  • Tests that assert the old default serialization must be updated to the new RFC 3339 output.

Written for commit 6b824c9. Summary will update on new commits.

Review in cubic

@anystubbs

Copy link
Copy Markdown
Author

Fixes #20961

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

12 issues found across 26 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/openapi3/client/petstore/python-httpx-sync/petstore_api/configuration.py">

<violation number="1" location="samples/openapi3/client/petstore/python-httpx-sync/petstore_api/configuration.py:184">
P2: Naive `datetime` values still serialize without a UTC offset, so this default does not produce RFC 3339 timestamps for those callers. Reject naive values or normalize them to an explicit timezone before serialization.</violation>
</file>

<file name="samples/openapi3/client/petstore/python-lazyImports/petstore_api/configuration.py">

<violation number="1" location="samples/openapi3/client/petstore/python-lazyImports/petstore_api/configuration.py:302">
P2: The new default accepts naive datetimes, but `isoformat()` emits them without a timezone offset, so the result is not RFC 3339. Require timezone-aware values before serialization rather than silently emitting an invalid date-time.</violation>
</file>

<file name="samples/openapi3/client/petstore/python/petstore_api/configuration.py">

<violation number="1" location="samples/openapi3/client/petstore/python/petstore_api/configuration.py:302">
P2: The new default still emits non-RFC 3339 values for naive datetimes because `isoformat()` omits the timezone designator. Require or normalize timezone-aware values before serialization, or qualify the RFC 3339 guarantee for values with timezone information.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/python/configuration.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/python/configuration.mustache:377">
P2: The default `isoformat()` path does not guarantee RFC 3339: naive datetimes omit the required UTC offset. Require or normalize timezone-aware values before serialization, or document the limitation.</violation>
</file>

<file name="samples/openapi3/client/petstore/python-httpx/petstore_api/configuration.py">

<violation number="1" location="samples/openapi3/client/petstore/python-httpx/petstore_api/configuration.py:294">
P2: Naive `datetime` values still serialize without a timezone offset, so the new default does not always produce RFC 3339. Reject naive values or document that callers must supply timezone-aware datetimes.</violation>
</file>

<file name="samples/openapi3/client/petstore/python/petstore_api/api/fake_api.py">

<violation number="1" location="samples/openapi3/client/petstore/python/petstore_api/api/fake_api.py:6761">
P2: Naive `datetime` values serialize without a time-offset, so the resulting query value is not RFC 3339. Reject naive values or apply a documented timezone before serialization.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/python/api.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/python/api.mustache:328">
P2: Naive datetime arguments reach this branch and `isoformat()` omits their offset, so the default still emits a non-RFC 3339 value. Require timezone-aware datetimes before serialization.</violation>
</file>

<file name="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/configuration.py">

<violation number="1" location="samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/configuration.py:184">
P2: `datetime.isoformat()` omits the UTC offset for naive datetimes, so this default does not always produce RFC 3339; the query serializer accepts naive values without validation. Require timezone-aware values or qualify/handle the naive case instead of promising RFC 3339 compliance.</violation>
</file>

<file name="samples/client/echo_api/python/openapi_client/configuration.py">

<violation number="1" location="samples/client/echo_api/python/openapi_client/configuration.py:237">
P2: The new default does not guarantee RFC 3339 for naive `datetime` values: `datetime.isoformat()` emits no UTC offset, and the generated query method accepts naive datetimes. Reject naive values or define an explicit timezone policy before treating this serialization as RFC-compliant.</violation>
</file>

<file name="samples/openapi3/client/petstore/python-httpx2/petstore_api/configuration.py">

<violation number="1" location="samples/openapi3/client/petstore/python-httpx2/petstore_api/configuration.py:294">
P2: The new default does not produce RFC 3339 for naive datetimes: `isoformat()` omits their UTC offset. Ensure naive values are handled or rejected before serialization, rather than describing this as RFC 3339-compliant by default.</violation>
</file>

<file name="samples/openapi3/client/petstore/python-httpx2-sync/petstore_api/configuration.py">

<violation number="1" location="samples/openapi3/client/petstore/python-httpx2-sync/petstore_api/configuration.py:294">
P2: The `None` default routes naive `datetime` values through `isoformat()`, which emits no UTC offset and is not RFC 3339. Reject or normalize naive values before enabling this default.</violation>
</file>

<file name="samples/client/echo_api/python/openapi_client/api/query_api.py">

<violation number="1" location="samples/client/echo_api/python/openapi_client/api/query_api.py:576">
P2: Naive `datetime` inputs are accepted here, but `isoformat()` emits them without a timezone offset, so the default is not RFC 3339 for those values. Require timezone-aware inputs or define an explicit timezone policy before serializing them.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

:param client_side_validation: Enable client-side validation. Default True.
:param socket_options: Options to pass down to the underlying urllib3 socket.
:param datetime_format: Datetime format string for serialization.
If None, datetime.isoformat() is used, which is RFC 3339 compliant.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Naive datetime values still serialize without a UTC offset, so this default does not produce RFC 3339 timestamps for those callers. Reject naive values or normalize them to an explicit timezone before serialization.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/python-httpx-sync/petstore_api/configuration.py, line 184:

<comment>Naive `datetime` values still serialize without a UTC offset, so this default does not produce RFC 3339 timestamps for those callers. Reject naive values or normalize them to an explicit timezone before serialization.</comment>

<file context>
@@ -181,6 +181,7 @@ class Configuration:
     :param client_side_validation: Enable client-side validation. Default True.
     :param socket_options: Options to pass down to the underlying urllib3 socket.
     :param datetime_format: Datetime format string for serialization.
+      If None, datetime.isoformat() is used, which is RFC 3339 compliant.
     :param date_format: Date format string for serialization.
 
</file context>

client_side_validation: bool=True,
socket_options: Optional[Any]=None,
datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
datetime_format: Optional[str]=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new default accepts naive datetimes, but isoformat() emits them without a timezone offset, so the result is not RFC 3339. Require timezone-aware values before serialization rather than silently emitting an invalid date-time.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/python-lazyImports/petstore_api/configuration.py, line 302:

<comment>The new default accepts naive datetimes, but `isoformat()` emits them without a timezone offset, so the result is not RFC 3339. Require timezone-aware values before serialization rather than silently emitting an invalid date-time.</comment>

<file context>
@@ -298,7 +299,7 @@ def __init__(
         client_side_validation: bool=True,
         socket_options: Optional[Any]=None,
-        datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
+        datetime_format: Optional[str]=None,
         date_format: str="%Y-%m-%d",
         *,
</file context>

client_side_validation: bool=True,
socket_options: Optional[Any]=None,
datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
datetime_format: Optional[str]=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new default still emits non-RFC 3339 values for naive datetimes because isoformat() omits the timezone designator. Require or normalize timezone-aware values before serialization, or qualify the RFC 3339 guarantee for values with timezone information.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/python/petstore_api/configuration.py, line 302:

<comment>The new default still emits non-RFC 3339 values for naive datetimes because `isoformat()` omits the timezone designator. Require or normalize timezone-aware values before serialization, or qualify the RFC 3339 guarantee for values with timezone information.</comment>

<file context>
@@ -298,7 +299,7 @@ def __init__(
         client_side_validation: bool=True,
         socket_options: Optional[Any]=None,
-        datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
+        datetime_format: Optional[str]=None,
         date_format: str="%Y-%m-%d",
         *,
</file context>

client_side_validation: bool=True,
socket_options: Optional[Any]=None,
datetime_format: str="{{{datetimeFormat}}}",
datetime_format: Optional[str]={{#datetimeFormat}}"{{{.}}}"{{/datetimeFormat}}{{^datetimeFormat}}None{{/datetimeFormat}},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The default isoformat() path does not guarantee RFC 3339: naive datetimes omit the required UTC offset. Require or normalize timezone-aware values before serialization, or document the limitation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/resources/python/configuration.mustache, line 377:

<comment>The default `isoformat()` path does not guarantee RFC 3339: naive datetimes omit the required UTC offset. Require or normalize timezone-aware values before serialization, or document the limitation.</comment>

<file context>
@@ -373,7 +374,7 @@ conf = {{{packageName}}}.Configuration(
         client_side_validation: bool=True,
         socket_options: Optional[Any]=None,
-        datetime_format: str="{{{datetimeFormat}}}",
+        datetime_format: Optional[str]={{#datetimeFormat}}"{{{.}}}"{{/datetimeFormat}}{{^datetimeFormat}}None{{/datetimeFormat}},
         date_format: str="{{{dateFormat}}}",
         *,
</file context>

client_side_validation: bool=True,
socket_options: Optional[Any]=None,
datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
datetime_format: Optional[str]=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Naive datetime values still serialize without a timezone offset, so the new default does not always produce RFC 3339. Reject naive values or document that callers must supply timezone-aware datetimes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/python-httpx/petstore_api/configuration.py, line 294:

<comment>Naive `datetime` values still serialize without a timezone offset, so the new default does not always produce RFC 3339. Reject naive values or document that callers must supply timezone-aware datetimes.</comment>

<file context>
@@ -290,7 +291,7 @@ def __init__(
         client_side_validation: bool=True,
         socket_options: Optional[Any]=None,
-        datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
+        datetime_format: Optional[str]=None,
         date_format: str="%Y-%m-%d",
         *,
</file context>

:param client_side_validation: Enable client-side validation. Default True.
:param socket_options: Options to pass down to the underlying urllib3 socket.
:param datetime_format: Datetime format string for serialization.
If None, datetime.isoformat() is used, which is RFC 3339 compliant.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: datetime.isoformat() omits the UTC offset for naive datetimes, so this default does not always produce RFC 3339; the query serializer accepts naive values without validation. Require timezone-aware values or qualify/handle the naive case instead of promising RFC 3339 compliance.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/configuration.py, line 184:

<comment>`datetime.isoformat()` omits the UTC offset for naive datetimes, so this default does not always produce RFC 3339; the query serializer accepts naive values without validation. Require timezone-aware values or qualify/handle the naive case instead of promising RFC 3339 compliance.</comment>

<file context>
@@ -181,6 +181,7 @@ class Configuration:
     :param client_side_validation: Enable client-side validation. Default True.
     :param socket_options: Options to pass down to the underlying urllib3 socket.
     :param datetime_format: Datetime format string for serialization.
+      If None, datetime.isoformat() is used, which is RFC 3339 compliant.
     :param date_format: Date format string for serialization.
 
</file context>

client_side_validation: bool=True,
socket_options: Optional[Any]=None,
datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
datetime_format: Optional[str]=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new default does not guarantee RFC 3339 for naive datetime values: datetime.isoformat() emits no UTC offset, and the generated query method accepts naive datetimes. Reject naive values or define an explicit timezone policy before treating this serialization as RFC-compliant.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/echo_api/python/openapi_client/configuration.py, line 237:

<comment>The new default does not guarantee RFC 3339 for naive `datetime` values: `datetime.isoformat()` emits no UTC offset, and the generated query method accepts naive datetimes. Reject naive values or define an explicit timezone policy before treating this serialization as RFC-compliant.</comment>

<file context>
@@ -233,7 +234,7 @@ def __init__(
         client_side_validation: bool=True,
         socket_options: Optional[Any]=None,
-        datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
+        datetime_format: Optional[str]=None,
         date_format: str="%Y-%m-%d",
         *,
</file context>

client_side_validation: bool=True,
socket_options: Optional[Any]=None,
datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
datetime_format: Optional[str]=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new default does not produce RFC 3339 for naive datetimes: isoformat() omits their UTC offset. Ensure naive values are handled or rejected before serialization, rather than describing this as RFC 3339-compliant by default.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/python-httpx2/petstore_api/configuration.py, line 294:

<comment>The new default does not produce RFC 3339 for naive datetimes: `isoformat()` omits their UTC offset. Ensure naive values are handled or rejected before serialization, rather than describing this as RFC 3339-compliant by default.</comment>

<file context>
@@ -290,7 +291,7 @@ def __init__(
         client_side_validation: bool=True,
         socket_options: Optional[Any]=None,
-        datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
+        datetime_format: Optional[str]=None,
         date_format: str="%Y-%m-%d",
         *,
</file context>

client_side_validation: bool=True,
socket_options: Optional[Any]=None,
datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
datetime_format: Optional[str]=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The None default routes naive datetime values through isoformat(), which emits no UTC offset and is not RFC 3339. Reject or normalize naive values before enabling this default.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/python-httpx2-sync/petstore_api/configuration.py, line 294:

<comment>The `None` default routes naive `datetime` values through `isoformat()`, which emits no UTC offset and is not RFC 3339. Reject or normalize naive values before enabling this default.</comment>

<file context>
@@ -290,7 +291,7 @@ def __init__(
         client_side_validation: bool=True,
         socket_options: Optional[Any]=None,
-        datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z",
+        datetime_format: Optional[str]=None,
         date_format: str="%Y-%m-%d",
         *,
</file context>

(
'datetime_query',
datetime_query.strftime(
datetime_query.isoformat()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Naive datetime inputs are accepted here, but isoformat() emits them without a timezone offset, so the default is not RFC 3339 for those values. Require timezone-aware inputs or define an explicit timezone policy before serializing them.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/echo_api/python/openapi_client/api/query_api.py, line 576:

<comment>Naive `datetime` inputs are accepted here, but `isoformat()` emits them without a timezone offset, so the default is not RFC 3339 for those values. Require timezone-aware inputs or define an explicit timezone policy before serializing them.</comment>

<file context>
@@ -573,7 +573,9 @@ def _test_query_datetime_date_string_serialize(
                     (
                         'datetime_query',
-                        datetime_query.strftime(
+                        datetime_query.isoformat()
+                        if self.api_client.configuration.datetime_format is None
+                        else datetime_query.strftime(
</file context>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant