Metadata-Version: 2.5
Name: sillo-framework
Version: 0.1.0b2
Summary: Python with the pieces already in place: an async web framework whose ORM, auth, admin, queues, scheduler and WebSockets share one configuration model.
Project-URL: Homepage, https://github.com/sillohq/core
Project-URL: Repository, https://github.com/sillohq/core
Project-URL: Documentation, https://docs.sillo.build
Project-URL: Issues, https://github.com/sillohq/core/issues
Author-email: Chidebele Dunamis <techwithdunamix@gmail.com>
License-Expression: BSD-3-Clause
License-File: LICENSE
Keywords: API,ASGI,HTTP,Python,async,asynchronous,backend,concurrent,framework,real-time,scalable,uvicorn,web,web server,websocket
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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 :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: anyio==4.14.1
Requires-Dist: itsdangerous>=2.1.2
Requires-Dist: passlib>=1.7.4
Requires-Dist: pydantic<3.0,>=2.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: python-multipart>=0.0.6
Requires-Dist: tomli>=2.0.1; python_version < '3.11'
Requires-Dist: typing-extensions>=4.12.2; python_version < '3.10'
Requires-Dist: uvicorn>=0.27.0
Provides-Extra: all
Requires-Dist: argon2-cffi>=21.2.0; extra == 'all'
Requires-Dist: bcrypt>=4.0.0; extra == 'all'
Requires-Dist: cryptography>=41.0.0; extra == 'all'
Requires-Dist: email-validator>=2.0.0; extra == 'all'
Requires-Dist: granian>=1.2.0; extra == 'all'
Requires-Dist: jinja2>=3.1.6; extra == 'all'
Requires-Dist: pyjwt>=2.7.0; extra == 'all'
Requires-Dist: python-ulid>=2.0.0; extra == 'all'
Requires-Dist: redis>=5.0.0; extra == 'all'
Requires-Dist: scrypt>=0.8.0; extra == 'all'
Requires-Dist: strawberry-graphql>=0.219.0; extra == 'all'
Requires-Dist: tortoise-orm>=1.0; extra == 'all'
Provides-Extra: cache
Requires-Dist: redis>=5.0.0; extra == 'cache'
Provides-Extra: crypto
Requires-Dist: cryptography>=41.0.0; extra == 'crypto'
Provides-Extra: dev
Requires-Dist: argon2-cffi>=21.2.0; extra == 'dev'
Requires-Dist: bcrypt>=4.0.0; extra == 'dev'
Requires-Dist: coverage<8.0,>=6.3; extra == 'dev'
Requires-Dist: cryptography>=41.0.0; extra == 'dev'
Requires-Dist: email-validator>=2.0.0; extra == 'dev'
Requires-Dist: exceptiongroup>=1.2.0; (python_version < '3.11') and extra == 'dev'
Requires-Dist: fakeredis[lua]>=2.26.0; extra == 'dev'
Requires-Dist: granian>=1.2.0; extra == 'dev'
Requires-Dist: httpx<0.29.0,>=0.23.3; extra == 'dev'
Requires-Dist: jinja2>=3.1.6; extra == 'dev'
Requires-Dist: mypy>=1.15.0; extra == 'dev'
Requires-Dist: pyjwt>=2.7.0; extra == 'dev'
Requires-Dist: pytest-asyncio<1.5.0,>=0.25.3; extra == 'dev'
Requires-Dist: pytest<9.1.0,>=8.3.4; extra == 'dev'
Requires-Dist: python-ulid>=2.0.0; extra == 'dev'
Requires-Dist: redis>=5.0.0; extra == 'dev'
Requires-Dist: ruff<0.17,>=0.16.0; extra == 'dev'
Requires-Dist: scrypt>=0.8.0; extra == 'dev'
Requires-Dist: strawberry-graphql>=0.219.0; extra == 'dev'
Requires-Dist: tortoise-orm>=1.0; extra == 'dev'
Requires-Dist: ty<0.1,>=0.0.63; extra == 'dev'
Requires-Dist: typing-extensions==4.16.0; extra == 'dev'
Provides-Extra: events
Requires-Dist: redis>=5.0.0; extra == 'events'
Provides-Extra: granian
Requires-Dist: granian>=1.2.0; extra == 'granian'
Provides-Extra: graphql
Requires-Dist: strawberry-graphql>=0.219.0; extra == 'graphql'
Provides-Extra: hashing-all
Requires-Dist: argon2-cffi>=21.2.0; extra == 'hashing-all'
Requires-Dist: bcrypt>=4.0.0; extra == 'hashing-all'
Requires-Dist: scrypt>=0.8.0; extra == 'hashing-all'
Provides-Extra: hashing-argon2
Requires-Dist: argon2-cffi>=21.2.0; extra == 'hashing-argon2'
Provides-Extra: hashing-bcrypt
Requires-Dist: bcrypt>=4.0.0; extra == 'hashing-bcrypt'
Provides-Extra: hashing-scrypt
Requires-Dist: scrypt>=0.8.0; extra == 'hashing-scrypt'
Provides-Extra: jwt
Requires-Dist: pyjwt>=2.7.0; extra == 'jwt'
Provides-Extra: record
Requires-Dist: tortoise-orm>=1.0; extra == 'record'
Provides-Extra: templating
Requires-Dist: jinja2>=3.1.6; extra == 'templating'
Description-Content-Type: text/markdown

# Sillo

<p align="center">
  <img src="https://avatars.githubusercontent.com/u/199959103?s=400&u=2b9d0cb939318b295fefd0cdbc417f85d5d4ba87&v=4" alt="Sillo logo" width="160" height="160">
</p>

<p align="center">
  <strong>Python With the Pieces Already in Place.</strong>
</p>

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.

## Requirements

- Python 3.10+
- `uv` for project and dependency management

## Installation

```bash
uv add sillo-framework
```

For optional feature groups:

```bash
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:

```bash
uv add "sillo-framework[all]"
```

## Hello World

```python
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 an ASGI server:

```bash
uv add uvicorn
uv run uvicorn main:app --reload
```

## Request Validation

Sillo validates request bodies with Pydantic through `request_model`.

```python
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.

```python
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:

```python
from sillo import Depend


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

## Routing

```python
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:

```bash
cd docs/docs
bun run build
```

## Testing

Run the core test suite with:

```bash
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
