A lightweight framework for building API endpoints using Python's native libraries.
Project description
LightAPI: Fast Python REST API Framework with Async, CRUD, OpenAPI, JWT, and YAML
LightAPI is a fast, async-ready Python REST API framework that lets you instantly generate CRUD endpoints from SQLAlchemy models or your existing database schema. With built-in OpenAPI documentation, JWT authentication, Redis caching, and YAML-driven configuration, LightAPI is the best choice for building scalable, production-ready APIs in Python.
๐ Table of Contents
- Why LightAPI?
- Who is LightAPI for?
- โจ Features Overview
- ๐ ๏ธ Installation
- โก Quick Start
- ๐ Feature Documentation
- ๐ Examples
- ๐งช Testing
- ๐ง Configuration
- ๐ Deployment
- โ FAQ
- ๐ Performance
- ๐ค Contributing
- ๐ License
Why LightAPI?
LightAPI is a modern, async-ready Python REST API framework designed for rapid development and production use. It combines the best features of FastAPI, Flask, and Django REST Framework while maintaining simplicity and performance.
๐ฏ Key Benefits
- โก Instant CRUD APIs: Generate full REST APIs from SQLAlchemy models in seconds
- ๐ High Performance: Built on Starlette/Uvicorn with async support
- ๐ Auto Documentation: OpenAPI/Swagger docs generated automatically
- ๐ Security First: Built-in JWT authentication and CORS support
- ๐พ Smart Caching: Redis integration with intelligent cache management
- ๐ Advanced Queries: Filtering, pagination, sorting, and search out of the box
- โ Data Validation: Comprehensive request/response validation
- ๐ Configuration Driven: YAML-based API generation
- ๐ง Extensible: Custom middleware and endpoint customization
Who is LightAPI for?
- ๐ข Backend developers who want to ship APIs fast, with minimal code
- ๐ Data engineers needing to expose existing databases as RESTful services
- ๐ Prototypers and startups who want to iterate quickly and scale later
- ๐๏ธ Enterprise teams building microservices and internal APIs
- ๐ Educators teaching REST API development and best practices
- ๐ Migration projects moving from other frameworks to modern async Python
โจ Features Overview
๐ง Core Features
- Automatic CRUD Endpoints: Generate REST APIs from SQLAlchemy models
- Async/Await Support: High-performance async request handling
- OpenAPI Documentation: Auto-generated Swagger UI and ReDoc
- JWT Authentication: Secure token-based authentication
- CORS Support: Cross-origin resource sharing configuration
- Redis Caching: Intelligent caching with TTL and invalidation
- Request Validation: Comprehensive input validation and error handling
- Database Agnostic: Works with PostgreSQL, MySQL, SQLite, and more
๐ Advanced Features
- Advanced Filtering: Complex queries with multiple criteria
- Pagination & Sorting: Efficient data retrieval with customizable pagination
- Search Functionality: Full-text search across multiple fields
- YAML Configuration: Define APIs without writing Python code
- Custom Middleware: Extensible middleware system
- Error Handling: Comprehensive error responses and logging
- Performance Monitoring: Built-in performance metrics and caching stats
- Hot Reloading: Development server with auto-reload
๐ ๏ธ Installation
Basic Installation
pip install lightapi
With Optional Dependencies
# For Redis caching
pip install lightapi[redis]
# For PostgreSQL support
pip install lightapi[postgresql]
# For MySQL support
pip install lightapi[mysql]
# All features
pip install lightapi[all]
Development Installation
git clone https://github.com/iklobato/lightapi.git
cd lightapi
pip install -e .
โก Quick Start
1. Basic CRUD API (30 seconds)
from lightapi import LightApi
from lightapi.rest import RestEndpoint
from lightapi.models import Base
from sqlalchemy import Column, Integer, String, Float
class Product(Base, RestEndpoint):
__tablename__ = "products"
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
price = Column(Float, nullable=False)
category = Column(String(50))
# Create API
app = LightApi(database_url="sqlite:///./products.db")
app.register(Product)
if __name__ == "__main__":
app.run()
That's it! You now have a full REST API with:
GET /products- List all productsGET /products/{id}- Get specific productPOST /products- Create new productPUT /products/{id}- Update productDELETE /products/{id}- Delete product- Auto-generated OpenAPI docs at
/docs
2. Advanced API with Authentication & Caching
from lightapi import LightApi
from lightapi.rest import RestEndpoint
from lightapi.models import Base
from lightapi.cache import cache_manager
from sqlalchemy import Column, Integer, String, Float, DateTime
from datetime import datetime
class User(Base, RestEndpoint):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(50), nullable=False, unique=True)
email = Column(String(100), nullable=False, unique=True)
created_at = Column(DateTime, default=datetime.utcnow)
def get(self, request):
"""Custom GET with caching"""
user_id = request.path_params.get('id')
if user_id:
# Try cache first
cache_key = f"user:{user_id}"
cached_user = cache_manager.get(cache_key)
if cached_user:
return cached_user
# Get from database and cache
user = self.get_by_id(int(user_id))
if user:
user_data = {
"id": user.id,
"username": user.username,
"email": user.email,
"created_at": user.created_at.isoformat()
}
cache_manager.set(cache_key, user_data, ttl=300) # 5 minutes
return user_data
return {"error": "User not found"}, 404
return super().get(request)
# Create API with advanced features
app = LightApi(
database_url="postgresql://user:pass@localhost/mydb",
swagger_title="Advanced User API",
cors_origins=["http://localhost:3000"],
jwt_secret="your-secret-key"
)
app.register(User)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
๐ Feature Documentation
๐ง Basic CRUD Operations
LightAPI automatically generates CRUD endpoints for your SQLAlchemy models:
from lightapi import LightApi
from lightapi.rest import RestEndpoint
from lightapi.models import Base
from sqlalchemy import Column, Integer, String, Float, Boolean, DateTime
from datetime import datetime
class Product(Base, RestEndpoint):
__tablename__ = "products"
id = Column(Integer, primary_key=True)
name = Column(String(200), nullable=False)
description = Column(String(1000))
price = Column(Float, nullable=False)
category = Column(String(50), nullable=False)
in_stock = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
app = LightApi(database_url="sqlite:///./products.db")
app.register(Product)
Generated Endpoints:
GET /products- List products with paginationGET /products/{id}- Get specific productPOST /products- Create new productPUT /products/{id}- Update existing productDELETE /products/{id}- Delete product
Example Usage:
# Create a product
curl -X POST http://localhost:8000/products \
-H "Content-Type: application/json" \
-d '{"name": "Laptop", "price": 999.99, "category": "electronics"}'
# Get all products
curl http://localhost:8000/products
# Get specific product
curl http://localhost:8000/products/1
# Update product
curl -X PUT http://localhost:8000/products/1 \
-H "Content-Type: application/json" \
-d '{"name": "Gaming Laptop", "price": 1299.99}'
# Delete product
curl -X DELETE http://localhost:8000/products/1
โก Async/Await Support
LightAPI supports async endpoints for high-performance applications:
import asyncio
from lightapi.rest import RestEndpoint
class AsyncProduct(Base, RestEndpoint):
__tablename__ = "async_products"
id = Column(Integer, primary_key=True)
name = Column(String(100))
async def get(self, request):
"""Async GET endpoint"""
# Simulate async database query
await asyncio.sleep(0.1)
product_id = request.path_params.get('id')
if product_id:
# Async processing
result = await self.async_get_product(int(product_id))
return result
# List all products
products = await self.async_get_all_products()
return {"products": products}
async def post(self, request):
"""Async POST endpoint"""
data = await request.json()
# Async validation
await self.async_validate(data)
# Async save
new_product = await self.async_create_product(data)
return new_product, 201
async def async_get_product(self, product_id):
"""Simulate async database lookup"""
await asyncio.sleep(0.05)
return {
"id": product_id,
"name": f"Async Product {product_id}",
"processing_time": 0.05
}
async def async_get_all_products(self):
"""Simulate async list query"""
await asyncio.sleep(0.1)
return [
{"id": i, "name": f"Product {i}"}
for i in range(1, 11)
]
async def async_validate(self, data):
"""Async validation"""
await asyncio.sleep(0.02)
if not data.get('name'):
raise ValueError("Name is required")
async def async_create_product(self, data):
"""Async product creation"""
await asyncio.sleep(0.05)
return {
"id": 999,
"name": data['name'],
"created_at": datetime.utcnow().isoformat()
}
Benefits of Async:
- Handle thousands of concurrent requests
- Non-blocking I/O operations
- Better resource utilization
- Improved response times under load
๐ OpenAPI/Swagger Documentation
LightAPI automatically generates comprehensive API documentation:
app = LightApi(
database_url="sqlite:///./api.db",
swagger_title="My Awesome API",
swagger_version="2.0.0",
swagger_description="A comprehensive REST API built with LightAPI",
enable_swagger=True # Default: True
)
Documentation Features:
- Swagger UI: Interactive API explorer at
/docs - ReDoc: Alternative documentation at
/redoc - OpenAPI Schema: JSON schema at
/openapi.json - Auto-generated: Models, endpoints, and validation rules
- Customizable: Add descriptions, examples, and metadata
Access Documentation:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc - OpenAPI JSON:
http://localhost:8000/openapi.json
๐ JWT Authentication
Secure your API with JWT token authentication:
import os
from lightapi import LightApi
from lightapi.auth import AuthEndpoint
# Set JWT secret
os.environ['LIGHTAPI_JWT_SECRET'] = 'your-super-secret-key'
class User(Base, RestEndpoint):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(50), unique=True)
password_hash = Column(String(255))
class AuthUser(AuthEndpoint):
"""Authentication endpoint"""
__tablename__ = "auth_users"
id = Column(Integer, primary_key=True)
username = Column(String(50))
role = Column(String(20), default="user")
app = LightApi(
database_url="sqlite:///./secure_api.db",
jwt_secret="your-super-secret-key"
)
app.register(User)
app.register(AuthUser)
Authentication Flow:
- Login:
POST /authendpointwith credentials - Get Token: Receive JWT token in response
- Use Token: Include in
Authorization: Bearer <token>header - Access Protected: Access protected endpoints
Example Usage:
# Login and get token
curl -X POST http://localhost:8000/authendpoint \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "secret"}'
# Response: {"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."}
# Use token to access protected endpoint
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
http://localhost:8000/secretresource
JWT Features:
- Token expiration handling
- Role-based access control
- Automatic token validation
- Secure secret key management
- Custom claims support
๐ CORS Support
Enable Cross-Origin Resource Sharing for web applications:
app = LightApi(
database_url="sqlite:///./api.db",
cors_origins=[
"http://localhost:3000", # React dev server
"http://localhost:8080", # Vue dev server
"https://myapp.com", # Production frontend
"https://*.myapp.com" # Subdomains
]
)
CORS Configuration:
# Allow all origins (development only)
app = LightApi(cors_origins=["*"])
# Specific origins
app = LightApi(cors_origins=[
"http://localhost:3000",
"https://myapp.com"
])
# Environment-based configuration
import os
cors_origins = os.getenv('CORS_ORIGINS', '').split(',')
app = LightApi(cors_origins=cors_origins)
๐พ Redis Caching
Boost performance with intelligent Redis caching:
from lightapi.cache import cache_manager
class CachedProduct(Base, RestEndpoint):
__tablename__ = "cached_products"
id = Column(Integer, primary_key=True)
name = Column(String(100))
price = Column(Float)
def get(self, request):
"""GET with caching"""
product_id = request.path_params.get('id')
if product_id:
# Try cache first
cache_key = f"product:{product_id}"
cached_product = cache_manager.get(cache_key)
if cached_product:
return {
**cached_product,
"cache_hit": True,
"ttl_remaining": cache_manager.ttl(cache_key)
}
# Get from database
product = self.get_by_id(int(product_id))
if product:
product_data = {
"id": product.id,
"name": product.name,
"price": product.price
}
# Cache for 5 minutes
cache_manager.set(cache_key, product_data, ttl=300)
return {
**product_data,
"cache_hit": False,
"cached_for": 300
}
return {"error": "Product not found"}, 404
# List with caching
cache_key = "products:list"
cached_list = cache_manager.get(cache_key)
if cached_list:
return {
**cached_list,
"cache_hit": True
}
# Get from database and cache
products = self.get_all()
result = {
"products": [
{"id": p.id, "name": p.name, "price": p.price}
for p in products
]
}
cache_manager.set(cache_key, result, ttl=120) # 2 minutes
return {
**result,
"cache_hit": False
}
def post(self, request):
"""POST with cache invalidation"""
result = super().post(request)
# Invalidate list cache when creating new product
cache_manager.delete("products:list")
return result
def put(self, request):
"""PUT with cache update"""
product_id = request.path_params.get('id')
result = super().put(request)
# Update cache
if product_id:
cache_key = f"product:{product_id}"
cache_manager.delete(cache_key) # Or update with new data
cache_manager.delete("products:list") # Invalidate list
return result
Caching Features:
- TTL Support: Automatic expiration
- Cache Invalidation: Smart cache clearing
- Pattern Deletion: Clear multiple keys at once
- Cache Statistics: Monitor hit/miss rates
- JSON Serialization: Automatic data serialization
- Key Isolation: Prevent key conflicts
Cache Management:
# Cache statistics
stats = cache_manager.get_info()
# Clear all caches
cache_manager.clear_all()
# Delete by pattern
cache_manager.delete_pattern("products:*")
# Check TTL
remaining = cache_manager.ttl("product:123")
๐ Advanced Filtering & Pagination
Powerful querying capabilities out of the box:
class AdvancedProduct(Base, RestEndpoint):
__tablename__ = "advanced_products"
id = Column(Integer, primary_key=True)
name = Column(String(200))
price = Column(Float)
category = Column(String(50))
brand = Column(String(100))
rating = Column(Float)
in_stock = Column(Boolean)
created_at = Column(DateTime)
def get(self, request):
"""Advanced filtering and pagination"""
params = request.query_params
# Pagination
page = int(params.get('page', 1))
page_size = int(params.get('page_size', 10))
# Filtering
filters = {}
if params.get('category'):
filters['category'] = params.get('category')
if params.get('brand'):
filters['brand'] = params.get('brand')
if params.get('min_price'):
filters['min_price'] = float(params.get('min_price'))
if params.get('max_price'):
filters['max_price'] = float(params.get('max_price'))
if params.get('min_rating'):
filters['min_rating'] = float(params.get('min_rating'))
if params.get('in_stock') is not None:
filters['in_stock'] = params.get('in_stock').lower() == 'true'
# Text search
search = params.get('search')
if search:
filters['search'] = search
# Sorting
sort_by = params.get('sort_by', 'id')
sort_order = params.get('sort_order', 'asc')
# Apply filters and get results
products = self.filter_products(filters, sort_by, sort_order)
# Pagination
total_count = len(products)
start_index = (page - 1) * page_size
end_index = start_index + page_size
paginated_products = products[start_index:end_index]
return {
"products": paginated_products,
"pagination": {
"page": page,
"page_size": page_size,
"total_count": total_count,
"total_pages": (total_count + page_size - 1) // page_size,
"has_next": page * page_size < total_count,
"has_prev": page > 1
},
"filters": filters,
"sorting": {
"sort_by": sort_by,
"sort_order": sort_order
}
}
Query Examples:
# Basic pagination
GET /products?page=1&page_size=20
# Filter by category
GET /products?category=electronics
# Price range filter
GET /products?min_price=100&max_price=500
# Multiple filters with sorting
GET /products?category=electronics&brand=apple&min_rating=4.0&sort_by=price&sort_order=desc
# Text search
GET /products?search=laptop
# Complex query
GET /products?category=electronics&min_price=200&max_price=1000&in_stock=true&sort_by=rating&sort_order=desc&page=2&page_size=15
โ Request Validation
Comprehensive input validation and error handling:
import re
from datetime import datetime
class ValidatedUser(Base, RestEndpoint):
__tablename__ = "validated_users"
id = Column(Integer, primary_key=True)
username = Column(String(50), nullable=False)
email = Column(String(100), nullable=False)
age = Column(Integer)
salary = Column(Float)
def validate_data(self, data, method='POST'):
"""Comprehensive validation"""
errors = []
# Username validation
username = data.get('username', '').strip()
if method == 'POST' and not username:
errors.append("Username is required")
elif username:
if len(username) < 3:
errors.append("Username must be at least 3 characters")
elif len(username) > 50:
errors.append("Username must be no more than 50 characters")
elif not re.match(r'^[a-zA-Z0-9_]+$', username):
errors.append("Username can only contain letters, numbers, and underscores")
# Email validation
email = data.get('email', '').strip()
if method == 'POST' and not email:
errors.append("Email is required")
elif email:
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, email):
errors.append("Invalid email format")
# Age validation
age = data.get('age')
if age is not None:
try:
age = int(age)
if age < 0:
errors.append("Age cannot be negative")
elif age > 150:
errors.append("Age cannot be more than 150")
except (ValueError, TypeError):
errors.append("Age must be a valid integer")
# Salary validation
salary = data.get('salary')
if salary is not None:
try:
salary = float(salary)
if salary < 0:
errors.append("Salary cannot be negative")
except (ValueError, TypeError):
errors.append("Salary must be a valid number")
return errors
def post(self, request):
"""Create with validation"""
try:
data = request.data
# Validate
errors = self.validate_data(data, method='POST')
if errors:
return {
"error": "Validation failed",
"details": errors,
"received_data": data
}, 400
# Create user
new_user = {
"id": 123,
"username": data['username'].strip(),
"email": data['email'].strip(),
"age": int(data.get('age', 0)) if data.get('age') else None,
"salary": float(data.get('salary', 0)) if data.get('salary') else None,
"created_at": datetime.utcnow().isoformat()
}
return new_user, 201
except Exception as e:
return {
"error": "Internal server error",
"message": str(e)
}, 500
def put(self, request):
"""Update with validation"""
user_id = request.path_params.get('id')
if not user_id:
return {"error": "User ID is required"}, 400
try:
user_id = int(user_id)
except ValueError:
return {"error": "Invalid user ID format"}, 400
data = request.data
errors = self.validate_data(data, method='PUT')
if errors:
return {
"error": "Validation failed",
"details": errors
}, 400
# Update logic here
return {"message": "User updated successfully"}
Validation Features:
- Field Validation: Required fields, length limits, format checks
- Type Validation: Automatic type conversion and validation
- Custom Rules: Business logic validation
- Error Aggregation: Multiple validation errors in single response
- Method-Specific: Different validation for POST/PUT/PATCH
- Detailed Errors: Clear error messages with field information
๐ YAML Configuration
Create REST APIs without writing Python code! LightAPI can automatically generate full CRUD APIs from existing database tables using simple YAML configuration files.
Basic YAML Configuration
# config.yaml
database_url: "sqlite:///my_app.db"
swagger_title: "My API"
swagger_version: "1.0.0"
swagger_description: "API generated from YAML configuration"
enable_swagger: true
tables:
- name: users
crud: [get, post, put, delete]
- name: posts
crud: [get, post, put]
- name: comments
crud: [get] # Read-only
Advanced YAML Configuration
# advanced_config.yaml
database_url: "${DATABASE_URL}" # Environment variable
swagger_title: "E-commerce API"
swagger_version: "2.0.0"
swagger_description: |
E-commerce API with role-based permissions
## Permission Levels
- Admin: Full user management
- Manager: Product and inventory management
- Customer: Order creation and viewing
enable_swagger: true
tables:
# ADMIN LEVEL - Full access
- name: users
crud: [get, post, put, patch, delete]
# MANAGER LEVEL - Product management
- name: products
crud: [get, post, put, patch, delete]
# CUSTOMER LEVEL - Limited operations
- name: orders
crud: [get, post, patch] # Create orders, update status only
# READ-ONLY - Audit trail
- name: audit_log
crud: [get]
Database Support
# SQLite
database_url: "sqlite:///app.db"
# PostgreSQL
database_url: "postgresql://user:pass@localhost:5432/db"
# MySQL
database_url: "mysql+pymysql://user:pass@localhost:3306/db"
# Environment variables
database_url: "${DATABASE_URL}"
Run YAML-Configured API
from lightapi import LightApi
# Create API from YAML configuration
app = LightApi.from_config('config.yaml')
app.run()
That's it! Your API is now running with:
- Full CRUD operations based on your configuration
- Automatic input validation from database schema
- Interactive Swagger documentation at
/docs - Proper HTTP status codes and error handling
CRUD Operations
Each CRUD operation maps to HTTP methods:
| CRUD | HTTP Method | Endpoint | Description |
|---|---|---|---|
get |
GET | /table/ |
List all records |
get |
GET | /table/{id} |
Get specific record |
post |
POST | /table/ |
Create new record |
put |
PUT | /table/{id} |
Update entire record |
patch |
PATCH | /table/{id} |
Partially update record |
delete |
DELETE | /table/{id} |
Delete record |
Configuration Patterns
# Full CRUD
- name: users
crud: [get, post, put, patch, delete]
# Read-only (analytics, reports)
- name: analytics
crud: [get]
# Create + Read (blog posts)
- name: posts
crud: [get, post]
# No delete (data integrity)
- name: categories
crud: [get, post, put, patch]
# Status updates only
- name: orders
crud: [get, patch]
Environment-Based Deployment
# development.yaml
database_url: "${DEV_DATABASE_URL}"
enable_swagger: true
tables:
- name: users
crud: [get, post, put, patch, delete] # Full access in dev
# production.yaml
database_url: "${PROD_DATABASE_URL}"
enable_swagger: false # Disabled in production
tables:
- name: users
crud: [get, patch] # Limited access in production
Key Benefits:
- Zero Python Code: Define APIs using only YAML
- Database Reflection: Automatically discovers existing tables and schemas
- Environment Variables: Flexible deployment across dev/staging/production
- Role-Based Permissions: Different CRUD operations per table
- Production Ready: Proper error handling and validation
๐ง Custom Middleware
Extend LightAPI with custom middleware:
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
import time
import logging
class PerformanceMiddleware(BaseHTTPMiddleware):
"""Log request performance"""
async def dispatch(self, request: Request, call_next):
start_time = time.time()
# Process request
response = await call_next(request)
# Calculate duration
duration = time.time() - start_time
# Log performance
logging.info(f"{request.method} {request.url.path} - {duration:.3f}s")
# Add performance header
response.headers["X-Process-Time"] = str(duration)
return response
class AuthenticationMiddleware(BaseHTTPMiddleware):
"""Custom authentication middleware"""
def __init__(self, app, excluded_paths=None):
super().__init__(app)
self.excluded_paths = excluded_paths or ['/docs', '/redoc', '/openapi.json']
async def dispatch(self, request: Request, call_next):
# Skip authentication for excluded paths
if request.url.path in self.excluded_paths:
return await call_next(request)
# Check for API key
api_key = request.headers.get('X-API-Key')
if not api_key:
return Response("API Key required", status_code=401)
# Validate API key (implement your logic)
if not self.validate_api_key(api_key):
return Response("Invalid API Key", status_code=401)
# Add user info to request
request.state.user = self.get_user_from_api_key(api_key)
return await call_next(request)
def validate_api_key(self, api_key):
# Implement API key validation
return api_key == "valid-api-key"
def get_user_from_api_key(self, api_key):
# Get user information from API key
return {"id": 1, "username": "api_user"}
# Add middleware to app
app = LightApi(database_url="sqlite:///./api.db")
app.add_middleware(PerformanceMiddleware)
app.add_middleware(AuthenticationMiddleware, excluded_paths=['/docs', '/health'])
๐ Examples
LightAPI includes comprehensive examples for all features:
๐ Example Files
examples/rest_crud_basic.py- Basic CRUD operationsexamples/async_performance.py- Async/await performance demoexamples/authentication_jwt.py- JWT authenticationexamples/caching_redis_custom.py- Redis caching strategiesexamples/advanced_filtering_pagination.py- Complex queriesexamples/advanced_validation.py- Comprehensive validationexamples/yaml_configuration.py- YAML-driven API generationexamples/middleware_custom.py- Custom middlewareexamples/swagger_openapi_docs.py- Documentation customization
๐ Running Examples
# Clone the repository
git clone https://github.com/iklobato/lightapi.git
cd lightapi
# Install dependencies
pip install -e .
# Run basic CRUD example
python examples/rest_crud_basic.py
# Run async performance example
python examples/async_performance.py
# Run JWT authentication example
python examples/authentication_jwt.py
# Run caching example (requires Redis)
redis-server # Start Redis in another terminal
python examples/caching_redis_custom.py
๐งช Testing
LightAPI includes comprehensive test coverage:
๐ง Running Tests
# Install test dependencies
pip install pytest pytest-asyncio httpx
# Run all tests
pytest
# Run specific test categories
pytest tests/test_crud.py
pytest tests/test_auth.py
pytest tests/test_caching.py
pytest tests/test_validation.py
# Run with coverage
pytest --cov=lightapi --cov-report=html
๐ Test Coverage
LightAPI maintains high test coverage across all features:
- โ CRUD operations
- โ Async functionality
- โ JWT authentication
- โ Redis caching
- โ Request validation
- โ Error handling
- โ Middleware
- โ Configuration
๐ง Configuration
๐ Environment Variables
# Database
export LIGHTAPI_DATABASE_URL="postgresql://user:pass@localhost/db"
# Server
export LIGHTAPI_HOST="0.0.0.0"
export LIGHTAPI_PORT="8000"
export LIGHTAPI_DEBUG="true"
# JWT Authentication
export LIGHTAPI_JWT_SECRET="your-super-secret-key"
# CORS
export LIGHTAPI_CORS_ORIGINS='["http://localhost:3000", "https://myapp.com"]'
# Swagger
export LIGHTAPI_SWAGGER_TITLE="My API"
export LIGHTAPI_SWAGGER_VERSION="1.0.0"
export LIGHTAPI_ENABLE_SWAGGER="true"
# Caching
export LIGHTAPI_CACHE_TIMEOUT="3600"
โ๏ธ Configuration Class
from lightapi.config import Config
# Custom configuration
config = Config()
config.database_url = "postgresql://localhost/mydb"
config.jwt_secret = "my-secret"
config.cors_origins = ["http://localhost:3000"]
app = LightApi(config=config)
๐ Deployment
๐ณ Docker Deployment
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
# docker-compose.yml
version: '3.8'
services:
api:
build: .
ports:
- "8000:8000"
environment:
- LIGHTAPI_DATABASE_URL=postgresql://postgres:password@db:5432/mydb
- LIGHTAPI_JWT_SECRET=your-secret-key
depends_on:
- db
- redis
db:
image: postgres:13
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
โ๏ธ Cloud Deployment
Heroku:
# Install Heroku CLI
heroku create my-lightapi-app
heroku addons:create heroku-postgresql:hobby-dev
heroku addons:create heroku-redis:hobby-dev
heroku config:set LIGHTAPI_JWT_SECRET=your-secret-key
git push heroku main
AWS Lambda:
# lambda_handler.py
from mangum import Mangum
from main import app
handler = Mangum(app)
โ FAQ
Q: How does LightAPI compare to FastAPI?
A: LightAPI builds on FastAPI's foundation but focuses specifically on rapid CRUD API development. While FastAPI is a general-purpose framework, LightAPI provides:
- Automatic CRUD endpoint generation
- Built-in caching with Redis
- YAML-driven API configuration
- Advanced filtering and pagination out of the box
- Simplified authentication setup
Q: Can I use LightAPI with existing databases?
A: Yes! LightAPI works with any SQLAlchemy-compatible database. You can:
- Use existing SQLAlchemy models
- Generate models from existing database schemas
- Configure database connections via environment variables
- Support PostgreSQL, MySQL, SQLite, and more
Q: Is LightAPI production-ready?
A: Absolutely! LightAPI is built on proven technologies:
- Starlette/Uvicorn for high performance
- SQLAlchemy for robust database operations
- Pydantic for data validation
- Redis for caching
- Comprehensive error handling and logging
Q: How do I handle database migrations?
A: LightAPI integrates with Alembic for database migrations:
# Initialize migrations
alembic init migrations
# Create migration
alembic revision --autogenerate -m "Add users table"
# Apply migrations
alembic upgrade head
Q: Can I customize the generated endpoints?
A: Yes! You have full control:
- Override any HTTP method in your RestEndpoint class
- Add custom validation logic
- Implement custom business logic
- Add middleware for cross-cutting concerns
- Customize response formats
Q: How do I handle file uploads?
A: LightAPI supports file uploads through Starlette:
from starlette.requests import Request
class FileUpload(Base, RestEndpoint):
def post(self, request: Request):
form = await request.form()
file = form["file"]
# Process file
content = await file.read()
return {"filename": file.filename, "size": len(content)}
๐ Performance
LightAPI is designed for high performance:
๐ Benchmarks
- Requests/second: 10,000+ (simple CRUD operations)
- Async support: Handle thousands of concurrent connections
- Memory usage: Low memory footprint with efficient caching
- Response times: Sub-millisecond for cached responses
โก Performance Tips
- Use async endpoints for I/O-heavy operations
- Enable Redis caching for frequently accessed data
- Implement pagination for large datasets
- Use database indexes for filtered fields
- Configure connection pooling for high-traffic applications
๐ค Contributing
We welcome contributions! Here's how to get started:
๐ง Development Setup
# Clone repository
git clone https://github.com/iklobato/lightapi.git
cd lightapi
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run linting
flake8 lightapi/
black lightapi/
๐ Contribution Guidelines
- Fork the repository
- Create a feature branch
- Write tests for new features
- Ensure all tests pass
- Submit a pull request
๐ Bug Reports
Please use GitHub Issues to report bugs. Include:
- Python version
- LightAPI version
- Minimal code example
- Error messages and stack traces
๐ License
LightAPI is released under the MIT License. See LICENSE for details.
๐ Acknowledgments
LightAPI is built on the shoulders of giants:
- FastAPI - For the excellent foundation and inspiration
- Starlette - For the high-performance ASGI framework
- SQLAlchemy - For the powerful ORM
- Pydantic - For data validation
- Uvicorn - For the lightning-fast ASGI server
๐ Support
- Documentation: https://lightapi.readthedocs.io
- GitHub Issues: https://github.com/iklobato/lightapi/issues
- Discussions: https://github.com/iklobato/lightapi/discussions
- Email: support@lightapi.dev
Ready to build lightning-fast APIs? Get started with LightAPI today! โก
pip install lightapi
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 lightapi-0.1.12.tar.gz.
File metadata
- Download URL: lightapi-0.1.12.tar.gz
- Upload date:
- Size: 428.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85d4259edc50e10612fac3c798babc9951625cf93475e59427145f29209b9037
|
|
| MD5 |
8b59c4d8a03ca2e1e89dfe608c404dd6
|
|
| BLAKE2b-256 |
178663f0270dbf29711f5fe2bb90823bcaf1f9afb849cba31a10abc886be57c6
|
File details
Details for the file lightapi-0.1.12-py3-none-any.whl.
File metadata
- Download URL: lightapi-0.1.12-py3-none-any.whl
- Upload date:
- Size: 45.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed3b02af76f55b7dd5f65620cf0425204fc45e5818375e2179a7bc4cc76a2cfc
|
|
| MD5 |
c69c63ef3b0206263fe0fdd3f6056d6b
|
|
| BLAKE2b-256 |
2f5821cd7725da290f2db85eca5ed07fbe0bdd06d31458b3dd6c6b22c4b4fa25
|