Metadata-Version: 2.4
Name: alt-stack-openapi-pydantic
Version: 1.6.3
Summary: Generate Pydantic models, typed route maps, and an asyncio client from OpenAPI
License-Expression: MIT
Project-URL: Homepage, https://github.com/anthonyaltieri/alt-stack
Project-URL: Repository, https://github.com/anthonyaltieri/alt-stack
Project-URL: Issues, https://github.com/anthonyaltieri/alt-stack/issues
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic[email]>=2.7.0
Provides-Extra: dev
Requires-Dist: alt-stack-http-client-httpx; extra == "dev"
Requires-Dist: pyrefly>=1.0.0; extra == "dev"
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: ruff>=0.6.0; extra == "dev"
Requires-Dist: ty>=0.0.78; extra == "dev"
Dynamic: license-file

# `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

```bash
python -m pip install alt-stack-openapi-pydantic
```

Consumers of a generated SDK install the runtime package instead:

```bash
python -m pip install alt-stack-http-client-httpx
```

## Generate

```bash
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.

```python
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:

```python
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`:

```python
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.

## Development

```bash
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

- [Code generation Quickstart](../../apps/docs/docs/codegen/quickstart.md)
- [Common Patterns](../../apps/docs/docs/codegen/common-patterns.md)
- [Python/Pydantic API Documentation](../../apps/docs/docs/codegen/api/pydantic-openapi.md)
