Metadata-Version: 2.4
Name: getserving
Version: 0.1.1a10
Summary: A powerful, dependency-injection-driven ASGI web framework for Python with first-class support for configuration management, type-safe routing, and extensible middleware.
Project-URL: Homepage, https://github.com/ZechCodes/Serving
Project-URL: Documentation, https://github.com/ZechCodes/Serving/tree/main/docs
Project-URL: Repository, https://github.com/ZechCodes/Serving
Project-URL: Issues, https://github.com/ZechCodes/Serving/issues
Project-URL: Changelog, https://github.com/ZechCodes/Serving/blob/main/CHANGELOG.md
Author-email: Zechariah Zimmerman <zzimmerman@8ly.com>
Maintainer-email: Zechariah Zimmerman <zzimmerman@8ly.com>
License: MIT License
        
        Copyright (c) 2025 Zechariah Zimmerman
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: api,asgi,framework,http,web
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.13
Requires-Dist: bevy>=3.1.0b9
Requires-Dist: jinja2>=3.1.6
Requires-Dist: python-multipart>=0.0.20
Requires-Dist: pyyaml>=6.0.2
Requires-Dist: starlette>=0.41.0
Requires-Dist: websockets>=15.0.1
Requires-Dist: werkzeug>=3.1.3
Provides-Extra: server
Requires-Dist: uvicorn>=0.34.2; extra == 'server'
Description-Content-Type: text/markdown

# 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 `ConfigModel`s (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
- Configurable event system for app/request triggers
- Static asset mount in dev compatible with `url_for('static', ...)`

## 🚀 Quick Start

### Install

```bash
pip install getserving[server]
```

### Minimal App

1) Router module

```python
# 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"
```

2) Template

```html
<!-- templates/home.html -->
<h1>{{ message }}</h1>
```

3) Configuration

```yaml
# 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"
```

4) Run

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

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

```python
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](docs/sessions.md)

## 🧭 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](docs/authentication.md) 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](docs/forms.md).

## 🎨 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](docs/error-handling.md).

## 🧰 CLI

```bash
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/](docs/README.md) directory for detailed guides and references:

- [Getting Started](docs/getting-started.md) — install and minimal setup
- [Configuration](docs/configuration.md) — YAML layout, templates, theming, routers, auth
- [Routing](docs/routing.md) — router decorator, params, permissions
- [Dependency Injection](docs/dependency-injection.md) — Bevy DI and `ConfigModel`s
- [Forms & CSRF](docs/forms.md) — forms + CSRF
- [Error Handling](docs/error-handling.md) — exceptions and theming
- [Authentication](docs/authentication.md) — provider protocol and configuration
- [Middleware](docs/middleware.md) — default middleware stack
- [Response Helpers](docs/response.md) — `set_header`, `redirect`, etc.
- [CLI](docs/cli.md) — CLI flags and examples
- [Testing](docs/testing.md) — testing patterns

Also see the [demo/blog](demo/blog/README.md) 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](LICENSE).
