Metadata-Version: 2.4
Name: nitro-framework
Version: 0.1.0
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Rust
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Dist: jinja2>=3.1.0
Requires-Dist: aiofiles>=25.1.0
Requires-Dist: aiosmtplib>=5.1.2
Requires-Dist: click>=8.4
Requires-Dist: orjson>=3.11
Requires-Dist: python-multipart>=0.0.32
Requires-Dist: regex>=2026.7.19
Requires-Dist: aioboto3>=15.5.0 ; extra == 'all'
Requires-Dist: authlib>=1.7.2 ; extra == 'all'
Requires-Dist: azure-storage-blob>=12.30.0 ; extra == 'all'
Requires-Dist: emcache>=1.3.3 ; python_full_version < '3.14' and extra == 'all'
Requires-Dist: httpx>=0.28.1 ; extra == 'all'
Requires-Dist: redis[hiredis]>=8.0.0 ; extra == 'all'
Requires-Dist: sendgrid>=6.12.5 ; extra == 'all'
Requires-Dist: aioboto3>=15.5.0 ; extra == 'aws'
Requires-Dist: azure-storage-blob>=12.30.0 ; extra == 'azure'
Requires-Dist: uvloop>=0.21 ; extra == 'benchmark'
Requires-Dist: httpx>=0.28.1 ; extra == 'benchmark'
Requires-Dist: pytest>=9 ; extra == 'dev'
Requires-Dist: ruff>=0.16 ; extra == 'dev'
Requires-Dist: pytest-asyncio>=1.0 ; extra == 'dev'
Requires-Dist: pytest-timeout>=2.4 ; extra == 'dev'
Requires-Dist: cryptography>=50.0.0 ; extra == 'dev'
Requires-Dist: websockets>=15 ; extra == 'dev'
Requires-Dist: aioquic>=1.3 ; extra == 'dev'
Requires-Dist: authlib>=1.7.2 ; extra == 'email-oauth'
Requires-Dist: emcache>=1.3.3 ; python_full_version < '3.14' and extra == 'memcached'
Requires-Dist: redis[hiredis]>=8.0.0 ; extra == 'redis'
Requires-Dist: sendgrid>=6.12.5 ; extra == 'sendgrid'
Requires-Dist: httpx>=0.28.1 ; extra == 'sendgrid'
Provides-Extra: all
Provides-Extra: aws
Provides-Extra: azure
Provides-Extra: benchmark
Provides-Extra: dev
Provides-Extra: email-oauth
Provides-Extra: memcached
Provides-Extra: redis
Provides-Extra: sendgrid
License-File: LICENSE-MIT
License-File: LICENSE-APACHE
Summary: Async-first Python web framework with a bundled Rust server
Keywords: async,web,framework,http3,webtransport
Author-email: Mario Ritzerfeld <oss@jaldis.com>
License-Expression: MIT OR Apache-2.0
Requires-Python: >=3.13
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/jaldisdev/nitro/blob/canary/CHANGELOG.md
Project-URL: Documentation, https://github.com/jaldisdev/nitro/blob/canary/docs/overview.md
Project-URL: Homepage, https://github.com/jaldisdev/nitro
Project-URL: Issues, https://github.com/jaldisdev/nitro/issues
Project-URL: Repository, https://github.com/jaldisdev/nitro

# Nitro

An async-first Python web framework with its server compiled in.

```python
# routes.py
from nitro.routing import HTTPRoute
from nitro.protocols import HttpRequest, HttpResponse, JSONResponse


async def show_user(request: HttpRequest, user_id: int) -> HttpResponse:
    return JSONResponse({"id": user_id, "name": "Ada"})


patterns = [
    HTTPRoute("/users/<int:user_id>", show_user, name="user"),
]
```

```python
# app.py
from nitro import Nitro

app = Nitro(routes="routes")
```

```sh
nitro app:app
```

A project usually points the `ROUTES` setting at its route module rather than
naming it here. Handlers can also be registered on the application directly with
`@app.route(...)`.

