getserving


Namegetserving JSON
Version 0.1.1a8 PyPI version JSON
download
home_pageNone
SummaryA powerful, dependency-injection-driven ASGI web framework for Python with first-class support for configuration management, type-safe routing, and extensible middleware.
upload_time2025-09-19 22:35:41
maintainerNone
docs_urlNone
authorNone
requires_python>=3.13
licenseMIT 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.
keywords api asgi framework http web
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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
- 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).

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "getserving",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.13",
    "maintainer_email": "Zechariah Zimmerman <zzimmerman@8ly.com>",
    "keywords": "api, asgi, framework, http, web",
    "author": null,
    "author_email": "Zechariah Zimmerman <zzimmerman@8ly.com>",
    "download_url": "https://files.pythonhosted.org/packages/52/32/ab7fcf109b24b3ed02e0449c9b6790d73af8a792fd8af43379a4a486408a/getserving-0.1.1a8.tar.gz",
    "platform": null,
    "description": "# Serving: The Extensible Python Web Framework \ud83d\ude80\n\n> [!WARNING]\n> Serving is currently in alpha and is NOT recommended for production use. APIs are subject to change.\n\nServing is a small ASGI web framework built on Starlette with first\u2011class dependency injection (Bevy), YAML configuration, typed routing, forms with CSRF, and themed error pages.\n\n## \u2728 Highlights\n\n- ASGI/Starlette core with a minimal surface area\n- Dependency Injection via Bevy (request\u2011scoped container)\n- YAML configuration with typed `ConfigModel`s (including collections)\n- Lightweight routing decorator; return\u2011type\u2011based responses\n- Forms + CSRF with Jinja2 templates\n- Themed error pages with dev\u2011mode details\n- Simple CLI wrapper around Uvicorn\n- Pluggable sessions with DI\u2011friendly access\n- Static asset mount in dev compatible with `url_for('static', ...)`\n\n## \ud83d\ude80 Quick Start\n\n### Install\n\n```bash\npip install getserving[server]\n```\n\n### Minimal App\n\n1) Router module\n\n```python\n# myapp/web.py\nfrom serving.router import Router\nfrom serving.types import PlainText, JSON, Jinja2\nfrom serving.injectors import QueryParam\nfrom serving import redirect\n\napp = Router()\n\n@app.route(\"/\")\nasync def index() -> Jinja2:\n    return \"home.html\", {\"message\": \"Hello from Serving\"}\n\n@app.route(\"/hello\")\nasync def hello(name: QueryParam[str] = \"world\") -> PlainText:\n    return f\"Hello, {name}!\"\n\n@app.route(\"/redirect\")\nasync def go_home() -> PlainText:\n    redirect(\"/\")\n    return \"This will not be sent\"\n```\n\n2) Template\n\n```html\n<!-- templates/home.html -->\n<h1>{{ message }}</h1>\n```\n\n3) Configuration\n\n```yaml\n# serving.dev.yaml\nenvironment: dev\n\nauth:\n  credential_provider: myapp.auth:MyProvider\n  config:\n    csrf_secret: change-me-long-random-string\n\ntemplates:\n  directory: templates\n\nstatic:\n  mount: /static\n  directory: static\n  # In dev, assets are served by default; in other envs default is false.\n  # Explicitly enable serving in non-dev if desired:\n  # serve: true\n\nrouters:\n  - entrypoint: myapp.web:app\n    routes:\n      - path: \"/\"\n      - path: \"/hello\"\n      - path: \"/redirect\"\n```\n\n4) Run\n\n```bash\nserv -e dev --reload\n```\n\nYour app will be available at http://127.0.0.1:8000.\n\n## \ud83d\udddd\ufe0f Sessions\n\nServing supports pluggable session providers and a dict\u2011like `Session` mapping bound to each request.\n\nConfigure a provider in YAML:\n\n```yaml\n# serving.dev.yaml (add alongside `auth`/`routers`)\nsession:\n  session_provider: serving.session:InMemorySessionProvider\n  session_type: serving.session:Session  # optional\n  config: {}\n```\n\nUse the session in routes:\n\n```python\nfrom serving.session import Session\nfrom serving.injectors import SessionParam\n\n@app.route(\"/whoami\")\nasync def whoami(sess: Session) -> JSON:\n    return {\"user\": sess.get(\"user_id\")}\n\n@app.route(\"/feature\")\nasync def feature(beta: SessionParam[bool] = False) -> JSON:\n    # Uses parameter name as key; default applies if key is missing\n    return {\"beta\": beta}\n```\n\nSee the full guide: [Sessions](docs/sessions.md)\n\n## \ud83e\udded Return Types\n\n- `PlainText` \u2192 PlainTextResponse\n- `JSON` \u2192 JSONResponse\n- `HTML` \u2192 HTMLResponse\n- `Jinja2` \u2192 TemplateResponse (tuple of `template_name`, `context_dict`)\n- Returning a Starlette `Response` is passed through as\u2011is\n\n## \ud83d\udd10 Authentication & Permissions\n\nConfigure 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.\n\n## \ud83e\uddfe Forms & CSRF\n\nUse `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).\n\n## \ud83c\udfa8 Error Pages & Theming\n\nCustomize 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).\n\n## \ud83e\uddf0 CLI\n\n```bash\nserv [-d DIR] [-e ENV] [uvicorn options...]\n```\n\n- `-d, --working-directory DIR` \u2014 where your `serving.{env}.yaml` lives\n- `-e, --env ENV` \u2014 choose environment (e.g., `dev`, `prod`)\n- All other flags are passed to Uvicorn (e.g., `--reload`, `--host`, `--port`)\n\n## \ud83d\udcda Documentation\n\nSee the [docs/](docs/README.md) directory for detailed guides and references:\n\n- [Getting Started](docs/getting-started.md) \u2014 install and minimal setup\n- [Configuration](docs/configuration.md) \u2014 YAML layout, templates, theming, routers, auth\n- [Routing](docs/routing.md) \u2014 router decorator, params, permissions\n- [Dependency Injection](docs/dependency-injection.md) \u2014 Bevy DI and `ConfigModel`s\n- [Forms & CSRF](docs/forms.md) \u2014 forms + CSRF\n- [Error Handling](docs/error-handling.md) \u2014 exceptions and theming\n- [Authentication](docs/authentication.md) \u2014 provider protocol and configuration\n- [Middleware](docs/middleware.md) \u2014 default middleware stack\n- [Response Helpers](docs/response.md) \u2014 `set_header`, `redirect`, etc.\n- [CLI](docs/cli.md) \u2014 CLI flags and examples\n- [Testing](docs/testing.md) \u2014 testing patterns\n\nAlso see the [demo/blog](demo/blog/README.md) demo for a runnable example.\n\n## \ud83e\udd1d Contributing\n\nContributions are welcome! Bug reports, feature suggestions, docs, and tests are appreciated. Please open an issue or pull request.\n\n## \ud83d\udcc4 License\n\nMIT \u2014 see [LICENSE](LICENSE).\n",
    "bugtrack_url": null,
    "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.",
    "summary": "A powerful, dependency-injection-driven ASGI web framework for Python with first-class support for configuration management, type-safe routing, and extensible middleware.",
    "version": "0.1.1a8",
    "project_urls": {
        "Changelog": "https://github.com/ZechCodes/Serving/blob/main/CHANGELOG.md",
        "Documentation": "https://github.com/ZechCodes/Serving/tree/main/docs",
        "Homepage": "https://github.com/ZechCodes/Serving",
        "Issues": "https://github.com/ZechCodes/Serving/issues",
        "Repository": "https://github.com/ZechCodes/Serving"
    },
    "split_keywords": [
        "api",
        " asgi",
        " framework",
        " http",
        " web"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "57d06e566b05b9849e7f36fabe1072ef484ded47a3e351dcaa6767826f80bd04",
                "md5": "0b4a30e0afd759837cadbf33e88eebce",
                "sha256": "a0af155ceeabb8f3dab023c1b84ec0366f7707f9b41b31526421023977f003de"
            },
            "downloads": -1,
            "filename": "getserving-0.1.1a8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0b4a30e0afd759837cadbf33e88eebce",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.13",
            "size": 30508,
            "upload_time": "2025-09-19T22:35:40",
            "upload_time_iso_8601": "2025-09-19T22:35:40.468083Z",
            "url": "https://files.pythonhosted.org/packages/57/d0/6e566b05b9849e7f36fabe1072ef484ded47a3e351dcaa6767826f80bd04/getserving-0.1.1a8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5232ab7fcf109b24b3ed02e0449c9b6790d73af8a792fd8af43379a4a486408a",
                "md5": "f5cca3443f9dab617ea547596f21fb77",
                "sha256": "baa0244587b79cc0c1f52549a48185b1a063f94841673f7cd96de7de15f58d6c"
            },
            "downloads": -1,
            "filename": "getserving-0.1.1a8.tar.gz",
            "has_sig": false,
            "md5_digest": "f5cca3443f9dab617ea547596f21fb77",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.13",
            "size": 66895,
            "upload_time": "2025-09-19T22:35:41",
            "upload_time_iso_8601": "2025-09-19T22:35:41.783409Z",
            "url": "https://files.pythonhosted.org/packages/52/32/ab7fcf109b24b3ed02e0449c9b6790d73af8a792fd8af43379a4a486408a/getserving-0.1.1a8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-19 22:35:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ZechCodes",
    "github_project": "Serving",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "getserving"
}
        
Elapsed time: 1.61404s