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.
- Why LightAPI?
- Who is LightAPI for?
- ✨ Features Overview
- 🛠️ Installation
- ⚡ Quick Start
- 📚 Feature Documentation
- 📁 Examples
- 🧪 Testing
- 🔧 Configuration
- 🚀 Deployment
- ❓ FAQ
- 📊 Performance
- 🤝 Contributing
- 📄 License
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.
- ⚡ 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
- 🏢 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
- 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 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
pip install lightapi
# 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]
git clone https://github.com/iklobato/lightapi.git
cd lightapi
pip install -e .
from lightapi import LightApi
from lightapi.rest import RestEndpoint
from lightapi.models import register_model_class
from sqlalchemy import Column, Integer, String, Float
@register_model_class
class Product(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
from lightapi import LightApi
from lightapi.rest import RestEndpoint
from lightapi.models import register_model_class
from lightapi.cache import cache_manager
from sqlalchemy import Column, Integer, String, Float, DateTime
from datetime import datetime
@register_model_class
class User(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)
LightAPI automatically generates CRUD endpoints for your SQLAlchemy models:
from lightapi import LightApi
from lightapi.rest import RestEndpoint
from lightapi.models import register_model_class
from sqlalchemy import Column, Integer, String, Float, Boolean, DateTime
from datetime import datetime
@register_model_class
class Product(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
LightAPI supports async endpoints for high-performance applications:
import asyncio
from lightapi.rest import RestEndpoint
@register_model_class
class AsyncProduct(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
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
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'
@register_model_class
class User(RestEndpoint):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(50), unique=True)
password_hash = Column(String(255))
@register_model_class
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 /authendpoint
with 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
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)
Boost performance with intelligent Redis caching:
from lightapi.cache import cache_manager
@register_model_class
class CachedProduct(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")
Powerful querying capabilities out of the box:
@register_model_class
class AdvancedProduct(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
Comprehensive input validation and error handling:
import re
from datetime import datetime
@register_model_class
class ValidatedUser(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
Create REST APIs without writing Python code! LightAPI can automatically generate full CRUD APIs from existing database tables using simple YAML configuration files.
# 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_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]
# 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}"
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
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 |
# 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]
# 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
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'])
LightAPI includes comprehensive examples for all features:
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
# 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
LightAPI includes comprehensive test coverage:
# 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
LightAPI maintains high test coverage across all features:
- ✅ CRUD operations
- ✅ Async functionality
- ✅ JWT authentication
- ✅ Redis caching
- ✅ Request validation
- ✅ Error handling
- ✅ Middleware
- ✅ Configuration
# 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"
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)
# 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:
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)
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
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
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
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
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
A: LightAPI supports file uploads through Starlette:
from starlette.requests import Request
@register_model_class
class FileUpload(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)}
LightAPI is designed for high performance:
- 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
- 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
We welcome contributions! Here's how to get started:
# 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/
- Fork the repository
- Create a feature branch
- Write tests for new features
- Ensure all tests pass
- Submit a pull request
Please use GitHub Issues to report bugs. Include:
- Python version
- LightAPI version
- Minimal code example
- Error messages and stack traces
LightAPI is released under the MIT License. See LICENSE for details.
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
- Documentation: https://lightapi.readthedocs.io
- GitHub Issues: https://github.com/iklobato/lightapi/issues
- Discussions: https://github.com/iklobato/lightapi/discussions
- Email: [email protected]
Ready to build lightning-fast APIs? Get started with LightAPI today! ⚡
pip install lightapi