Skip to content

fix(python-fastapi): rebase #24098 onto master (relax path/query/header strict typing, #21905) - #24793

Open
JerrySLau wants to merge 8 commits into
OpenAPITools:masterfrom
JerrySLau:goopher/fix_python-fastapi-query-param-strict-coercion
Open

fix(python-fastapi): rebase #24098 onto master (relax path/query/header strict typing, #21905)#24793
JerrySLau wants to merge 8 commits into
OpenAPITools:masterfrom
JerrySLau:goopher/fix_python-fastapi-query-param-strict-coercion

Conversation

@JerrySLau

@JerrySLau JerrySLau commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

This PR rebases @goopher's #24098 onto current master. It does not change the original fix; it only resolves merge conflicts and keeps the behavior working against upstream refactors that landed after #24098.

Original problem (#21905): Pydantic strict types (StrictInt/StrictStr/StrictFloat) and Field(strict=True) disable string coercion. Path/query/header values always arrive as strings, so FastAPI rejected valid requests with 422 (int_type: Input should be a valid integer).

Original approach (from #24098):

  • Path/query/header params emit coercible types (int/str/float) and omit strict=True.
  • Body params and the Python client stay strict (JSON bodies carry real types).
  • Strictness is a type (PydanticCoercibleType), selected by getPydanticParameterType(), not a boolean flag.

What this rebase had to reconcile with master:

Fixes #21905
Supersedes / continues #24098 (credit: @goopher)

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.

Summary by cubic

Fixes #21905 by relaxing strict Pydantic typing for python-fastapi path/query/header/cookie params, which previously rejected valid requests with 422 because wire-string values couldn't be coerced to StrictInt/StrictStr/StrictFloat.

Bug Fixes

  • Path/query/header/cookie params now emit coercible int/str/float types without strict=True via a new PydanticCoercibleType; body params and the Python client keep strict types.
  • Endpoint argument commas now stay on the parameter line; a trailing newline in the endpoint_argument_definition.mustache partial was making them wrap onto their own line.
  • Rebased onto master while preserving the ConstraintApplier from [python] centralize the Python constraint rules #24141, with regenerated petstore samples and regression tests.

Written for commit ae92480. Summary will update on new commits.

Review in cubic

goopher and others added 6 commits June 22, 2026 20:02
…OpenAPITools#21905)

Pydantic strict types (StrictInt/StrictStr/StrictFloat) and Field(strict=True)
disable automatic string coercion. Since path/query/header values always arrive
on the wire as strings, FastAPI rejected otherwise-valid requests with a 422
(int_type: Input should be a valid integer).

Add a relaxStrict flag to PydanticType that emits coercible types (int/str/float)
and omits strict=True, gated behind a shouldRelaxStrictParameterTyping() hook that
defaults to false. PythonFastAPIServerCodegen overrides it for path/query/header
params. Body params and the Python client generator are unchanged (strict typing
is correct for JSON bodies).

Regenerated the python-fastapi petstore sample.

Claude-Session: https://claude.ai/code/session_019g7iwAyg7ErX1WrhqHyTn6
Replace the relaxStrict boolean + shouldRelaxStrictParameterTyping hook with
an explicit PydanticCoercibleType subclass of PydanticType that never emits
Pydantic strict types for the scalar kinds where strictness blocks coercion.

Selection moves into a getPydanticParameterType() factory: PythonFastAPIServer
returns PydanticCoercibleType for path/query/header params and the strict base
type for everything else. The rule ("wire-string params are never strict") is
now a code structure rather than a flag callers must remember to set, and the
explanatory comment lives in one place on the class it describes.

Behaviour-preserving: the regenerated python-fastapi sample is byte-identical
to the previous commit. Python codegen tests (fastapi, client) pass.

Claude-Session: https://claude.ai/code/session_019g7iwAyg7ErX1WrhqHyTn6
… for FastAPI path/query/header params)

Resolve conflicts in AbstractPythonCodegen.java: upstream moved constraint
handling into a static ConstraintApplier / ConstraintType, replacing the
per-type constants and the instance applyConstraints method. Reapply the
PR's PydanticCoercibleType subclass on top of that refactor so path/query/
header parameters emit coercible (non-strict) Pydantic types, using the new
ConstraintApplier API.
…OpenAPITools#21905)

Pydantic strict types (StrictInt/StrictStr/StrictFloat) and Field(strict=True)
disable automatic string coercion. Since path/query/header values always arrive
on the wire as strings, FastAPI rejected otherwise-valid requests with a 422
(int_type: Input should be a valid integer).

Add a relaxStrict flag to PydanticType that emits coercible types (int/str/float)
and omits strict=True, gated behind a shouldRelaxStrictParameterTyping() hook that
defaults to false. PythonFastAPIServerCodegen overrides it for path/query/header
params. Body params and the Python client generator are unchanged (strict typing
is correct for JSON bodies).

Regenerated the python-fastapi petstore sample.

Claude-Session: https://claude.ai/code/session_019g7iwAyg7ErX1WrhqHyTn6

Conflicts:
      modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java
      samples/server/petstore/python-fastapi/src/openapi_server/apis/fake_api.py
      samples/server/petstore/python-fastapi/src/openapi_server/apis/pet_api.py
      samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api.py
      samples/server/petstore/python-fastapi/src/openapi_server/apis/user_api.py
Replace the relaxStrict boolean + shouldRelaxStrictParameterTyping hook with
an explicit PydanticCoercibleType subclass of PydanticType that never emits
Pydantic strict types for the scalar kinds where strictness blocks coercion.

Selection moves into a getPydanticParameterType() factory: PythonFastAPIServer
returns PydanticCoercibleType for path/query/header params and the strict base
type for everything else. The rule ("wire-string params are never strict") is
now a code structure rather than a flag callers must remember to set, and the
explanatory comment lives in one place on the class it describes.

Behaviour-preserving: the regenerated python-fastapi sample is byte-identical
to the previous commit. Python codegen tests (fastapi, client) pass.

Claude-Session: https://claude.ai/code/session_019g7iwAyg7ErX1WrhqHyTn6

 Conflicts:
	modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java

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

All reported issues were addressed across 10 files

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

Re-trigger cubic

@wing328

wing328 commented Aug 27, 2026

Copy link
Copy Markdown
Member

thanks for filing a new PR based on the latest master

cc @cbornet (2017/09) @tomplus (2018/10) @krjakbrjak (2023/02) @fa0311 (2023/10)

…ITools#21905)

Cookie values arrive as strings in the Cookie header, just like
path/query/header params, so strict types (StrictInt/StrictBool/
StrictStr, strict=True) disabled Pydantic's string coercion and made
FastAPI reject valid requests with a 422.

Route cookie params through PydanticCoercibleType as well, and add a
regression test covering path/query/header/cookie params while
verifying JSON body model properties keep strict typing.
The trailing newline added to endpoint_argument_definition.mustache in
OpenAPITools#23398 leaks into the rendered output: api.mustache includes the partial
inline, immediately followed by a comma, so the newline wraps the comma
onto a line of its own:

    pet: Annotated[Pet, Field(description="...")] = Body(..., description="...")
    ,

Remove the trailing newline so parameters render as `...),` again.
Add a regression test asserting the comma stays at end of line (raw
content checks, since assertFileContains linearizes away newlines), and
regenerate the python-fastapi petstore sample.
@JerrySLau

Copy link
Copy Markdown
Contributor Author

Added ae92480 — a small formatting fix spotted while regenerating samples:

fix(python-fastapi): keep endpoint argument comma on the parameter line

#23398 added a trailing newline to endpoint_argument_definition.mustache, which wraps the parameter comma onto its own line in generated code. This commit removes it (plus a regression test and sample regeneration). No behavior change.

@wing328

wing328 commented Aug 27, 2026

Copy link
Copy Markdown
Member

is it correct to say that you've been using this fix in the production environment and it works as expected?

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.

[BUG][Python] strict=True in Pydantic Field breaks HTTP query parameter type conversion for integers

3 participants