fix(python-aiohttp): don't clash the Connexion context argument with a parameter named 'request'

KH
1d ago
+441-6

Generated python-aiohttp apps register the API with pass_context_arg_name='request', and every handler takes the aiohttp request as its first argument request. A parameter whose handler argument name is also request breaks this:

async def list_things(request: web.Request, request=None) -> web.Response:   # SyntaxError: duplicate argument

The app doesn't start. Even if it compiled, Connexion sets kwargs[pass_context_arg_name] after the parameters, so the parameter value would be overwritten by the request context. I didn't find an existing issue for this.

Changes

  • The context argument name is computed once for the whole spec in preprocessOpenAPI. add_api is called once, and __init__.py, tests/conftest.py and every controller must use the same name.
  • It stays request unless a handler argument would use that name. Then it becomes request_context, or request_context2, request_context3, ... if those are taken too. A warning is logged when this happens.
  • Handler argument names are collected the way the generator builds them:
    • parameters, including path-level and $ref'd ones;
    • the body argument name;
    • form fields of the first content type, walking allOf/$ref like fromRequestBodyToFormParameters;
    • across both paths and webhooks;
    • including the numbers DefaultCodegen appends to duplicate parameter names.
  • The templates (__init__main.mustache, conftest.mustache, controller.mustache, including the .headers / .cookies reads) take the name from the connexionContextArgName additional property.
  • Specs without such a parameter generate exactly the same output as before.

Why rename the context argument instead of the parameter: Connexion derives the keyword it passes from the wire name, and the generated openapi.yaml keeps the original names. So the generator cannot choose a different handler argument name for the parameter. The context argument name, on the other hand, is ours to pick.

Verification

  • Python*Test / AbstractPython*Test pass (177). The new tests cover:

    • a query request;
    • request together with request_context (gives request_context2);
    • duplicate names that DefaultCodegen renumbers (gives request_context3);
    • a multipart form field request inside allOf;
    • an OAS 3.1 webhook with request;
    • a spec without request (stays request).

    They fail without the change.

  • I generated python-aiohttp from those specs and from petstore. All .py files pass compileall. On Connexion 2.14.2, GET /v1/things?request=abc with X-Trace: t returns 200 and the handler receives request='abc' and the header value. The generated tests/ pass. With the generator from master, the same project doesn't compile.

  • bin/generate-samples.sh bin/configs/python*.yaml produces no diff.

Known limitations (unchanged by this PR):

  • Names that Connexion and the generator convert differently, e.g. re.quest, are not detected. Connexion's pythonic() gives request; the generator gives re_quest. That mismatch exists independently of this change.
  • Other arguments Connexion injects, such as user / token_info, are out of scope here.

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 python-aiohttp generated apps becoming uncompilable when a spec has a parameter whose handler argument name is request. The Connexion context argument is now renamed to request_context (or request_context2, etc. if that is taken too), so generated handlers compile and the parameter value is no longer overwritten by the request context.

Details

  • The context argument name is resolved once for the whole spec and shared by the templates via the connexionContextArgName additional property.
  • Collision detection covers parameters (including path-level and $ref'd ones), body argument names, form fields in composed schemas, webhooks, and duplicate-name renumbering.
  • Specs without a conflicting parameter generate identical output to before.