fix(python-flask, python-aiohttp): generate valid security function names for scheme names with '-' or '.'

KH
2h ago
+381-16

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-key and api.key) are numbered _2, _3, and so on.
  • addSecurityExtensions (x-apikeyInfoFunc, x-basicInfoFunc, x-bearerInfoFunc, x-tokenInfoFunc, x-scopeValidateFunc) and the security_controller.mustache templates both use that suffix. The templates get it through a fromSecurity override that sets x-python-connexion-security-function-suffix.
  • Names that are already valid identifiers produce exactly the same output as before. User-provided x-*InfoFunc extensions are kept.

Verification

  • Python*Test / AbstractPython*Test pass. The new test covers python-flask, python-flask with useConnexion3, and python-aiohttp. It uses schemes api-key, petstore.auth (OAuth2), basic-auth, bearer-token, 1st-key, a literal api_key_2 next to the colliding api.key, and a scheme with a user-provided x-apikeyInfoFunc. It fails without the change.
  • I generated python-flask from that spec. All .py files pass compileall. 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*.yaml produces 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:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    Regenerated all bin/configs/python*.yaml samples: 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.