Metadata-Version: 2.4
Name: ryne
Version: 0.4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Rust
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Dist: maturin>=1.7 ; extra == 'dev'
Requires-Dist: pytest>=8 ; extra == 'dev'
Requires-Dist: httpx>=0.27 ; extra == 'dev'
Requires-Dist: psutil>=5.9 ; extra == 'dev'
Requires-Dist: watchfiles>=0.21 ; extra == 'dev'
Requires-Dist: ruff>=0.6 ; extra == 'dev'
Requires-Dist: jinja2>=3.1 ; extra == 'templates'
Requires-Dist: httpx>=0.27 ; extra == 'test'
Requires-Dist: websockets>=12 ; extra == 'test'
Provides-Extra: dev
Provides-Extra: templates
Provides-Extra: test
License-File: LICENSE
Summary: Fast, secure, full-stack Python backend framework with a native Rust core
Keywords: web,framework,backend,rust,http,orm,async
Author: RYNE contributors
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/ryne-framework/ryne/blob/main/CHANGELOG.md
Project-URL: Homepage, https://github.com/ryne-framework/ryne
Project-URL: Issues, https://github.com/ryne-framework/ryne/issues
Project-URL: Repository, https://github.com/ryne-framework/ryne

# RYNE

<p align="center">
  <a href="https://pypi.org/project/ryne/"><img src="https://img.shields.io/pypi/v/ryne?color=f59e0b" alt="PyPI version"></a>
  <a href="https://pypi.org/project/ryne/"><img src="https://img.shields.io/pypi/pyversions/ryne" alt="Python versions"></a>
  <a href="https://github.com/ryne-framework/ryne/actions/workflows/ci.yml"><img src="https://github.com/ryne-framework/ryne/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://pypi.org/project/ryne/"><img src="https://img.shields.io/pypi/l/ryne" alt="License"></a>
</p>

**Fast, secure, full-stack Python backend framework with a native Rust core.**

Write your entire application in pure Python. RYNE runs the HTTP server
(HTTP/1.1 + HTTP/2, native TLS), routing, JSON, validation, the SQLite
driver and cryptography in compiled Rust — and installing it never requires
a Rust toolchain:

```bash
pip install ryne
```

<p align="center">
  <img src="https://raw.githubusercontent.com/ryne-framework/ryne/main/docs/benchmarks/benchmark_rps_python.png" alt="RYNE vs Python web frameworks: RPS by scenario" width="780">
</p>

## Why RYNE

| Goal | How RYNE delivers it |
|---|---|
| **Python-only install** | Prebuilt wheels (CPython 3.10+, Windows / Linux / macOS, abi3) bundle the Rust core via PyO3. |
| **Native Rust core** | hyper + tokio event loop, trie router, JSON, schema validation, SQLite and argon2 — all native. |
| **Developer experience** | Django-style models, migrations, decorators, a CLI with hot reload, and a built-in test client. No Rust knowledge needed, ever. |
| **Full-stack** | REST API, WebSockets, Jinja2 templates, static files, uploads, ORM, migrations, authentication, revocable sessions, CORS — admin panel and PostgreSQL on the roadmap. |
| **Performance-first** | Rust owns the socket, serializes responses, serves statics and runs WebSockets; Python is invoked exactly once per request. |
| **Security-first** | Native TLS (rustls), rate limiting, backpressure, signed CSRF, revocable sessions, argon2id, parameterized SQL, request IDs and access logs — safe defaults everywhere. |

## Benchmarks

11 frameworks × 6 scenarios × 60 seconds per test, `oha` load generator,
50 concurrent connections, identical endpoints and payloads
([full methodology and complete tables](BENCHMARKS.md)).

| scenario | RYNE | Sanic | Starlette | Litestar | FastAPI | Flask | Django |
|---|---|---|---|---|---|---|---|
| json | **30 636** | 14 532 | 9 180 | 8 059 | 5 629 | 3 942 | 1 578 |
| plaintext | **27 829** | 12 881 | 9 098 | 7 546 | 6 447 | 4 281 | 925 |
| router | **27 472** | 10 984 | 8 168 | 6 861 | 4 641 | 3 995 | 988 |
| http | **22 333** | 12 506 | 7 347 | 6 159 | 4 316 | 3 929 | 1 281 |
| db (SQLite) | **7 348** | 2 162 | 2 104 | 2 520 | 1 625 | 1 488 | 1 323 |
| validation | **17 066** | 9 640 | 6 516 | 5 366 | 4 503 | 3 621 | 1 004 |
| **peak RAM (db)** | **38 MB** | 79 MB | 73 MB | 204 MB | 87 MB | 115 MB | 125 MB |

<p align="center">
  <img src="https://raw.githubusercontent.com/ryne-framework/ryne/main/docs/benchmarks/benchmark_latency.png" alt="Latency percentiles: RYNE has the lowest p50/p95/p99 among Python frameworks" width="780">
</p>

**How to read this.** RYNE is the fastest full-featured Python framework in
*all six* scenarios — 1.9–2.7× ahead of the runner-up (Sanic), 3.5–5.4×
ahead of FastAPI, 7–30× ahead of Flask and Django — while using the least
memory (now with WebSockets, templates, statics and uploads built in). Native Rust frameworks (Actix, Axum, Hyper, Rocket) are still
3–6× faster than RYNE: that is the honest price of running *user code* in
Python, and the trade-off RYNE makes to stay a pure-Python framework.

## Quickstart

```bash
pip install ryne
ryne startproject mysite
cd mysite
ryne makemigrations && ryne migrate
ryne run --reload
```

Or in a single file:

```python
from ryne import Ryne

app = Ryne()

@app.get("/hello/{name}")
async def hello(request, name: str):
    return {"message": f"Hello, {name}!"}

app.run()   # ryne run hello:app
```

