Skip to main content

A powerful, dependency-injection-driven ASGI web framework for Python with first-class support for configuration management, type-safe routing, and extensible middleware.

Project description

Serving: The Extensible Python Web Framework 🚀

[!WARNING] Serving is currently in alpha and is NOT recommended for production use. APIs are subject to change.

Serving is a small ASGI web framework built on Starlette with first‑class dependency injection (Bevy), YAML configuration, typed routing, forms with CSRF, and themed error pages.

✨ Highlights

  • ASGI/Starlette core with a minimal surface area
  • Dependency Injection via Bevy (request‑scoped container)
  • YAML configuration with typed ConfigModels (including collections)
  • Lightweight routing decorator; return‑type‑based responses
  • Forms + CSRF with Jinja2 templates
  • Themed error pages with dev‑mode details
  • Simple CLI wrapper around Uvicorn
  • Pluggable sessions with DI‑friendly access
  • Static asset mount in dev compatible with url_for('static', ...)

🚀 Quick Start

Install

pip install getserving[server]

Minimal App

  1. Router module
# myapp/web.py
from serving.router import Router
from serving.types import PlainText, JSON, Jinja2
from serving.injectors import QueryParam
from serving import redirect

app = Router()

@app.route("/")
async def index() -> Jinja2:
    return "home.html", {"message": "Hello from Serving"}

@app.route("/hello")
async def hello(name: QueryParam[str] = "world") -> PlainText:
    return f"Hello, {name}!"

@app.route("/redirect")
async def go_home() -> PlainText:
    redirect("/")
    return "This will not be sent"
  1. Template
<!-- templates/home.html -->
<h1>{{ message }}</h1>
  1. Configuration
# serving.dev.yaml
environment: dev

auth:
  credential_provider: myapp.auth:MyProvider
  config:
    csrf_secret: change-me-long-random-string

templates:
  directory: templates

static:
  mount: /static
  directory: static
  # In dev, assets are served by default; in other envs default is false.
  # Explicitly enable serving in non-dev if desired:
  # serve: true

routers:
  - entrypoint: myapp.web:app
    routes:
      - path: "/"
      - path: "/hello"
      - path: "/redirect"
  1. Run
serv -e dev --reload

Your app will be available at http://127.0.0.1:8000.

🗝️ Sessions

Serving supports pluggable session providers and a dict‑like Session mapping bound to each request.

Configure a provider in YAML:

# serving.dev.yaml (add alongside `auth`/`routers`)
session:
  session_provider: serving.session:InMemorySessionProvider
  session_type: serving.session:Session  # optional
  config: {}

Use the session in routes:

from serving.session import Session
from serving.injectors import SessionParam

@app.route("/whoami")
async def whoami(sess: Session) -> JSON:
    return {"user": sess.get("user_id")}

@app.route("/feature")
async def feature(beta: SessionParam[bool] = False) -> JSON:
    # Uses parameter name as key; default applies if key is missing
    return {"beta": beta}

See the full guide: Sessions

🧭 Return Types

  • PlainText → PlainTextResponse
  • JSON → JSONResponse
  • HTML → HTMLResponse
  • Jinja2 → TemplateResponse (tuple of template_name, context_dict)
  • Returning a Starlette Response is passed through as‑is

🔐 Authentication & Permissions

Configure an auth provider in YAML (auth.credential_provider). Serving calls has_credentials(permissions) before invoking a route; if denied, a themed 401 page is rendered. See Authentication for the CredentialProvider protocol and examples.

🧾 Forms & CSRF

Use serving.forms.Form with Jinja2. When CSRF is enabled (default), templates must call {{ csrf() }}; invalid tokens are rejected by CSRFMiddleware. See Forms & CSRF.

🎨 Error Pages & Theming

Customize error templates via the theming section in YAML. Dev mode can include extra details (stack traces, missing path). See Error Handling & Theming.

🧰 CLI

serv [-d DIR] [-e ENV] [uvicorn options...]
  • -d, --working-directory DIR — where your serving.{env}.yaml lives
  • -e, --env ENV — choose environment (e.g., dev, prod)
  • All other flags are passed to Uvicorn (e.g., --reload, --host, --port)

📚 Documentation

See the docs/ directory for detailed guides and references:

Also see the demo/blog demo for a runnable example.

🤝 Contributing

Contributions are welcome! Bug reports, feature suggestions, docs, and tests are appreciated. Please open an issue or pull request.

📄 License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

getserving-0.1.1a4.tar.gz (65.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

getserving-0.1.1a4-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

File details

Details for the file getserving-0.1.1a4.tar.gz.

File metadata

  • Download URL: getserving-0.1.1a4.tar.gz
  • Upload date:
  • Size: 65.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.6.9

File hashes

Hashes for getserving-0.1.1a4.tar.gz
Algorithm Hash digest
SHA256 ef58da6df06b2d248d725427084dbcaeb4a0fa68aa9b3984f0bcccf62f3f830c
MD5 8dd5deb9922233f3ca5fba461a2e28e9
BLAKE2b-256 b48e0186b9152fe5c8692f65d9369df3c5652fde96dc0f3edc18dd46010357dc

See more details on using hashes here.

File details

Details for the file getserving-0.1.1a4-py3-none-any.whl.

File metadata

File hashes

Hashes for getserving-0.1.1a4-py3-none-any.whl
Algorithm Hash digest
SHA256 c0a894db7df8e3845043abf48062b485d38db629379ff4e9064dc0a4061fdbc1
MD5 7e3f0748a4d3e6dba3314d4f83952d6f
BLAKE2b-256 46e63f1eb2fad08603fa6839b236765e615740fa9a8c55e42f5ff7135b08afdc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page