Metadata-Version: 2.4
Name: apiman
Version: 0.5.5
Summary: Integrate OpenAPI documentation and request validation into Python web applications
Author-email: strongbugman <strongbugman@gmail.com>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/strongbugman/apiman
Project-URL: Documentation, https://strongbugman.github.io/apiman/
Project-URL: Repository, https://github.com/strongbugman/apiman
Project-URL: Issues, https://github.com/strongbugman/apiman/issues
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyYAML>=6.0
Requires-Dist: Jinja2>=3.0.2
Requires-Dist: jsonschema-rs<0.20,>=0.13.0
Requires-Dist: xmltodict>=0.13.0
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: pytest-cov>=3.0.0; extra == "test"
Requires-Dist: uvicorn>=0.15.0; extra == "test"
Requires-Dist: Flask<4,>=2.0.2; extra == "test"
Requires-Dist: starlette<0.28,>=0.16.0; extra == "test"
Requires-Dist: ruff>=0.1.0; extra == "test"
Requires-Dist: mypy>=0.910; extra == "test"
Requires-Dist: requests>=2.26.0; extra == "test"
Requires-Dist: types-PyYAML>=6.0.0; extra == "test"
Requires-Dist: Django<5,>=3.2; extra == "test"
Requires-Dist: bottle<0.13,>=0.12.0; extra == "test"
Requires-Dist: WebTest>=3.0.0; extra == "test"
Requires-Dist: tornado<7,>=6.0; extra == "test"
Requires-Dist: python-multipart>=0.0.5; extra == "test"
Requires-Dist: falcon<4,>=3.1.0; extra == "test"
Requires-Dist: gunicorn>=20.1.0; extra == "test"
Requires-Dist: httpx<0.28,>=0.23.1; extra == "test"
Requires-Dist: mkdocs-material>=8.2.3; extra == "test"
Dynamic: license-file

# APIMAN

[![Test and Release](https://github.com/strongbugman/apiman/actions/workflows/test-and-release.yml/badge.svg)](https://github.com/strongbugman/apiman/actions/workflows/test-and-release.yml)
[![PyPI version](https://badge.fury.io/py/apiman.svg)](https://pypi.org/project/apiman/)
[![Codecov coverage](https://codecov.io/gh/strongbugman/apiman/branch/master/graph/badge.svg)](https://codecov.io/gh/strongbugman/apiman)
[![Python support](https://img.shields.io/pypi/pyversions/apiman.svg)](https://pypi.org/project/apiman/)
[![License](https://img.shields.io/github/license/strongbugman/apiman)](LICENSE)

**APIMAN** integrates OpenAPI documentation and schema-based request validation into Python web applications without requiring a framework rewrite.

## Features

- Integrations for **Starlette, Flask, Django, Bottle, Tornado, and Falcon**
- OpenAPI 2.0, OpenAPI 3.0.x, and OpenAPI 3.1.x specification validation
- Built-in Swagger UI and ReDoc endpoints
- Specifications from docstrings, YAML strings, dictionaries, YAML files, or JSON files
- Validation for query, header, cookie, path, JSON, XML, and form request data
- Synchronous and asynchronous validation APIs

## Installation

```bash
pip install -U apiman
```

Install the web framework you use separately, for example:

```bash
pip install starlette uvicorn
```

## Quick start

```python
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import JSONResponse

from apiman.starlette import Apiman

app = Starlette()
apiman = Apiman()
apiman.init_app(app)


@app.route("/hello", methods=["GET"])
async def hello(request: Request):
    """
    summary: Say hello
    parameters:
      - name: name
        in: query
        required: true
        schema:
          type: string
    responses:
      "200":
        description: Successful response
    """
    apiman.validate_request(request)
    return JSONResponse({"message": f"Hello, {request.query_params['name']}!"})
```

Run the application and open:

- Swagger UI: `http://localhost:8000/apiman/swagger/`
- ReDoc: `http://localhost:8000/apiman/redoc/`
- OpenAPI document: `http://localhost:8000/apiman/specification/`

## Documentation

The full guide covers framework setup, specification sources, reusable schemas, request validation, and project maintenance:

**[APIMAN documentation](https://strongbugman.github.io/apiman/)**

The documentation can also be built locally:

```bash
make docs
```

## Development

APIMAN supports Python 3.9 through 3.12. This project uses [uv](https://docs.astral.sh/uv/) and Ruff:

```bash
make install   # create/sync .venv
make lint      # Ruff + mypy
make test      # lint + tests + coverage
make test-all  # Python 3.9-3.12 via Nox
make docs      # strict MkDocs build
make build     # sdist and wheel
```

`make format` rewrites Python files and is intentionally separate from the read-only quality checks.

## Compatibility Notes

APIMAN validates assembled specifications with bundled OpenAPI 2.0, 3.0.x, and 3.1.x schemas. Header parameter names are matched case-insensitively; query, cookie, and path parameter names remain case-sensitive.

Request validation supports JSON, XML, form, query, header, cookie, and path inputs. Repeated query and form values are accepted for array schemas. Repeated values for scalar schemas remain invalid.

Use `apiman.reset()` to clear collected route/schema caches and `apiman.reload(...)` to clear caches and collect routes again through the active framework adapter.

The built-in Swagger UI and ReDoc templates use pinned jsDelivr CDN versions, not `@latest`. Serving those endpoints requires browser access to jsDelivr unless you customize the templates to serve local assets.

## License

APIMAN is licensed under the [BSD 3-Clause License](LICENSE).
