A batteries-included web framework for Python — async-first, type-safe, modular.
Project description
arvel
The batteries-included, async-first web framework for Python — type-safe and modular.
Expressive facades, an Active-Record ORM, a real queue, auth, mail, caching, views and a
powerful CLI — one coherent, fully-typed, async/await-native toolkit. You get a productive,
high-level developer experience without giving up Python's type system or performance.
Install
uv add arvel # light core — no heavy dependencies
uv add 'arvel[standard]' # the common set: http, db, queue, cache, view, mail, image
uv add 'arvel[all]' # everything
Requires Python 3.14+. Capabilities are opt-in extras — you install only what you use,
and import arvel stays light because engines are imported lazily.
Quickstart
arvel new blog # scaffold a new app
cd blog && uv sync
source .venv/bin/activate # activate the virtualenv
arvel serve --reload # http://127.0.0.1:8000
arvel new gives you a runnable project: an ASGI entrypoint, a bootstrap/app.py factory, web/api
route groups, config files, a User model with migrations and a factory, and a test suite.
A taste
Routing — define routes with the Route facade; web (stateful) and api (JSON) groups:
from arvel import Route, Schema
async def show(request):
return {"hello": request.path_param("name")}
Route.get("/hello/{name}", show, name="hello")
class CreatePost(Schema): # typed request/response → automatic OpenAPI at /schema
title: str
async def store(request, data: CreatePost) -> CreatePost:
return data
Route.post("/posts", store, name="posts.store")
ORM — an Active-Record model on SQLAlchemy Core:
from arvel import Model
class Post(Model):
__fillable__ = ["title", "body"]
__casts__ = {"published": "bool", "meta": "json"}
post = await Post.create(title="Hello", body="…")
posts = await Post.where("published", True).order_by("created_at", "desc").get()
await Post.with_("author").get() # eager-load relations — no N+1
Validation — concise rules, returning only the validated data:
from arvel import Validator
data = Validator(request_body, {
"email": "required|email",
"age": "nullable|integer|min:18",
}).validate()
Queues, authorization, mail, cache — the facades you'd expect, all async:
from arvel import Job, Gate, Mail, Cache
await SendWelcome.dispatch(user_id=42) # background job
await SendWelcome.dispatch_after(600, user_id=42) # …or run it in 10 minutes
if await Gate.allows("update", post): ... # authorization
await Mail.to(user).send(WelcomeMail()) # mailables
await Cache.remember("stats", 300, compute_stats) # cache-aside
More: notifications, events & listeners, task scheduling, file storage (local/S3/GCS/Azure),
localization, server-rendered views, and a rich Str/Arr/Collection helper set.
Why arvel
- Batteries included, async-first. Routing, ORM, queue, cache, auth, mail, views, CLI — one
coherent DX, built
async/await-native from the ground up. - Type-safe. Strict typing across the public API, so your editor and CI catch mistakes before runtime — no stub-chasing.
- Lightweight & modular. One package, opt-in extras, lazy imports. You pay only for what you use, and the CLI stays fast.
- Convention over configuration. Sensible defaults, expressive facades, and a familiar project layout — scaffold and ship without wiring boilerplate.
The four gates
Engineering guarantees enforced in CI from the first commit:
- G1 — boundaries.
import-linterkeeps modules honest: kernel isolation, a layered DAG, and no heavy import at module load. - G2 — startup.
import arvelpulls zero heavy libraries; the CLI stays snappy. - G3 — types. Strict
mypyandpyrighton every public API. - G4 — stack fidelity. Each capability is built on its mandated engine (Litestar, SQLAlchemy Core, whenever, Typer, …) — verified by a per-module test.
Extras
| Extra | Adds |
|---|---|
http, server |
Litestar routing · the granian/uvicorn dev server |
sqlite, postgres, mysql |
SQLAlchemy + the matching async driver + Alembic |
queue, queue-redis, queue-amqp |
taskiq jobs · Redis broker · RabbitMQ/AMQP broker |
redis |
cashews caching (Redis backend) |
jwt, oauth, 2fa |
JWT tokens · OAuth providers · TOTP two-factor (auth is core) |
mail, notifications |
SMTP mail · multi-channel notifications (Apprise) |
view |
Jinja2 templating |
s3, gcs, azure, supabase |
filesystem disks |
image, video, media |
media handling (Pillow / PyAV) |
search, vector |
Meilisearch · pgvector |
i18n, telemetry |
Babel localization · OpenTelemetry/Sentry |
arvel[standard] bundles the everyday set; arvel[all] installs everything.
Development
uv venv && uv pip install -e '.[dev]'
./tools/validate.sh # ruff · mypy · pyright · import-linter · bandit · pip-audit · pytest
Inspired by
If you're coming from PHP, arvel will feel familiar: facades, the service container, providers, migrations, factories, gates & policies, and a project layout are all here. Arvel is built natively for async Python, embraces the type system end to end, and stands on best-in-class Python engines (Litestar · SQLAlchemy Core · Alembic · whenever · Typer · taskiq · Babel · msgspec · cashews · fsspec · Jinja2).
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arvel-0.63.1.tar.gz.
File metadata
- Download URL: arvel-0.63.1.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
44bc0eb6f1811820eb459e7f53ff5d9e5c228736196c4fdf51c9984a28297b58
|
|
| MD5 |
daa8bb595288d1dd206919a7289af7da
|
|
| BLAKE2b-256 |
49008a1d74742c80ae4954484113f98152109b143d0a418c5c0797dbde335e2c
|
Provenance
The following attestation bundles were made for arvel-0.63.1.tar.gz:
Publisher:
publish.yml on mohamed-rekiba/arvel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arvel-0.63.1.tar.gz -
Subject digest:
44bc0eb6f1811820eb459e7f53ff5d9e5c228736196c4fdf51c9984a28297b58 - Sigstore transparency entry: 2152288966
- Sigstore integration time:
-
Permalink:
mohamed-rekiba/arvel@4f56c41b3c59208c6449d61623251bd2ebfa2344 -
Branch / Tag:
refs/tags/v0.63.1 - Owner: https://github.com/mohamed-rekiba
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4f56c41b3c59208c6449d61623251bd2ebfa2344 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file arvel-0.63.1-py3-none-any.whl.
File metadata
- Download URL: arvel-0.63.1-py3-none-any.whl
- Upload date:
- Size: 578.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
628808a7f8543853058dff9ea89bc4bb91cb6f6fd619a199f6b6feea9b9cfc62
|
|
| MD5 |
3df89341b901ebdbd01b78cc55706e64
|
|
| BLAKE2b-256 |
3e59c2cf9011ba1600a0e311a4a08f5a3e04b3cb3dac0a4704aee2b3f7638416
|
Provenance
The following attestation bundles were made for arvel-0.63.1-py3-none-any.whl:
Publisher:
publish.yml on mohamed-rekiba/arvel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arvel-0.63.1-py3-none-any.whl -
Subject digest:
628808a7f8543853058dff9ea89bc4bb91cb6f6fd619a199f6b6feea9b9cfc62 - Sigstore transparency entry: 2152288979
- Sigstore integration time:
-
Permalink:
mohamed-rekiba/arvel@4f56c41b3c59208c6449d61623251bd2ebfa2344 -
Branch / Tag:
refs/tags/v0.63.1 - Owner: https://github.com/mohamed-rekiba
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4f56c41b3c59208c6449d61623251bd2ebfa2344 -
Trigger Event:
workflow_dispatch
-
Statement type: