🔥 FrameFire
FrameFire is a simple, lightweight, and fast WSGI web framework for Python. Built on top of WebOb, it provides an intuitive and expressive API for building modern web applications with minimal boilerplate.
✨ Features
- Expressive Routing: Decorator-based and method-based routing with support for dynamic URL parameters.
- Class-Based Handlers: Group related logic into class-based views (GET, POST, PUT, DELETE).
- Jinja2 Templates: Built-in support for rendering Jinja2 templates easily.
- Static Files: Automatic serving of static files out of the box using WhiteNoise.
- Middleware: Simple, class-based middleware architecture to process requests and responses.
- Custom Exception Handling: Catch and handle exceptions gracefully globally.
- Test Client Included: Built-in testing support making unit testing an absolute breeze.
- JSON & Text Helpers: Simplified response creation with
.json,.text, and.htmlattributes.
📦 Installation
FrameFire is available on PyPI. Install it using pip:
pip install framefire
🚀 Quickstart
Create a file named app.py:
from fireframe.app import FrameFire
app = FrameFire()
@app.route("/")
def home(request, response):
response.text = "Hello, FrameFire!"
@app.route("/json")
def json_endpoint(request, response):
response.json = {"framework": "FrameFire", "status": "Awesome"}
if __name__ == "__main__":
# You can use a WSGI server like Gunicorn to run the app
# gunicorn app:app
pass
Run the application using gunicorn:
gunicorn app:app
📖 User Guide
🛣️ Routing & Dynamic Parameters
You can easily capture values from the URL and pass them to your handlers:
@app.route("/hello/{name}")
def greeting(request, response, name):
response.text = f"Hello, {name}!"
🏛️ Class-Based Views
For more complex endpoints, you can use class-based handlers. Just implement methods corresponding to HTTP verbs:
@app.route("/books")
class BooksResource:
def get(self, request, response):
response.text = "List of books"
def post(self, request, response):
response.text = "Create a new book"
def delete(self, request, response):
response.text = "Delete a book"
🎨 Templates
FrameFire comes with Jinja2 integrated. By default, it looks for templates in a templates/ directory.
@app.route("/html")
def template_handler(request, response):
# Renders 'index.html' from the 'templates' directory
response.html = app.template(
"index.html",
context={"title": "FrameFire", "body": "Welcome to my app!"}
)
🗂️ Static Files
Static file serving is powered by WhiteNoise. Just place your static assets (CSS, JS, images) inside a static/ directory in the root of your project, and they will be served automatically!
<!-- Inside your template -->
<link rel="stylesheet" href="/style.css">
🛡️ Middleware
You can intercept and modify requests and responses globally using middleware:
from fireframe.middleware import Middleware
class LoggingMiddleware(Middleware):
def process_request(self, request):
print(f"Incoming Request: {request.method} {request.path}")
def process_response(self, request, response):
print(f"Outgoing Response: {response.status_code}")
app.add_middleware(LoggingMiddleware)
⚠️ Custom Exception Handling
Add a global exception handler to gracefully catch unexpected errors:
def on_exception(request, response, exc):
response.text = f"Something went wrong: {str(exc)}"
response.status_code = 500
app.add_exception_handler(on_exception)
🧪 Testing
FrameFire makes it easy to write unit tests using its built-in session client.
import pytest
from fireframe.app import FrameFire
@pytest.fixture
def app():
return FrameFire()
@pytest.fixture
def test_client(app):
return app.test_session()
def test_greeting(app, test_client):
@app.route("/hello/{name}")
def greeting(request, response, name):
response.text = f"Hello {name}"
response = test_client.get("http://testserver/hello/John")
assert response.text == "Hello John"
assert response.status_code == 200
📄 License
This project is licensed under the MIT License.
Metadata
Release files for framefire 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| framefire-0.2.0.tar.gz | 8.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| framefire-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.3 kB
Release files / framefire-0.2.0.tar.gz
| Download URL | framefire-0.2.0.tar.gz |
|---|---|
| Size | 8.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5567a583259dadaad9e49d559c372cb45c005cc31be3d1826aa424b5dfaa5eea
|
|
BLAKE2b-256 checksum How to use checksums |
b978161d5f50c25a4853ea2750eec59c04122d9878bfa4a148feb68e055cc610
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / framefire-0.2.0-py3-none-any.whl
| Download URL | framefire-0.2.0-py3-none-any.whl |
|---|---|
| Size | 7.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
12774812dbff2f5259823bb67da84acc39f52cab0fbed1fd8368facc5acda762
|
|
BLAKE2b-256 checksum How to use checksums |
594f7f29602ec10c487021e8d6c677c043d641f1e32a8c84b0270d6ec225d13e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|