kinglet


Namekinglet JSON
Version 1.6.1 PyPI version JSON
download
home_pageNone
SummaryA lightweight routing framework for Python Workers
upload_time2025-09-04 09:42:21
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseMIT
keywords cloudflare workers python routing web framework asgi lightweight
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <div align="center">
  <img src="logo.png" alt="Kinglet Logo" width="200" height="200">
  <h1>Kinglet</h1>
  <p><strong>Lightning-fast Python web framework for Cloudflare Workers</strong></p>

  [![CI](https://github.com/mitchins/Kinglet/actions/workflows/ci.yml/badge.svg)](https://github.com/mitchins/Kinglet/actions/workflows/ci.yml)
  [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mitchins_Kinglet&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=mitchins_Kinglet)
  [![codecov](https://codecov.io/github/mitchins/kinglet/graph/badge.svg?token=VSA89V2XBH)](https://codecov.io/github/mitchins/kinglet)
  [![PyPI version](https://badge.fury.io/py/kinglet.svg)](https://badge.fury.io/py/kinglet)
  [![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/downloads/)
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
</div>

## Quick Start

Install: `pip install kinglet` or add `dependencies = ["kinglet"]` to pyproject.toml

```python
from kinglet import Kinglet, CorsMiddleware, cache_aside_d1

app = Kinglet(root_path="/api")

# Flexible middleware (v1.4.2+)
app.add_middleware(CorsMiddleware(allow_origin="*"))

@app.post("/auth/login")
async def login(request):
    data = await request.json()
    return {"token": "jwt-token", "user": data["email"]}

@app.get("/api/data")
@cache_aside_d1(cache_type="api_data", ttl=1800)  # D1 caching (v1.5.0+)
async def get_data(request):
    return {"data": "cached_in_prod_fresh_in_dev"}
```

## Why Kinglet?

| Feature | Kinglet | FastAPI | Flask |
|---------|---------|---------|-------|
| **Bundle Size** | 272KB | 7.8MB | 1.9MB |
| **Testing** | No server needed | TestServer required | Test client required |
| **Workers Ready** | ✅ Built-in | ❌ Complex setup | ❌ Not compatible |

## Key Features

**Core:** Decorator routing, typed parameters, flexible middleware, auto error handling, serverless testing
**Cloudflare:** D1/R2/KV helpers, D1-backed caching, environment-aware policies, CDN-aware URLs
**Database:** Micro-ORM for D1 with migrations, field validation, bulk operations (v1.6.0+)
**Security:** JWT validation, TOTP/2FA, geo-restrictions, fine-grained auth decorators
**Developer:** Full type hints, debug mode, request validation, zero-dependency testing

## Examples

**Typed Parameters & Auth:**
```python
@app.get("/users/{user_id}")
async def get_user(request):
    user_id = request.path_param_int("user_id")  # Validates or returns 400
    token = request.bearer_token()               # Extract JWT
    limit = request.query_int("limit", 10)       # Query params with defaults
    return {"user": user_id, "token": token}
```

**Flexible Middleware & Caching:**
```python
# Configure middleware with parameters
cors = CorsMiddleware(allow_origin="*", allow_methods="GET,POST")
app.add_middleware(cors)

# D1-backed caching (v1.5.0+) - faster and cheaper for <1MB responses
@app.get("/api/data")
@cache_aside_d1(cache_type="api_data", ttl=1800)  # D1 primary, R2 fallback
async def get_data(request):
    return {"data": "expensive_query_result"}

# R2-backed caching for larger responses
@app.get("/api/large")
@cache_aside(cache_type="large_data", ttl=3600)  # Environment-aware
async def get_large_data(request):
    return {"data": "large_expensive_query_result"}
```

**D1 Micro-ORM (v1.6.0+):**
```python
from kinglet import Model, StringField, IntegerField

class Game(Model):
    title = StringField(max_length=200)
    score = IntegerField(default=0)

# Simple CRUD with field validation
game = await Game.objects.create(db, title="Pac-Man", score=100)
top_games = await Game.objects.filter(db, score__gte=90).order_by("-score").all()
```

**Security & Access Control:**
```python
@app.get("/admin/debug")
@require_dev()                    # 404 in production (blackhole)
@geo_restrict(allowed=["US"])     # HTTP 451 for other countries
async def debug_endpoint(request):
    return {"debug": "sensitive data"}
```

**Testing (No Server):**
```python
def test_api():
    client = TestClient(app)
    status, headers, body = client.request("GET", "/users/123")
    assert status == 200
```

## Documentation

- **[Examples](examples/)** - Quick start examples
- **[ORM Guide](docs/ORM.md)** - D1 micro-ORM with migrations (v1.6.0+)
- **[Middleware Guide](docs/MIDDLEWARE.md)** - Flexible middleware system (v1.4.2+)
- **[Caching Guide](docs/CACHING.md)** - Environment-aware caching (v1.4.3+)
- **[Security Guide](docs/SECURITY_BEST_PRACTICES.md)** - Critical security patterns
- **[TOTP/2FA Guide](docs/TOTP.md)** - Two-factor authentication

---

Built for Cloudflare Workers Python community. **[Need help?](https://github.com/mitchins/Kinglet/issues)**

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "kinglet",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "cloudflare, workers, python, routing, web, framework, asgi, lightweight",
    "author": null,
    "author_email": "Mitchell Currie <mitchell@mitchins.dev>",
    "download_url": "https://files.pythonhosted.org/packages/5f/51/e1e840817b3f259b892dd628916a4f088ee9de5af06ba28c9212f8295d49/kinglet-1.6.1.tar.gz",
    "platform": null,
    "description": "<div align=\"center\">\n  <img src=\"logo.png\" alt=\"Kinglet Logo\" width=\"200\" height=\"200\">\n  <h1>Kinglet</h1>\n  <p><strong>Lightning-fast Python web framework for Cloudflare Workers</strong></p>\n\n  [![CI](https://github.com/mitchins/Kinglet/actions/workflows/ci.yml/badge.svg)](https://github.com/mitchins/Kinglet/actions/workflows/ci.yml)\n  [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mitchins_Kinglet&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=mitchins_Kinglet)\n  [![codecov](https://codecov.io/github/mitchins/kinglet/graph/badge.svg?token=VSA89V2XBH)](https://codecov.io/github/mitchins/kinglet)\n  [![PyPI version](https://badge.fury.io/py/kinglet.svg)](https://badge.fury.io/py/kinglet)\n  [![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/downloads/)\n  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n</div>\n\n## Quick Start\n\nInstall: `pip install kinglet` or add `dependencies = [\"kinglet\"]` to pyproject.toml\n\n```python\nfrom kinglet import Kinglet, CorsMiddleware, cache_aside_d1\n\napp = Kinglet(root_path=\"/api\")\n\n# Flexible middleware (v1.4.2+)\napp.add_middleware(CorsMiddleware(allow_origin=\"*\"))\n\n@app.post(\"/auth/login\")\nasync def login(request):\n    data = await request.json()\n    return {\"token\": \"jwt-token\", \"user\": data[\"email\"]}\n\n@app.get(\"/api/data\")\n@cache_aside_d1(cache_type=\"api_data\", ttl=1800)  # D1 caching (v1.5.0+)\nasync def get_data(request):\n    return {\"data\": \"cached_in_prod_fresh_in_dev\"}\n```\n\n## Why Kinglet?\n\n| Feature | Kinglet | FastAPI | Flask |\n|---------|---------|---------|-------|\n| **Bundle Size** | 272KB | 7.8MB | 1.9MB |\n| **Testing** | No server needed | TestServer required | Test client required |\n| **Workers Ready** | \u2705 Built-in | \u274c Complex setup | \u274c Not compatible |\n\n## Key Features\n\n**Core:** Decorator routing, typed parameters, flexible middleware, auto error handling, serverless testing\n**Cloudflare:** D1/R2/KV helpers, D1-backed caching, environment-aware policies, CDN-aware URLs\n**Database:** Micro-ORM for D1 with migrations, field validation, bulk operations (v1.6.0+)\n**Security:** JWT validation, TOTP/2FA, geo-restrictions, fine-grained auth decorators\n**Developer:** Full type hints, debug mode, request validation, zero-dependency testing\n\n## Examples\n\n**Typed Parameters & Auth:**\n```python\n@app.get(\"/users/{user_id}\")\nasync def get_user(request):\n    user_id = request.path_param_int(\"user_id\")  # Validates or returns 400\n    token = request.bearer_token()               # Extract JWT\n    limit = request.query_int(\"limit\", 10)       # Query params with defaults\n    return {\"user\": user_id, \"token\": token}\n```\n\n**Flexible Middleware & Caching:**\n```python\n# Configure middleware with parameters\ncors = CorsMiddleware(allow_origin=\"*\", allow_methods=\"GET,POST\")\napp.add_middleware(cors)\n\n# D1-backed caching (v1.5.0+) - faster and cheaper for <1MB responses\n@app.get(\"/api/data\")\n@cache_aside_d1(cache_type=\"api_data\", ttl=1800)  # D1 primary, R2 fallback\nasync def get_data(request):\n    return {\"data\": \"expensive_query_result\"}\n\n# R2-backed caching for larger responses\n@app.get(\"/api/large\")\n@cache_aside(cache_type=\"large_data\", ttl=3600)  # Environment-aware\nasync def get_large_data(request):\n    return {\"data\": \"large_expensive_query_result\"}\n```\n\n**D1 Micro-ORM (v1.6.0+):**\n```python\nfrom kinglet import Model, StringField, IntegerField\n\nclass Game(Model):\n    title = StringField(max_length=200)\n    score = IntegerField(default=0)\n\n# Simple CRUD with field validation\ngame = await Game.objects.create(db, title=\"Pac-Man\", score=100)\ntop_games = await Game.objects.filter(db, score__gte=90).order_by(\"-score\").all()\n```\n\n**Security & Access Control:**\n```python\n@app.get(\"/admin/debug\")\n@require_dev()                    # 404 in production (blackhole)\n@geo_restrict(allowed=[\"US\"])     # HTTP 451 for other countries\nasync def debug_endpoint(request):\n    return {\"debug\": \"sensitive data\"}\n```\n\n**Testing (No Server):**\n```python\ndef test_api():\n    client = TestClient(app)\n    status, headers, body = client.request(\"GET\", \"/users/123\")\n    assert status == 200\n```\n\n## Documentation\n\n- **[Examples](examples/)** - Quick start examples\n- **[ORM Guide](docs/ORM.md)** - D1 micro-ORM with migrations (v1.6.0+)\n- **[Middleware Guide](docs/MIDDLEWARE.md)** - Flexible middleware system (v1.4.2+)\n- **[Caching Guide](docs/CACHING.md)** - Environment-aware caching (v1.4.3+)\n- **[Security Guide](docs/SECURITY_BEST_PRACTICES.md)** - Critical security patterns\n- **[TOTP/2FA Guide](docs/TOTP.md)** - Two-factor authentication\n\n---\n\nBuilt for Cloudflare Workers Python community. **[Need help?](https://github.com/mitchins/Kinglet/issues)**\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A lightweight routing framework for Python Workers",
    "version": "1.6.1",
    "project_urls": {
        "Bug Tracker": "https://github.com/mitchins/Kinglet/issues",
        "Homepage": "https://github.com/mitchins/Kinglet",
        "Repository": "https://github.com/mitchins/Kinglet"
    },
    "split_keywords": [
        "cloudflare",
        " workers",
        " python",
        " routing",
        " web",
        " framework",
        " asgi",
        " lightweight"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "45f83cd8befa7cf9c456a9f9852008cb49c62a8f6be76a0971825c1de6f658f2",
                "md5": "a8cf1fcb5280fd3ac241339c69850a3a",
                "sha256": "1501b5d451b5fc68c21b55d8f1d37b5ed9e4b690f6b261df7390e6532afbd60a"
            },
            "downloads": -1,
            "filename": "kinglet-1.6.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a8cf1fcb5280fd3ac241339c69850a3a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 66154,
            "upload_time": "2025-09-04T09:42:19",
            "upload_time_iso_8601": "2025-09-04T09:42:19.581500Z",
            "url": "https://files.pythonhosted.org/packages/45/f8/3cd8befa7cf9c456a9f9852008cb49c62a8f6be76a0971825c1de6f658f2/kinglet-1.6.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5f51e1e840817b3f259b892dd628916a4f088ee9de5af06ba28c9212f8295d49",
                "md5": "9c40bb15839f74101b4aecdd63b0e518",
                "sha256": "fe98e59906bcca8a95c34a305fcb52182ad815d9fc4292dcb5af9be6db1d391e"
            },
            "downloads": -1,
            "filename": "kinglet-1.6.1.tar.gz",
            "has_sig": false,
            "md5_digest": "9c40bb15839f74101b4aecdd63b0e518",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 141523,
            "upload_time": "2025-09-04T09:42:21",
            "upload_time_iso_8601": "2025-09-04T09:42:21.200931Z",
            "url": "https://files.pythonhosted.org/packages/5f/51/e1e840817b3f259b892dd628916a4f088ee9de5af06ba28c9212f8295d49/kinglet-1.6.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-04 09:42:21",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mitchins",
    "github_project": "Kinglet",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "kinglet"
}
        
Elapsed time: 0.72772s