fix(python-flask, python-aiohttp): generate valid security function names for scheme names with '-' or '.'
Security scheme names may contain - and .: OpenAPI component keys match ^[a-zA-Z0-9\.\-_]+$. The generated python-flask / python-aiohttp security_controller.py uses the name verbatim in function names, and the x-*InfoFunc extensions in the generated openapi.yaml point at the same names. For example, with a scheme named api-key:
def info_from_api-key(api_key, required_scopes): # SyntaxError
The module doesn't compile, so the generated app can't start. I didn't find an existing issue for this.
Changes
- Each scheme name gets one Python identifier suffix, computed once in
preprocessOpenAPI, in spec order. Characters other than[A-Za-z0-9_]become_. Names that would collide (e.g.api-keyandapi.key) are numbered_2,_3, and so on. addSecurityExtensions(x-apikeyInfoFunc,x-basicInfoFunc,x-bearerInfoFunc,x-tokenInfoFunc,x-scopeValidateFunc) and thesecurity_controller.mustachetemplates both use that suffix. The templates get it through afromSecurityoverride that setsx-python-connexion-security-function-suffix.- Names that are already valid identifiers produce exactly the same output as before. User-provided
x-*InfoFuncextensions are kept.
Verification
Python*Test/AbstractPython*Testpass. The new test covers python-flask, python-flask withuseConnexion3, and python-aiohttp. It uses schemesapi-key,petstore.auth(OAuth2),basic-auth,bearer-token,1st-key, a literalapi_key_2next to the collidingapi.key, and a scheme with a user-providedx-apikeyInfoFunc. It fails without the change.- I generated python-flask from that spec. All
.pyfiles passcompileall. On Connexion 2.14.2, every protected operation (apiKey, basic, bearer, OAuth2, the colliding and the user-provided ones) returns 401 without credentials and 200 with them. With the generator from master, the same project doesn't compile. A second review also exercised Connexion 3.3.0 and aiohttp. bin/generate-samples.sh bin/configs/python*.yamlproduces no diff.
Note: #25457 also overrides fromSecurity in the same class. Whichever lands second needs the two bodies merged into one override.
PR checklist
- Read the contribution guidelines.
- Run the following to build the project and update samples:
Regenerated all./mvnw clean package || exit ./bin/generate-samples.sh ./bin/configs/*.yaml || exit ./bin/utils/export_docs_generators.sh || exitbin/configs/python*.yamlsamples: no diff. Generator options and docs are unchanged. - 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 @tomplus @krjakbrjak @fa0311 (Python technical committee)
Parts of this change were drafted with AI coding assistants (Devin, Claude Code, with reviews by Codex and Fable) and reviewed and verified by me.
š¤ Generated with Claude Code
Summary by cubic
Fixes generated python-flask and python-aiohttp apps failing to compile when a security scheme name contains - or . (e.g. api-key). Scheme names were used verbatim in security_controller.py function names and in the x-*InfoFunc/x-scopeValidateFunc references in the spec, producing invalid Python like def info_from_api-key(...).
Each scheme name now maps to a valid Python identifier suffix computed once per spec: non-[A-Za-z0-9_] characters become _, names that are already valid identifiers keep their unnumbered suffix, and sanitized names that would collide (e.g. api-key and api.key) get _2, _3, etc. Both the security_controller.mustache templates and the x-*Func extensions use the same suffix via a fromSecurity override, and user-provided x-*InfoFunc extensions are preserved.
The new test parses the generated openapi.yaml and asserts each x-*Func reference points at the matching generated function, covering python-flask, python-flask with useConnexion3, and python-aiohttp; generated samples are unchanged. Note: #25457 also overrides fromSecurity in the same class ā whichever lands second must merge the two method bodies.