chore(open-api#py-client): add hidden Python httpx client generator#586
Open
nx-plugin-for-aws wants to merge 4 commits into
Open
chore(open-api#py-client): add hidden Python httpx client generator#586nx-plugin-for-aws wants to merge 4 commits into
nx-plugin-for-aws wants to merge 4 commits into
Conversation
Contributor
|
📚 Documentation translations have been updated and committed (e0e8b17) to this PR. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #586 +/- ##
==========================================
- Coverage 87.83% 87.68% -0.15%
==========================================
Files 166 167 +1
Lines 6067 6310 +243
Branches 1467 1557 +90
==========================================
+ Hits 5329 5533 +204
- Misses 367 370 +3
- Partials 371 407 +36 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
e0e8b17 to
ce94e62
Compare
Contributor
|
📚 Documentation translations have been updated and committed (3ff14ec) to this PR. |
Contributor
|
📚 Documentation translations have been updated and committed (904ee26) to this PR. |
1 task
904ee26 to
473976b
Compare
Contributor
|
📚 Documentation translations have been updated and committed (2da12ce) to this PR. |
ee94c32 to
4b9e07d
Compare
34d7d5d to
352d62c
Compare
fc1239b to
d612646
Compare
nx-plugin-for-aws
pushed a commit
that referenced
this pull request
Jul 10, 2026
Rebased port of #586 onto main's rewritten OpenAPI codegen pipeline (parser.ts + typed codegen-data). Emits pydantic v2 models and httpx-based sync/async clients mirroring open-api#ts-client.
d612646 to
f8ce907
Compare
nx-plugin-for-aws
pushed a commit
that referenced
this pull request
Jul 13, 2026
Rebased port of #586 onto main's rewritten OpenAPI codegen pipeline (parser.ts + typed codegen-data). Emits pydantic v2 models and httpx-based sync/async clients mirroring open-api#ts-client.
f8ce907 to
4842013
Compare
added 4 commits
July 15, 2026 00:18
Rebased port of #586 onto main's rewritten OpenAPI codegen pipeline (parser.ts + typed codegen-data). Emits pydantic v2 models and httpx-based sync/async clients mirroring open-api#ts-client.
- Tagged discriminated unions: discriminated oneOf/anyOf renders as a pydantic tagged union (Annotated[Union[...], Field(discriminator=...)]) with Literal-typed discriminator fields on each member, mirroring the ts-client tagged-union narrowing from #913. - multipart/form-data: flattened-body multipart requests route fields through httpx files=/data= instead of JSON-encoding, matching the ts-client FormData handling from #914; binary fields stream as file parts. - deepObject query parameters serialise as key[prop]=value pairs. - toPythonName also tests the snake-cased form against the Python keyword set so spec properties like 'from_' don't emit invalid syntax.
… from #922 and #930 - application/x-www-form-urlencoded bodies route through httpx data= (arrays as repeated keys, None fields omitted) instead of being JSON-encoded. - Fixed-length tuples (3.1 prefixItems) render as tuple[A, B] with TypeAdapter validation; open tuples degrade to plain lists. - matrix and label path styles serialise per RFC 6570 (with explode). - allowReserved query parameters keep reserved characters literal via a manually built query string. - Content-based (content: application/json) parameters JSON-serialise their value as a single query/header/cookie entry. - Multipart parts honour content types declared by the request body encoding object. - Python worker reads streamed (multipart) request bodies so tests can assert on the wire payload.
…batim Parity with #937: a urlencoded body whose schema is a primitive (e.g. a raw pre-encoded string) is sent as-is via httpx content= with the declared Content-Type, rather than being dict-iterated for form encoding. Object bodies are unchanged. The #938 generation-time guard for non-encodable urlencoded array bodies is inherited from shared codegen; covered with a py-client test.
4842013 to
efd3431
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reason for this change
Future connection generators (React → FastAPI Python client, Python client → tRPC API over OpenAPI, etc.) need a Python client generator symmetric to
open-api#ts-client. This PR lands the foundation as a hidden generator so it can evolve without release-note surface until a connection generator consumes it.Description of changes
Adds
open-api#py-client(hidden) that emits:types_gen.py— pydantic v2 models for every schema, per-operation error wrapper classes, per-operation requestTypedDicts.client_gen.py— sync client usinghttpx.Client(whenclientTypeissyncorboth).async_client_gen.py— async client usinghttpx.AsyncClient(whenclientTypeisasyncorboth).The shape mirrors
open-api#ts-clientend-to-end:tagsare exposed asapi.pet.add_pet(...)rather than flat methods.api.user.create_users_with_list_input([User(...), ...])).GetPetByIdApiError) with.errornarrowable to a discriminated union (GetPetById404Error | GetPetById5XXError | GetPetByIdDefaultError).application/jsonl+itemSchemaandapplication/x-ndjsonreturningIterator[T]/AsyncIterator[T].Field(frozen=True)for readOnly,Field(description=...)from spec, multipart/form-data + binary request bodies.Shared codegen changes
To keep the Python generator as thin as the TypeScript one, language-agnostic concerns moved into
codegen-data.ts:op.parameterGroups = { path, query, header, cookie, body }— templates no longer filter byin.op.requestShape— neutral description of operation inputs with asourcetag so language templates translate once.op.errorShape— neutral error taxonomy (one entry per non-success response) withstatusCodesprecomputed for ranges like5XX.toPythonTypenow returns idiomatic PEP-585 types; addedtoPythonAnnotationfor forward-ref-quoted use.pythonType/pythonAnnotation/effectiveProperties(allOf flattening) /isInlinedByAllOf/referencedCollectionKind— all neutral.Only Python-specific concerns stay in
open-api/py-client/generator.ts.PythonVerifier test harness
A new long-lived
uv run --with pydantic --with httpxworker compiles generated modules withpy_compileand invokes their methods against a mockedhttpxtransport that records every request. Lets the TS test suite verify generated code both syntactically and behaviourally.Description of how you validated changes
it.each-parameterised) covering shapes, operations, errors, real specs (petstore + FastAPI).Issue # (if applicable)
N/A — scoped as
chorebecause the generator is hidden and intended for internal use by upcoming connection generators. Not advertised in release notes until consumed.Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license
Rebase notes (2026-07-10)
Rebased onto latest main (post-#886 codegen rewrite). Because the shared OpenAPI pipeline was rewritten on main (typed
parser.ts+codegen-data.ts), the shared-codegen portion of this PR was re-implemented against the new architecture rather than merged textually:requestShape/errorShape/parameter annotationsnow live in typed form incodegen-data.ts+codegen-data/types.ts(noas any).toPythonType,toPythonAnnotation,qualifyPythonType,toPythonClassName) integrated into main'slanguages.ts, emitting PEP-585 generics andLiteral[...]enums.New parity features (added on main after this PR forked):
oneOf/anyOfrenders as a pydantic tagged union —Annotated[Union[...], Field(discriminator=...)]— withLiteral-typed discriminator fields on each member, so parsing dispatches to the matching branch and never merges branches.files=/data=(binary values stream as file parts); never JSON-encoded.key[prop]=valuepairs, matching ts-client.Metric moved from
g38(now taken byts#rdb) tog56. All 2661 unit tests pass locally.Rebase notes (2026-07-13)
Rebased onto latest main again and ported the ts-client spec-compliance fixes that landed since:
application/x-www-form-urlencodedbodies route through httpxdata=(repeated keys for arrays,Noneomitted) instead of JSON; fixed-length tuples (3.1prefixItems) render astuple[A, B]validated viaTypeAdapter; JSON-wire primitive responses parse correctly; non-discriminated unions with conflicting member marshalling fail loudly at generation time (sharedassertNoConflictingUnionMemberMarshalling).matrix/labelpath styles (incl. explode) serialise per RFC 6570;allowReservedquery parameters keep reserved characters literal; content-based (content: application/json) parameters JSON-serialise as a single value; multipart parts honourencoding-declared content types.All 2753 unit tests pass locally; build green.
Rebase notes (2026-07-15)
Rebased onto latest main (clean rebase, no conflicts) and ported the two urlencoded ts-client fixes that landed since:
content=with the declared Content-Type, instead of being dict-iterated for form encoding. Object bodies unchanged.All 2778 unit tests pass locally; build green.