code_hacker web Framework built for learning purposes.
Project description
Code Hacker Framework
A lightweight, modern Python web framework for building fast and flexible web applications and APIs.
Features
- 🚀 Simple Routing: Easy-to-use route decorators and function/class-based handlers
- 🎨 Template Support: Built-in Jinja2 template rendering
- 📦 Static Files: Automatic static file serving with WhiteNoise
- 🔧 Middleware: Custom middleware support for request/response processing
- ✅ Type-Safe Responses: JSON, HTML, and text response helpers
- 🧪 Testing: Built-in test client for easy testing
- 📝 Flexible Handlers: Support for both function-based and class-based handlers
- 🛡️ Exception Handling: Custom exception handlers for error management
Installation
pip install code-hacker
Or install from source:
git clone <repository-url>
cd backend_frame_work
pip install -e .
Quick Start
Basic Application
from code_hacker import Application as API
# Create application instance
app = API(templates_dir="templates", static_dir="static")
# Define a route with decorator
@app.route("/")
def home(request, response):
response.text = "Hello, World!"
# Run the application
if __name__ == "__main__":
from wsgiref.simple_server import make_server
with make_server("localhost", 8000, app) as server:
print("Server running on http://localhost:8000")
server.serve_forever()
Using with a WSGI Server
from code_hacker import Application as API
app = API()
@app.route("/hello")
def hello_handler(request, response):
response.text = "Hello from Code Hacker!"
# Use with Gunicorn, uWSGI, or any WSGI server
# gunicorn app:app
Routing
Function-Based Routes
from code_hacker import Application as API
app = API()
# Simple GET route
@app.route("/home")
def home(request, response):
response.text = "Welcome Home!"
# Route with URL parameters
@app.route("/users/{name}")
def user_profile(request, response, name):
response.text = f"Hello, {name}!"
# Route with integer parameter
@app.route("/posts/{id:d}")
def get_post(request, response, id):
response.json = {"id": id, "title": "Post Title"}
# Route with allowed methods
@app.route("/api/data", allowed_methods=["GET", "POST"])
def data_handler(request, response):
if request.method == "GET":
response.json = {"data": "some data"}
elif request.method == "POST":
response.json = {"status": "created"}
Django-Style Route Registration
from code_hacker import Application as API
app = API()
def my_handler(request, response):
response.text = "This is a Django-style route"
# Register route explicitly
app.add_route("/my-route", my_handler)
# With allowed methods
app.add_route("/restricted", my_handler, allowed_methods=["POST", "PUT"])
Class-Based Handlers
from code_hacker import Application as API
app = API()
# Class-based handler (RESTful style)
@app.route("/books")
class BooksResource:
def get(self, request, response):
"""Handle GET /books"""
response.json = {"books": []}
def post(self, request, response):
"""Handle POST /books"""
response.json = {"status": "created"}
def put(self, request, response):
"""Handle PUT /books"""
response.json = {"status": "updated"}
def delete(self, request, response):
"""Handle DELETE /books"""
response.status_code = 204
# Class handler with parameters
@app.route("/users/{id:d}")
class UserResource:
def get(self, request, response, id):
response.json = {"id": id, "name": "User"}
def put(self, request, response, id):
response.json = {"id": id, "updated": True}
Response Types
JSON Responses
@app.route("/api/users")
def get_users(request, response):
response.json = {
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
}
HTML Responses
@app.route("/")
def index(request, response):
response.html = app.template("index.html", context={
"title": "My Website",
"name": "Code Hacker"
})
Text Responses
@app.route("/status")
def status(request, response):
response.text = "Server is running!"
Custom Body and Headers
@app.route("/custom")
def custom(request, response):
response.body = b"Custom binary data"
response.content_type = "application/octet-stream"
response.headers["X-Custom-Header"] = "Custom Value"
response.status_code = 200
Templates
Code Hacker uses Jinja2 for template rendering.
Setup Templates
from code_hacker import Application as API
app = API(templates_dir="templates") # Specify your templates directory
Template Example
templates/index.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Welcome to {{ name }}</h1>
</body>
</html>
app.py:
@app.route("/")
def index(request, response):
response.html = app.template("index.html", context={
"title": "Home Page",
"name": "Code Hacker"
})
Static Files
Static files are automatically served from the /static path.
Setup Static Files
from code_hacker import Application as API
app = API(static_dir="static") # Your static files directory
Accessing Static Files
<!-- In your templates -->
<link rel="stylesheet" href="/static/css/main.css">
<script src="/static/js/app.js"></script>
Middleware
Create custom middleware to process requests and responses.
Basic Middleware
from code_hacker import Application as API, Middleware
import time
app = API()
class TimingMiddleware(Middleware):
def process_request(self, request):
# Called before request is handled
request.start_time = time.time()
def process_response(self, request, response):
# Called after request is handled
if hasattr(request, 'start_time'):
duration = time.time() - request.start_time
response.headers['X-Response-Time'] = f"{duration:.4f}s"
# Register middleware
app.add_middleware(TimingMiddleware)
Multiple Middleware
class LoggingMiddleware(Middleware):
def process_request(self, request):
print(f"[{time.time()}] {request.method} {request.path}")
def process_response(self, request, response):
print(f"[{time.time()}] Response: {response.status_code}")
class AuthMiddleware(Middleware):
def process_request(self, request):
# Check authentication
token = request.headers.get("Authorization")
if not token:
raise ValueError("Unauthorized")
app.add_middleware(LoggingMiddleware)
app.add_middleware(AuthMiddleware)
Exception Handling
Register custom exception handlers to gracefully handle errors.
from code_hacker import Application as API
app = API()
def custom_exception_handler(request, response, exception):
response.status_code = 500
response.json = {
"error": str(exception),
"type": type(exception).__name__
}
app.add_exception_handler(custom_exception_handler)
@app.route("/error")
def error_handler(request, response):
raise ValueError("Something went wrong!")
Testing
Code Hacker includes a built-in test client for easy testing.
Basic Test Example
import pytest
from code_hacker import Application as API
@pytest.fixture
def api():
return API()
@pytest.fixture
def client(api):
return api.test_session()
def test_home_route(api, client):
@api.route("/")
def home(request, response):
response.text = "Hello, World!"
response = client.get("http://testserver/")
assert response.text == "Hello, World!"
assert response.status_code == 200
def test_json_response(api, client):
@api.route("/api/data")
def data(request, response):
response.json = {"key": "value"}
response = client.get("http://testserver/api/data")
assert response.json()["key"] == "value"
assert response.headers["Content-Type"] == "application/json"
Running Tests
pytest test_code_hacker.py
Complete Example Application
"""
Complete example application using Code Hacker Framework
"""
from code_hacker import Application as API, Middleware
import time
# Create application
app = API(templates_dir="templates", static_dir="static")
# Custom exception handler
def exception_handler(request, response, exception):
response.status_code = 500
response.text = f"Error: {str(exception)}"
app.add_exception_handler(exception_handler)
# Timing middleware
class TimingMiddleware(Middleware):
def process_request(self, req):
req.start_time = time.time()
def process_response(self, req, resp):
if hasattr(req, 'start_time'):
duration = time.time() - req.start_time
resp.headers['X-Response-Time'] = f"{duration:.4f}s"
app.add_middleware(TimingMiddleware)
# Routes
@app.route("/")
def home(request, response):
response.html = app.template("index.html", context={
"title": "Home",
"name": "Code Hacker"
})
@app.route("/api/users")
def get_users(request, response):
response.json = {
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
}
@app.route("/users/{id:d}")
class UserResource:
def get(self, request, response, id):
response.json = {"id": id, "name": f"User {id}"}
def delete(self, request, response, id):
response.status_code = 204
# Run server
if __name__ == "__main__":
from wsgiref.simple_server import make_server
with make_server("localhost", 8000, app) as server:
print("Server running on http://localhost:8000")
server.serve_forever()
Project Structure
project/
├── code_hacker/ # Framework package
│ ├── __init__.py
│ ├── api.py # Application class
│ ├── middleware.py # Middleware base class
│ └── response.py # Response class
├── app.py # Your application routes
├── conftest.py # Test fixtures
├── test_code_hacker.py # Test suite
├── static/ # Static files
│ └── main.css
└── templates/ # Jinja2 templates
└── index.html
API Reference
Application Class
Methods
route(path, allowed_methods=None): Decorator to register a routeadd_route(path, handler, allowed_methods=None): Explicitly register a routeadd_middleware(middleware_cls): Register middlewareadd_exception_handler(handler): Register exception handlertemplate(template_name, context=None): Render a Jinja2 templatetest_session(base_url="http://testserver"): Create a test client
Constructor Parameters
templates_dir="templates": Directory containing Jinja2 templatesstatic_dir="static": Directory containing static files
Response Object
Properties
text: Set plain text response (sets content-type to text/plain)json: Set JSON response (sets content-type to application/json)html: Set HTML response (sets content-type to text/html)body: Set raw body as bytescontent_type: Set content-type headerstatus_code: Set HTTP status code (default: 200)headers: Dictionary of custom headers
Middleware Class
Override these methods in your middleware:
process_request(request): Called before request handlingprocess_response(request, response): Called after request handling
Requirements
- Python 3.7+
- webob
- jinja2
- whitenoise
- parse
- requests
- wsgiadapter
License
MIT License
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please open an issue on the GitHub repository.
Project details
Release history Release notifications | RSS feed
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 code_hacker-0.0.1.tar.gz.
File metadata
- Download URL: code_hacker-0.0.1.tar.gz
- Upload date:
- Size: 9.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e51a3da7f16d06e5168e5e49ff0788d0e515d850e612fff4f1015de4acda9207
|
|
| MD5 |
daba725db50ca9023c42576464176124
|
|
| BLAKE2b-256 |
6eeeb57f0a5239a62c516e5521bc5056b29f296013ea7002e3a9dddfe909273c
|
File details
Details for the file code_hacker-0.0.1-py3-none-any.whl.
File metadata
- Download URL: code_hacker-0.0.1-py3-none-any.whl
- Upload date:
- Size: 7.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e19ce3072a0a75713270c812c882c25452de05b09f3058c9bdf409b724b28b95
|
|
| MD5 |
8081114c8066c01b527774c1afc0e8fe
|
|
| BLAKE2b-256 |
9f83b5f22e51da8ff51b91a0fe9d36b2d34aef3874d1ff35c622c908fee0f73d
|