fix(python-flask, python-aiohttp): name handler arguments the way Connexion passes them
With pythonic_params=True, which the generated python-flask and python-aiohttp servers use, Connexion renames parameters with snake_and_shadow(): snake_case, then a trailing _ if the name is a Python builtin or, since Connexion 2.10, a keyword. The generator named the handler arguments differently. It added a leading _ for its own reserved words and left builtins unchanged. As a result:
- a path parameter
idproduceddef get_thing(id, ...)while Connexion callsget_thing(id_=...), so every request fails withTypeError(500); - query parameters such as
filter,typeorformatare silently dropped.
Changes
AbstractPythonConnexionServerCodegen.toParamName():
- appends
_to Python builtins (a fixed list of the lowercasedir(builtins)names; it matches Python 3.11 and 3.14 exactly) and to keywords, like Connexion; - keeps leading underscores (
_fromstays_from) and passescallbackthrough unchanged, as Connexion does; - keeps the previous naming for header and cookie parameters. Connexion never passes these to the handler (they are read from the request), so they keep a name such as
_jsonthat doesn't shadow modules likejson.
python-blueplanet opts out (usesPythonicParams() returns false). Its generated app doesn't set pythonic_params, so Connexion 1.x passes the original names.
The wire names don't change: x-python-connexion-openapi-name restores them in the generated openapi.yaml, now also for parameters defined under components/parameters. The generated controller tests send form data under the wire names too.
A side effect: names that the generator reserved but that are neither builtins nor keywords (date, self, schema, ...) now become date instead of _date, which is what Connexion passes.
Verification
Python*Test/AbstractPython*Testpass. The new tests cover flask, aiohttp and blueplanet signatures,_from,callback,date/self, a JSON header namedjson, a$refparameter, and form keys.- Generated python-flask and python-aiohttp servers from a spec with path
idand queryfilter,type,format,from,pageSize, plus_from,callback,date,selfand a JSON headerjson. On Connexion 2.14.2, the requests return 200 with every value delivered (id_,filter_,type_,format_,from_,page_size,_from,callback,date,self,_json). With the generator from master, the sameGET /probe/abcfails withTypeError: unexpected keyword argument 'id_'. bin/generate-samples.sh bin/configs/python*.yamlproduces no diff; none of the sample specs use such names.
Known remaining differences / not in this PR
- Names that Connexion's
inflection.underscore()and the generator'sunderscore()still convert differently: acronyms (HTTPId), names with dots or other separators, and names starting with a digit. A spec with bothidandid_can't work either, because Connexion maps both toid_. - The builtins list follows current Pythons:
aiter/anext(3.10+) andbreakpoint(3.7+) would still mismatch on older interpreters. - Pre-existing and unchanged:
application/x-www-form-urlencodedrequest bodies fail on master too (missing 1 required positional argument). Connexion passes the form as a singlebodyargument, while the generated handler expects one argument per field.
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 handlers to name arguments the way Connexion actually passes them (pythonic_params=True). Previously, a path param id became id in the signature while Connexion sent id_, causing a TypeError (500) on every request; query params like filter, type, and format were silently dropped because the handler argument names didn't match.
- Builtins and keywords now get a trailing underscore (
id_,filter_,from_), matching Connexion'ssnake_and_shadow(). - Header and cookie params keep the previous naming, since Connexion reads them from the request and never passes them to the handler.
- Wire names in the generated
openapi.yamlare preserved via the existingx-python-connexion-openapi-nameextension, now also for parameters undercomponents/parameters. python-blueplanetopts out of the new naming because its generated app doesn't setpythonic_params(Connexion 1.x).