Introduction to Fenrir Framework

Fenrir is a state-of-the-art, high-performance, hybrid Python web framework built on top of modern ASGI specifications. It elegantly merges the best programming paradigms from Python's most popular web frameworks into a single unified workspace.

Why Hybrid?

Instead of rewriting or separating your microservices into different paradigms, Fenrir allows you to leverage FastAPI validation, Flask context-locals, and Falcon resources simultaneously in the same event-loop.

Key Features

  • ⚡ High-Speed ASGI Core: Extremely low-overhead routing and handler pipeline, achieving massive request throughput.
  • 🧩 Framework Hybridization: Coexist Flask-style context-locals, FastAPI-style dependencies, Falcon-style class-based resources, and Sanic listeners.
  • 📖 Auto-Generated OpenAPI Docs: Interactive Swagger UI (at /docs or /openapi-docs) instantly generated from your Pydantic schemas.
  • 🔌 Modern Communications: Native WebSockets and Server-Sent Events (SSE) out of the box.
  • 🛠️ Premium CLI Tooling: Visual route tables, interactive shell, in-memory benchmarking suite, and scaffold creators.

Installation & Setup

Fenrir requires Python 3.8+. Install the official release from PyPI:

pip install fenrir-framework

Scaffolding a New Project

Fenrir comes packed with a robust scaffolding CLI to get you up and running with a cleanly structured layout instantly.

# Create a new scaffolded project
fenrir new my_website
cd my_website

Serving the Application

You can run your app locally using the Asteri ASGI app server:

# Run with hot reloading on port 8088
fenrir run app:app --port 8088 --dev

FastAPI Paradigm (Validation & DI)

Fenrir native integration with Pydantic v2 allows for dynamic, type-safe parameters, automated body parsing, and Dependency Injection patterns.

Key Features

  • Automatic request body deserialization and Pydantic schema validation.
  • Dependency injection with Depends() decorators.
  • Parameter resolution (Query, Path, Header, Form, File).
from pydantic import BaseModel
from fenrir import Fenrir, Depends, Header

app = Fenrir()

class UserRegister(BaseModel):
    username: str
    email: str
    age: int

async def verify_token(x_api_key: str = Header(default=None)):
    if x_api_key != "secret-token":
        raise ValueError("Invalid credentials")
    return x_api_key

@app.post("/api/register")
async def register(
    body: UserRegister, 
    token: str = Depends(verify_token)
):
    return {"status": "success", "user": body.model_dump(), "auth": token}

Flask Paradigm (Context & Templating)

For rendering user interfaces or retrieving parameters imperatively, Fenrir provides thread/task-safe context locals and Jinja2 rendering.

Context variables (Thread safe)

Fenrir uses contextvars to ensure request, g, and session are perfectly isolated across asynchronous operations, resolving legacy executor thread-safety bugs.

Key Features

  • Context locals: request, g, session.
  • Jinja2 standard rendering using render_template().
  • Flask-style exception handler hooks (@app.exception(ValueError)).
from fenrir import Fenrir, request, g, render_template

app = Fenrir()

@app.get("/welcome")
async def welcome():
    # Retrieve query params via global request context-local
    name = request.args.get("name", "Guest")
    # Share state across middleware/routes using request global g
    g.visit_count = g.get("visit_count", 0) + 1
    
    return render_template("welcome.html", name=name, count=g.visit_count)

Falcon Paradigm (Class-Based Resources)

If you prefer class-based, REST-compliant designs with direct control over request and response objects, Fenrir supports Falcon-style resources.

Key Features

  • Class view methods mapping to HTTP verbs (on_get, on_post, on_put, on_delete).
  • Direct mutation of the response media: resp.media = {...}.
  • Lightweight routing mapping: app.add_route("/path", Resource()).
from fenrir import Fenrir

app = Fenrir()

class ItemResource:
    async def on_get(self, req, resp, item_id: int):
        resp.status = 200
        resp.media = {
            "item_id": item_id,
            "msg": "Fetched via Falcon Class-Based view!"
        }

    async def on_post(self, req, resp, item_id: int):
        data = req.json
        resp.status = 201
        resp.media = {
            "item_id": item_id,
            "received": data
        }

app.add_route("/items/<item_id:int>", ItemResource())

Sanic Paradigm (Tasks, Listeners & Hooks)

Manage lifecycle actions and run concurrent async tasks in the background using Sanic-style event scheduling.

Key Features

  • Lifecycle listeners: before_server_start, after_server_stop.
  • Global middleware hooks: @app.middleware("request") and @app.middleware("response").
  • Non-blocking background loop runner: app.add_task().
import asyncio
from fenrir import Fenrir

app = Fenrir()

@app.listener("before_server_start")
async def setup_db_pool(app_inst):
    print("Database connection initiated!")

async def background_poller():
    while True:
        print("Polling metrics...")
        await asyncio.sleep(60)

@app.listener("after_server_start")
async def run_poller(app_inst):
    # Register background coroutine
    app_inst.add_task(background_poller())

Bottle Paradigm (WSGI mounting)

Run older legacy applications synchronously inside the high-speed ASGI event loop with Bottle-style legacy mounting adapters.

Key Features

  • Mount legacy synchronous WSGI apps seamlessly: app.mount_wsgi(wsgi_app, prefix="/legacy").
  • Standard redirection helper: redirect(location).
  • Send assets: send_file(path_or_file) and directory secure reader send_from_directory(dir, path).
from fenrir import Fenrir, redirect
from legacy_app import flask_wsgi_app # WSGI app

app = Fenrir()

# Mount the Flask WSGI app onto ASGI routing
app.mount_wsgi(flask_wsgi_app, prefix="/legacy")

@app.get("/old-docs")
async def old_docs():
    # Legacy bottle-style redirection
    return redirect("/docs")

CLI Command Reference

Fenrir includes a visual, rich command-line tool. Execute fenrir or python -m fenrir.cli inside your shell.

Command Description Example
fenrir run Serve application using Asteri v2.2.2 ASGI with reload/multiprocess fenrir run app:app --port 8088 --dev
fenrir routes Visual colorized structural table of registered HTTP and WS paths fenrir routes app:app
fenrir shell Spawns an interactive REPL with loaded application state fenrir shell app:app
fenrir bench Runs zero-network HTTPX benchmarks directly over the ASGI pipeline fenrir bench app:app -i 1000 -p /
fenrir new Scaffolds a cleanly organized responsive web project directory fenrir new project_name
fenrir info Inspects active environment, engine modules and route statistics fenrir info app:app