## The full stack

### Validation — compiled to Rust at import time

```python
import enum
from ryne import HTTPException
from ryne.validation import Schema, Str, Int, List, Enum, Object

class Color(enum.Enum):
    RED = "red"
    BLUE = "blue"

class Address(Schema):
    city: Str(max_length=80)

class CreateArticle(Schema):
    title: Str(min_length=1, max_length=200)
    tags: List(Str(), max_items=10) = []
    views: Int(ge=0) = 0
    color: Enum(Color)                  # -> Color.RED member on output
    author: Object(nested=Address)      # nested schema
    nickname: Str(max_length=30) = None # optional + nullable

@app.post("/articles")
async def create_article(request):
    data = CreateArticle.validate_body(request)  # parse+validate in Rust, GIL-free
    ...
```

### ORM + migrations — Django-style

```python
from ryne.models import Model, CharField, IntField, ForeignKey

class Article(Model):
    title = CharField(max_length=200)
    views = IntField(default=0)
    author = ForeignKey(Author, null=True)

article = await Article.objects.create(title="Hi")
articles = await Article.objects.filter(views__gte=1).order_by("-id").limit(10)
```

```bash
ryne makemigrations   # schema diff -> reviewable Python migration files
ryne migrate          # applied atomically, recorded in ryne_migrations
```

SQLite ships compiled inside the wheel: WAL mode, a read connection pool and
a single serialized writer connection (in-process writes never fight over
SQLite's one-writer lock). The GIL is released during every query.
PostgreSQL is planned.

### Auth & revocable sessions

```python
from ryne.auth import authenticate, login, logout, logout_all, get_user, requires_login

@app.post("/login")
async def login_route(request):
    user = await authenticate(request.json()["username"], request.json()["password"])
    if user is None:
        raise HTTPException(401)
    await login(request, user)      # rotates the server-side session id
    return {"ok": True}

@app.post("/logout")
async def logout_route(request):
    await logout(request)           # revokes it server-side
    return {"ok": True}

@app.get("/me")
@requires_login
async def me(request):
    return {"user": (await get_user(request)).username}
```

Sessions are signed cookies (HMAC-SHA256, constant-time verification in
Rust) backed by a server-side registry: `login` rotates the session id, so
stolen pre-auth cookies are useless; `logout` revokes; `logout_all(user_id)`
kills every session of a user. Passwords are hashed with argon2id in native
code; unknown usernames cost the same as known ones (no timing oracle).

### Security defaults

- **Native TLS** (rustls, HTTP/2 via ALPN): `ryne run --tls-cert C --tls-key K`
- `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`,
  `Permissions-Policy`, `COOP` on every response (opt-in HSTS and CSP)
- **Signed CSRF tokens** for form submissions (JSON APIs unaffected)
- **Per-IP rate limiting** (sharded token bucket in Rust) → `429` + `Retry-After`
- **Backpressure**: `max_inflight` caps concurrent dispatches → instant `503`
- Slowloris body timeout + connection cap
- 1 MiB request-body limit, enforced mid-stream in Rust
- `x-request-id` on every response, access log, tracebacks in debug
- `DEBUG=False` by default — unexpected errors never leak internals
- Trusted-proxy aware client IPs (`trusted_proxies`)

For blocking sync workloads: `settings.sync_pool = True` runs sync handlers
on a bounded blocking executor (`sync_pool_size`, default 64) so a slow
handler can never starve the async runtime.

### WebSockets, templates, statics — the full stack

```python
@app.websocket("/ws/{room}")
async def chat(ws, room: str):
    async for message in ws:
        await ws.send_text(f"{room}: {message}")

@app.get("/")
async def page(request):
    return app.render(request, "index.html", posts=posts)   # Jinja2

app.mount_static("/static/", "static")                      # served by Rust
```

Origin-checked handshakes, RFC 6455 framing, multipart uploads
(`request.files`) and typed route params (`{id:int}`) are all built in.

### Testing

```python
from ryne.test import TestClient

def test_hello():
    with TestClient(app) as client:
        assert client.get("/hello/world").json() == {"message": "Hello, world!"}
```

The real server (hyper, sessions, CSRF, limits) on an ephemeral port —
`pip install ryne[test]`.

### CLI

```
ryne startproject <name>     scaffold a project
ryne run [module:app]        run the server (--reload, --host, --port,
                             --debug, --tls-cert/--tls-key)
ryne makemigrations [--name] generate a migration from model changes
ryne migrate                 apply pending migrations
ryne createsuperuser         create an admin user
ryne shell [module:app]      interactive shell with your app loaded
ryne check [module:app]      validate configuration
```

## Documentation

Full guides live in [docs/](docs/): [quickstart](docs/quickstart.md),
[tutorial](docs/tutorial.md), [validation](docs/validation.md),
[websockets](docs/websockets.md), [templates](docs/templates.md),
[static and uploads](docs/static-and-uploads.md),
[ORM and migrations](docs/orm.md), [auth and sessions](docs/auth.md),
[security](docs/security.md) (TLS deployment + hardening checklist),
[testing](docs/testing.md), [configuration reference](docs/configuration.md)
and [performance](docs/performance.md). Runnable examples in
[examples/](examples/) — including a WebSocket chat and a templates demo.

## Development

```bash
python -m venv .venv && .venv/Scripts/pip install -e '.[dev]'
python -m maturin develop     # build the Rust core into the venv
python -m pytest              # full test suite
cargo test --workspace        # Rust unit tests
python -m ruff check .        # lint
```

See [CHANGELOG.md](CHANGELOG.md) and the issue tracker for the roadmap
(admin panel, templates, WebSockets, PostgreSQL).

## License

MIT — see [LICENSE](LICENSE).

