A hybrid Python web framework combining Flask, FastAPI, Bottle, Falcon, and Sanic
Project description
Fenrir Web 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 (Flask, FastAPI, Sanic, Falcon, and Bottle) into a single unified workspace, powered locally by the premium Asteri v2.2.2 application server.
Whether you prefer the automatic Pydantic validation of FastAPI, the seamless context-locals of Flask, the raw class-based speed of Falcon, or the robust background task model of Sanic, Fenrir allows you to leverage them all simultaneously in the same codebase.
📦 Installation
Install directly from PyPI:
pip install fenrir-framework
Or install in development mode by cloning the repository:
git clone https://github.com/IshikawaUta/fenrir.git
cd fenrir
pip install -e .
🌟 Key Features
- ⚡ High-Speed ASGI Core: Extremely low-overhead routing and handler pipeline, achieving massive request throughput.
- 🧩 Framework Hybridization:
- FastAPI Paradigm: Native Pydantic v2 data validation,
Annotatedtype decorators, automated parameter resolution (Query,Path,Header,Cookie,Body), dynamic dependency injection (Depends), and automatedresponse_modelserialization. - Flask Paradigm: Thread/Task-safe context locals (
request,g,session), Jinja2 template rendering (render_template), and request teardown hooks. - Falcon Paradigm: Class-based resource controllers (
on_get,on_post), before/after hooks, and in-place response mutation. - Sanic Paradigm: Global
sys.modulespatching (install_sanic_compat()), standard response helpers (json,text,html,raw,redirect), lifecycle listeners (before_server_start, etc.), and a background event scheduler (app.add_task). - Bottle Paradigm: Built-in WSGI-to-ASGI wrapper and legacy mount adapter (
app.mount_wsgi()) to run old WSGI applications at ASGI speeds.
- FastAPI Paradigm: Native Pydantic v2 data validation,
- 📖 Auto-Generated OpenAPI Docs: Interactive Swagger UI (
/docs) and ReDoc (/redoc) instantly generated from your Pydantic schemas and route metadata. - 🔌 Modern Communications: Out-of-the-box support for WebSockets and Server-Sent Events (SSE).
- 🛠️ Premium CLI Tooling: Visual route tables, interactive app shell, in-memory benchmarking suite, project scaffolding, and environment system inspection.
- 🐍 Python 3.8–3.13 Compatible: Full backward compatibility ensured via
typing_extensionspolyfills forAnnotated,get_origin,get_args; and acontextvars-awareasyncio.to_threadshim.
🚀 Quick Start (The Hybrid Power)
Here is a simple example (demo_app.py) showcasing how Flask, FastAPI, Falcon, and Sanic styles coexist harmoniously in a single application:
import logging
from pydantic import BaseModel
from fenrir import (
Fenrir, Blueprint, request, g, Depends, Query, Header,
render_template, Response, Form, File, UploadFile,
WebSocket, WebSocketDisconnect
)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("demo")
# Initialize the Hybrid App
app = Fenrir(title="Fenrir Hybrid Demo", version="1.2.1")
# --- 1. FastAPI-Style Validation & DI ---
class UserRegister(BaseModel):
username: str
email: str
age: int
async def verify_api_key(x_api_key: str = Header(default=None)):
if x_api_key != "super-secret-key":
logger.warning("Invalid API key attempt")
return x_api_key
# --- 2. Flask-Style Routing & Context-Locals ---
@app.get("/")
async def home():
name = request.args.get("name", "Fenrir Developer")
return render_template("index.html", name=name)
# --- 3. Falcon-Style Class-Based Resources ---
class ItemResource:
async def on_get(self, req, resp, item_id: int):
resp.status = 200
resp.media = {"item_id": item_id, "style": "Falcon Resource"}
app.add_route("/items/<item_id:int>", ItemResource())
# --- 4. Sanic-Style Listeners & Background Tasks ---
@app.listener("before_server_start")
async def setup_db(app_instance):
logger.info("Initializing mock database...")
@app.middleware("request")
async def log_request(req):
logger.info(f"Incoming: {req.method} {req.path}")
g.user_role = "guest" # Share state using Flask-style 'g'
# Run with Asteri ASGI server
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000, workers=2)
💻 CLI Command Reference
Fenrir comes packed with a high-fidelity, visually rich command-line tool. Start the CLI by executing fenrir or python -m fenrir.cli.
1. fenrir run
Serve your application locally. Powered by Asteri v2.2.2, supporting dynamic multiprocessing, worker management, and live hot-reloading.
fenrir run demo_app:app --port 8000 --dev
- Flags:
-H,--host: Host bind address (default:127.0.0.1).-p,--port: Port number (default:8000).-w,--workers: Number of concurrent workers (default:1).-d,--dev/--reload: Active development mode with auto-reload.
2. fenrir routes
Print a beautiful, colorized structural table of all registered HTTP endpoints, methods, matching handlers, and associated blueprints.
fenrir routes demo_app:app
3. fenrir shell
Instantly spawn an interactive python shell pre-configured with all key framework classes and context loaded (app, request, g, Response, Blueprint, etc.).
fenrir shell demo_app:app
4. fenrir bench
Perform in-memory framework benchmarking directly over ASGI using HTTPX. Eliminates network noise and tests raw pipeline speed under loaded constraints.
fenrir bench demo_app:app -i 1000 -t 5 -p / -m GET
5. fenrir new
Scaffold a complete, cleanly structured new Fenrir project directory in seconds with a premium responsive UI out of the box.
fenrir new my_new_project
cd my_new_project
fenrir run app.py --dev
6. fenrir info
Inspect the environment including Python details, OS details, Pydantic/Asteri versions, active compatibility layers, and route statistics.
fenrir info demo_app:app
🧪 Comprehensive Test Suite
Fenrir is thoroughly covered by an automated test suite comprising 482 tests validating every single component, compat namespace, file upload, routing detail, and CLI functionality. The suite runs automatically via GitHub Actions on every push across Python 3.8 – 3.13.
Run the test suite locally:
PYTHONPATH=. pytest -v
Output:
======================== 482 passed, 1 skipped in 3.4s ========================
🔄 Changelog
v1.2.1 — Packaging & Asset Integration Patch
Logo and favicon assets are now properly included in the package distribution:
Logo Asset Packaging
- Issue:
fenrir newcommand failed to copy logo and favicon files when creating new projects outside the main repository. - Root cause: Logo files (
logo.png,logo.jpg) were stored in the repository root, not within thefenrir/package directory, so they were not included when the package was installed via PyPI. - Fix:
- Moved
logo.pngandlogo.jpgfrom repository root tofenrir/package directory. - Added
[tool.setuptools.package-data]configuration inpyproject.tomlto include image files:fenrir = ["logo.png", "logo.jpg"]. - Updated
fenrir/cli.pycmd_new()function to look for logos in the fenrir package directory first, with fallbacks for development mode.
- Moved
- Result: All tests pass (482 unit tests + 13 advanced tests).
fenrir newnow works correctly in all environments.
v1.1.1 — Python 3.8–3.10 Full Compatibility Patch
Five test failures on Python 3.8 CI were identified and patched:
1. RuntimeError: Working outside of request context (session, redirect in sync handlers)
- Root cause:
loop.run_in_executor()does not propagatecontextvarsby default. Sync route handlers usingsession[...]orredirect()lost the request context when moved into the executor thread. - Fix:
fenrir/compat.py— polyfill now callscontextvars.copy_context().run(func)instead of passingfuncdirectly to the executor.
2. AssertionError: {'user': None} != {'user': 'Alice'} (Annotated[str, Header()])
- Root cause:
typing.get_origin(typing_extensions.Annotated[...])returnsNoneon Python 3.8, soAnnotatedparameters were silently ignored during dependency resolution. - Fix:
fenrir/compat.py— exportget_origin/get_argsfromtyping_extensions(which correctly handles its ownAnnotated).fenrir/dependencies.pyandfenrir/openapi.pynow import these fromfenrir.compat.
3. AssertionError: {'content_type': ''} != {'content_type': 'text/plain'} (file upload)
- Root cause:
python-multipart < 0.0.21(installed on Python 3.8–3.10 CI runners) did not passcontent_typeintoFile.__init__, sofile.content_typedid not exist. - Fix:
fenrir/request.py— intercepts the parser'son_header_field/on_header_value/on_headers_finishedcallbacks to capture theContent-Typeof each multipart part before theFileobject is constructed, and injects it as a fallback.
4. AssertionError: 'target' == '/nested/target' (relative redirect)
- Resolved as a side-effect of fix #1 (contextvars propagation restores
request.pathinside the executor thread).
5. CI timeout on Python 3.9 (gevent build)
- The Python 3.9 job was cancelled mid-build because compiling
geventtook too long. This is an infrastructure concern, not a code issue; no code change required.
v1.1.0 — CI/CD & Centering Fix
- Added GitHub Actions workflow for automated testing across Python 3.8–3.13.
- Fixed centering of
PROJECT CREATED SUCCESSFULLYbadge and logo in scaffolded template. - Added RFC 7231 HEAD method compliance.
- Added
itsdangerousandpython-multipartas explicit core dependencies.
v0.1.0 — Initial Release
- Core ASGI framework with Flask, FastAPI, Sanic, Falcon, and Bottle hybridization.
- 482 automated unit tests.
- Premium CLI tooling (
run,routes,shell,bench,new,info). - Auto-generated OpenAPI/Swagger documentation.
- WebSocket and Server-Sent Events support.
📜 License
Fenrir is open-sourced software licensed under the MIT 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fenrir_framework-1.2.1.tar.gz.
File metadata
- Download URL: fenrir_framework-1.2.1.tar.gz
- Upload date:
- Size: 768.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96273df3ebbbbdb614dee662af9e2953eff4ada4a1ee01efdb4a0ad690e8389b
|
|
| MD5 |
aeb89a1033e7404b2fc1512c8b7da630
|
|
| BLAKE2b-256 |
8a4813d966f8119e6e6dce468223b229621566bac130bb51a610b83e91e7ad71
|
File details
Details for the file fenrir_framework-1.2.1-py3-none-any.whl.
File metadata
- Download URL: fenrir_framework-1.2.1-py3-none-any.whl
- Upload date:
- Size: 753.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7805dc12f77c517bf4be353782e56dedae04d16fd5413aa086c90e44f76f51b4
|
|
| MD5 |
70be2472d37b43b84fc4b7df03fcc851
|
|
| BLAKE2b-256 |
6bf7d724c40f720310611aed27859f2e2ed331cd8cc23418c7fafff452985465
|