Skip to content

[python] fix regex validator for date-time fields with a pattern#24105

Closed
timonrieger wants to merge 3 commits into
OpenAPITools:masterfrom
timonrieger:fix/datetime-regex
Closed

[python] fix regex validator for date-time fields with a pattern#24105
timonrieger wants to merge 3 commits into
OpenAPITools:masterfrom
timonrieger:fix/datetime-regex

Conversation

@timonrieger

@timonrieger timonrieger commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes the regex @field_validator generated for a property that has both format: date-time (or date/time) and a pattern, in the python (pydantic v2) generator.

Because the field is typed datetime, pydantic parses the JSON string into a datetime before the after-mode validator runs. The previous template did:

if not isinstance(value, str):
  value = str(value)          # -> "2026-06-23 10:21:47.710000+00:00" (space, not "T")
if not re.match(r"^...T...$", value):
  raise ValueError(...)
return value                    # -> field value clobbered to a str

Two defects:

  1. Wrong stringification: str(datetime) is space-separated and fails any ISO-8601 pattern, so every valid patterned date-time field raised ValidationError on deserialization.
  2. Type clobbering: value was reassigned to its stringified form and then returned, replacing the strongly-typed value with a str (e.g. a UUID/datetime field ends up holding a str, surfacing as PydanticSerializationUnexpectedValue).

The validator now matches against a derived string and returns the original value:

  • datetime/date/time → .isoformat() → T-separated, offset-aware → matches.
  • UUID/Decimal/int/enum → no isoformat → unchanged str() for matching only.
  • return value preserves the declared field type. No new imports required.

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 @cbornet (2017/09) @tomplus (2018/10) @krjakbrjak (2023/02) @fa0311 (2023/10) @multani (2023/10)

@timonrieger timonrieger marked this pull request as ready for review June 23, 2026 12:41
@wing328 wing328 added this to the 7.24.0 milestone Jun 23, 2026
timonrieger added a commit to timonrieger/immichpy that referenced this pull request Jun 23, 2026

@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.

2 issues found across 15 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


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

<violation number="1" location="samples/openapi3/client/petstore/python-httpx/petstore_api/models/nullable_property.py:41">
P2: Non-string conversion branches in pattern validator are dead code for this strict string field</violation>
</file>

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

<violation number="1" location="modules/openapi-generator/src/main/resources/python/model_generic.mustache:57">
P2: Pattern validation uses isoformat() which normalizes datetime representations (e.g., Z → +00:00), causing valid inputs matching patterns that expect the original lexical form to incorrectly fail validation.</violation>
</file>

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

Re-trigger cubic

value = str(value)

if not re.match(r"^[A-Z].*", value):
s = value if isinstance(value, str) else value.isoformat() if hasattr(value, "isoformat") else str(value)

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: Non-string conversion branches in pattern validator are dead code for this strict string field

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/client/petstore/python-httpx/petstore_api/models/nullable_property.py, line 41:

<comment>Non-string conversion branches in pattern validator are dead code for this strict string field</comment>

<file context>
@@ -38,10 +38,8 @@ def name_validate_regular_expression(cls, value):
-            value = str(value)
-
-        if not re.match(r"^[A-Z].*", value):
+        s = value if isinstance(value, str) else value.isoformat() if hasattr(value, "isoformat") else str(value)
+        if not re.match(r"^[A-Z].*", s):
             raise ValueError(r"must validate the regular expression /^[A-Z].*/")
</file context>


if not re.match(r"{{{.}}}", value{{#vendorExtensions.x-modifiers}} ,re.{{{.}}}{{/vendorExtensions.x-modifiers}}):
# match against the ISO string of parsed values (e.g. datetime) without mutating value
s = value if isinstance(value, str) else value.isoformat() if hasattr(value, "isoformat") else str(value)

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: Pattern validation uses isoformat() which normalizes datetime representations (e.g., Z → +00:00), causing valid inputs matching patterns that expect the original lexical form to incorrectly fail validation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/python/model_generic.mustache, line 57:

<comment>Pattern validation uses isoformat() which normalizes datetime representations (e.g., Z → +00:00), causing valid inputs matching patterns that expect the original lexical form to incorrectly fail validation.</comment>

<file context>
@@ -53,10 +53,9 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
-
-        if not re.match(r"{{{.}}}", value{{#vendorExtensions.x-modifiers}} ,re.{{{.}}}{{/vendorExtensions.x-modifiers}}):
+        # match against the ISO string of parsed values (e.g. datetime) without mutating value
+        s = value if isinstance(value, str) else value.isoformat() if hasattr(value, "isoformat") else str(value)
+        if not re.match(r"{{{.}}}", s{{#vendorExtensions.x-modifiers}} ,re.{{{.}}}{{/vendorExtensions.x-modifiers}}):
             raise ValueError(r"must validate the regular expression {{{vendorExtensions.x-pattern}}}")
</file context>

@timonrieger timonrieger marked this pull request as draft June 23, 2026 18:26
@timonrieger

Copy link
Copy Markdown
Contributor Author

Closing in favor of #24072, @wing328 that PR should be merged for the next minor. Tested this patch.

@timonrieger timonrieger deleted the fix/datetime-regex branch June 23, 2026 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants