alt-stack-openapi-pydantic
Generate Python 3.11+ Pydantic 2 models, statically typed Request/Response route maps, and an asyncio HttpxApiClient from OpenAPI JSON. This is the Python counterpart of @alt-stack/zod-openapi; the generated client runs on alt-stack-http-client-httpx.
Install
python -m pip install alt-stack-openapi-pydantic
Consumers of a generated SDK install the runtime package instead:
python -m pip install alt-stack-http-client-httpx
Generate
alt-stack-openapi-pydantic ./openapi.json --output ./generated_types.py
input may be a local JSON path or HTTP(S) URL. Use --registry to execute custom type mappings and --include to insert imports/definitions into output.
from generated_types import User
user = User.model_validate({"id": "u_1", "name": "Ada"})
The CLI enables route generation and emits Request/Response dictionaries whose leaves are Pydantic model classes. The dictionaries carry generated TypedDict annotations, so type checkers resolve literal lookups to the exact model and reject unknown paths, methods, request parts, and status codes:
from generated_types import Request, Response
Request["/users"]["POST"]["body"] # type[CreateUserBody]
Response["/users/{id}"]["GET"]["200"] # type[User]
Response["/users/{id}"]["GET"]["999"] # static error: unknown status
Generated modules also include an asyncio HttpxApiClient with one typed method per route, built on alt_stack_http_client_httpx:
from alt_stack_http_client_httpx import ApiSuccess
from generated_types import GetUsersIdParams, HttpxApiClient, Request, Response
async with HttpxApiClient(
"https://api.example.com", request_map=Request, response_map=Response
) as client:
result = await client.get("/users/{id}", params=GetUsersIdParams(id="u_1"))
if isinstance(result, ApiSuccess):
result.body # User; unknown paths, missing params, and wrong models are static errors
Generated modules that use non-object intersections inline a small all_of validator, so they depend only on pydantic and alt-stack-http-client-httpx at runtime.
Branded types
Annotate an identity schema in OpenAPI:
{ "type": "string", "format": "uuid", "x-altstack-brand": "UserId" }
The generated module declares UserId = NewType("UserId", UUID) once and uses it
in field and parameter annotations. Pydantic still parses UUID strings into UUID
values and applies each use's existing constraints. Optional and nullable fields,
references, array items, and union members retain the nominal type.
Names must be ASCII identifiers ([A-Za-z_][A-Za-z0-9_]*) and must not be Python
keywords, imported helper names, or unrelated component names. Conflicting base
types produce a generation error. If a component and its brand have the same name,
the Pydantic wrapper is named UserIdModel, leaving UserId for the NewType.
Python requires a class as a NewType base. Literal brands use their primitive
base; composite unions use object with the original Pydantic validator retained
in Annotated metadata.
Development
uv run --project packages/python-pydantic-openapi --extra dev pytest packages/python-pydantic-openapi/tests
uv run --project packages/python-pydantic-openapi --extra dev ruff check packages/python-pydantic-openapi
uv run --project packages/python-pydantic-openapi --extra dev ty check packages/python-pydantic-openapi
Documentation
Metadata
Release files for alt-stack-openapi-pydantic 1.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| alt_stack_openapi_pydantic-1.7.0.tar.gz | 41.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| alt_stack_openapi_pydantic-1.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 72.9 kB
Release files / alt_stack_openapi_pydantic-1.7.0.tar.gz
| Download URL | alt_stack_openapi_pydantic-1.7.0.tar.gz |
|---|---|
| Size | 41.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
11d467da4e8f286a40b7b09cbefb1c32a5bbf42ecfe74e7a70e82f849f3c864b
|
|
BLAKE2b-256 checksum How to use checksums |
451e77c4c5a51ef9aee518151a55e1839bc82b9554aaed98ea7a4d9e256f9f4a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / alt_stack_openapi_pydantic-1.7.0-py3-none-any.whl
| Download URL | alt_stack_openapi_pydantic-1.7.0-py3-none-any.whl |
|---|---|
| Size | 31.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
47a13a212bbebee66b46a80787dd9868636713bd77945c4b9845475834e042a9
|
|
BLAKE2b-256 checksum How to use checksums |
a30548a62a59ec445dfe9677bd337fe09390e36534fa07eb9cc4a0c2e7257807
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency log