Skip to main content

Sillo

Sillo logo

Python With the Pieces Already in Place.

Tests Coverage Type check Lint

PyPI Python versions PEP 561 typed Ruff License

Sillo is an async Python web framework for APIs, web applications, real-time systems, and business backends. The language does not change. You write the same Python, with the same type hints and the same async/await. What changes is how much is waiting for you when you start: routing, request validation, dependency injection, middleware, sessions, authentication, records, background work, WebSockets, OpenAPI, and testing are first-party modules sharing one configuration model.

Each of those is a solved problem with good packages behind it. The work that remains is the fitting, and that is what Sillo does once so you do not do it per project. One auth= declaration gates a route and writes its securityScheme into the OpenAPI spec. The queue and the scheduler start with the application lifecycle. Range requests, ETags, and content negotiation are middleware rather than something each project rewrites.

Project Health

Tests 4,746 passing with none skipped, on CPython 3.10 through 3.14. Python 3.15 is in the matrix too and passes, but is not claimed on PyPI until it ships final
Coverage 91%, with a 90% floor enforced in CI before anything is published
Types Ships py.typed, so your own checker sees Sillo's annotations rather than Any
Type check ty clean across the package
Lint and format ruff clean, checked on every push
Dependencies Seven at install time. The other 14 feature groups are opt-in extras
License BSD-3-Clause

None of this is aspirational. The coverage floor fails the build rather than printing a warning, the type check runs on every supported Python, and the badges above read from those same workflows rather than from a number written here by hand.

Requirements

  • Python 3.10+
  • uv for project and dependency management

Installation

uv add sillo-framework

For optional feature groups:

uv add "sillo-framework[templating]"
uv add "sillo-framework[jwt]"
uv add "sillo-framework[cache]"
uv add "sillo-framework[record]"
uv add "sillo-framework[graphql]"

For a full development setup:

uv add "sillo-framework[all]"

Hello World

from sillo import SilloApp

app = SilloApp(title="My API")


@app.get("/")
async def home(request, response):
    return response.json({"message": "Hello from Sillo"})

Run it with Sillo's own server:

uv run sillo serve --reload
  ● sillo 0.2.0

    app       main:app
    url       http://127.0.0.1:8000
    routes    4
    inspect   http://127.0.0.1:8000/__sillo/requests
    mode      serving
    pid       5716

    ready in 7ms  ·  press ctrl-c to stop

  22:48:04  GET     200  /                                      409us

No import string is needed. sillo serve looks for app.main:app, main:app and app:app, and you can pin it with the SILLO_APP environment variable or a [tool.sillo] app entry in pyproject.toml. Pass one explicitly when you want something else:

uv run sillo serve api.main:app --port 9000 --workers 4

Each request is logged with the time it took, and the address in the inspect line is a clickable request log you can open while developing. Add --no-inspect to leave it out, or --plain to see the underlying server's own output instead.

sillo serve is built for development. For production, run the application under a process supervisor with a reverse proxy in front of it.

Request Validation

Sillo validates request bodies with Pydantic through request_model.

from pydantic import BaseModel
from sillo import SilloApp

app = SilloApp()


class CreateUser(BaseModel):
    name: str
    email: str


@app.post("/users", request_model=CreateUser)
async def create_user(request, response, user: CreateUser):
    return response.json(user.model_dump(), status_code=201)

The validated model is also available as request.validated_data.

Dependency Injection

Use Depend to inject request-scoped dependencies into handlers.

from sillo import Depend, SilloApp

app = SilloApp()


async def get_current_user():
    return {"id": "user_1", "name": "Ada"}


@app.get("/me")
async def me(request, response, user=Depend(get_current_user)):
    return response.json(user)

When a dependency needs the current request:

from sillo import Depend


def auth_header(request=Depend(get_request=True)):
    return request.headers.get("Authorization")

Routing

from sillo import Router, SilloApp

app = SilloApp()
api = Router(prefix="/api")


@api.get("/users/{user_id:int}")
async def get_user(request, response, user_id: int):
    return response.json({"id": user_id})


app.mount_router(api)

What Sillo Provides

  • Async ASGI application core
  • HTTP routing, route groups, and mounted routers
  • Request and response helpers
  • Pydantic request validation
  • Dependency injection with nested dependencies
  • Query, header, and cookie parameter helpers
  • Middleware pipeline
  • CORS and CSRF support
  • Sessions and authentication utilities
  • API keys, JWT helpers, users, permissions, and guards
  • OpenAPI generation and interactive docs
  • File uploads, streaming responses, static files, and frontend fallback serving
  • WebSockets, consumers, channels, groups, events, and history helpers
  • Cache abstraction with memory and Redis support
  • Event system and background work primitives
  • Record layer for database-backed models, transactions, scopes, casting, and pagination
  • Mail service utilities
  • Sync and async test clients
  • Model admin at /admin/ that authenticates against your own user model
  • sillo command, and sillo.console for building a project's own

Scope And Boundaries

Sillo runs on its own. No hosted service is required to put an application into production.

The framework is opinionated at the defaults and open at the boundaries. Auth backends, middleware, cache drivers, session stores, and hashing algorithms are contracts you can implement yourself, and anything the framework does on your behalf is something you can read, override, or replace.

Sillo ships a sillo command with the framework-level operations, built on sillo.console. Inside a project it also merges in whatever that project's console.py registers, so sillo db:migrate works without the framework owning the command set. The operations underneath stay plain functions in sillo.record.commands, sillo.users.commands and sillo.work.commands, so a project that wants different names writes its own console against them.

Documentation

The documentation source lives in docs/docs.

Build it locally with:

cd docs/docs
bun run build

Testing

Run the core test suite with:

python3 -m pytest -q

Some optional integrations require their extras to be installed before their tests can run.

Release Principles

Sillo prioritizes:

  • clear APIs and useful error messages
  • strong defaults with replaceable internals
  • production-oriented documentation
  • compatibility, migration guidance, and honest release notes
  • security and reliability before broad platform expansion

License

BSD-3-Clause

Metadata

Release files for sillo-framework 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sillo-framework 0.2.1
File Size Uploaded
sillo_framework-0.2.1.tar.gz 4.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for sillo-framework 0.2.1
File Interpreter ABI Platform
sillo_framework-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 5.2 MB

Release files / sillo_framework-0.2.1.tar.gz

Download URL sillo_framework-0.2.1.tar.gz
Size 4.2 MB
Tags Source
SHA-256 checksum
How to use checksums
8b79e65078db300819f8bf0b469ec2d0b036b9cb3f6d5eb8b14a92d57031d9d7
BLAKE2b-256 checksum
How to use checksums
4542233a9e882a5cab6013effa18b83e1cf79d0bee5c05cb0c35366b23a214dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / sillo_framework-0.2.1-py3-none-any.whl

Download URL sillo_framework-0.2.1-py3-none-any.whl
Size 969.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f4d03414723498b16f903916f13ce99a56477b688a0ccfeca9d8896f67dca8c0
BLAKE2b-256 checksum
How to use checksums
d292246416afea02c86e5e749d8a6271e18326578969a19686d6430660a8197a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page