## Installation

```sh
pip install nitro-framework
```

Python 3.13 or newer. The distribution is named `nitro-framework`; the package
it installs is `nitro`, which is what you import. The wheel carries the compiled
server, so there is nothing to build.

Extras pull in the clients particular backends need:

```sh
pip install "nitro-framework[redis]"
```

`aws`, `azure`, `email-oauth`, `memcached`, `redis`, `sendgrid`, and `all`.

`nitro-intercom` is published from this repository too, from the same tag and at
the same version, so either package at a given version was built from the same
source. A Nitro project does not install it — see
[docs/intercom.md](docs/intercom.md).

## Not an ASGI framework

Nitro does not implement ASGI and does not ship an adapter for it. The server —
HTTP/1.1, HTTP/2, HTTP/3, WebSocket and WebTransport — is part of the package
and calls your application directly.

That is a design choice rather than an omission. An intermediate protocol limits
a server to what the protocol can express and charges every request for a
translation into dictionaries and callables. Removing it is what lets routing,
header handling, file serving, range requests and streaming backpressure live in
compiled code while handlers stay ordinary Python coroutines.

The trade is worth stating plainly: a Nitro application runs on the Nitro
server. It cannot be deployed under Uvicorn or Hypercorn, and it cannot mount an
ASGI application inside itself.

## Documentation

Start with [the overview](docs/overview.md).

| | |
|---|---|
| [Routing](docs/routing.md) | Paths, converters, mounting, reversing |
| [Requests and responses](docs/protocols.md) | Reading a request, sending files and streams |
| [WebSocket and WebTransport](docs/realtime.md) | Real-time connections |
| [Intercom](docs/intercom.md) | Publish/subscribe between connections |
| [Settings](docs/settings.md) | Configuration, including the server's own |
| [Dependency injection](docs/di.md) | `Depends`, and why its cache is per request |
| [Middleware](docs/middleware.md) | Wrapping handlers |
| [Sessions](docs/sessions.md) | Server-side state, and the origin check that guards it |
| [Caching](docs/cache.md) · [Storage](docs/storage.md) · [Templates](docs/templates.md) · [Mail](docs/mail.md) | Batteries |
| [Observability](docs/observability.md) | Prometheus metrics |
| [Command line](docs/cli.md) | Serving, `check`, `shell` |
| [Deployment](docs/deployment.md) | Workers, TLS, HTTP/3, draining |

## Layout

| Path | Contents |
|---|---|
| `nitro/` | The framework |
| `nitro-intercom/` | Standalone publish/subscribe client for non-Nitro services |
| `crates/nitro-core/` | Transport, lifecycle and routing — pure Rust, no interpreter |
| `crates/nitro-observability/` | Prometheus metrics and the exporter — pure Rust, no interpreter |
| `crates/nitro-py/` | Python bindings for the server (`nitro._nitro`) |
| `crates/intercom-core/` | Publish/subscribe channels — pure Rust, no interpreter |
| `crates/intercom-py/` | Python bindings for Intercom (`nitro_intercom._intercom`) |

The two core crates know nothing about Python. Everything that needs an
interpreter goes through a trait the binding crate implements, which is what
keeps the whole request path testable without one.

## Development

```sh
python -m venv .venv && . .venv/bin/activate
pip install maturin
maturin develop --extras dev          # builds the extension into the venv
```

```sh
cargo test --workspace                # Rust
pytest                                # Python
(cd nitro-intercom && pytest)         # the standalone package
```

Tests that need Redis skip when there is not one reachable at
`127.0.0.1:6379`, so a checkout without it still runs green.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get set up and what CI will
check. Security issues go to [SECURITY.md](SECURITY.md) rather than the issue
tracker. Changes worth knowing about are in [CHANGELOG.md](CHANGELOG.md).

## License

Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or the
[MIT license](LICENSE-MIT), at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you shall be dual licensed as above, without
any additional terms or conditions.

Copyright 2026 Jaldis B.V.

