Universal, framework-independent ORM for Python.
Project description
Akron
Universal, framework-independent ORM for Python 🚀
Akron is a modern Python ORM that provides a unified interface for working with multiple databases. Whether you're using SQLite, MySQL, PostgreSQL, or MongoDB, Akron gives you the same clean, type-safe API across all platforms.
✨ Key Features
- 🔄 Universal Database Support - One API for SQLite, MySQL, PostgreSQL, and MongoDB
- 🛡️ Type Safety - Full Pydantic integration for type-safe models and validation
- 🔧 Zero Configuration - Works out of the box with simple connection strings
- 🔗 Foreign Key Support - Multi-table relationships with automatic constraint handling
- 📦 Auto Migrations - Schema tracking and automatic migration generation
- ⚡ CLI Tools - Command-line interface for database management
- 🧪 Well Tested - Comprehensive test coverage across all database drivers
- 📖 Framework Independent - Works with any Python framework or standalone scripts
🚀 Quick Start
Installation
pip install akron
Basic Usage
from akron import Akron
# Initialize database connection
db = Akron("sqlite:///example.db")
# Create table
db.create_table("users", {
"id": "int",
"name": "str",
"email": "str",
"age": "int"
})
# Insert data
user_id = db.insert("users", {
"name": "Alice Johnson",
"email": "alice@example.com",
"age": 28
})
# Query data
users = db.find("users")
alice = db.find("users", {"name": "Alice Johnson"})
# Update records
db.update("users", {"id": user_id}, {"age": 29})
# Delete records
db.delete("users", {"email": "alice@example.com"})
# Close connection
db.close()
Type-Safe Models with Pydantic
from pydantic import BaseModel
from akron import Akron
from akron.models import ModelMixin
class User(BaseModel, ModelMixin):
id: int
name: str
email: str
age: int
is_active: bool = True
# Initialize database
db = Akron("sqlite:///users.db")
# Create table from model
User.create_table(db)
# Insert with type safety
new_user = User(id=1, name="Bob Smith", email="bob@example.com", age=25)
User.insert(db, new_user)
# Query with automatic deserialization
users = User.find(db) # Returns List[User]
active_users = User.find(db, {"is_active": True})
# Update and delete
User.update(db, {"id": 1}, {"age": 26})
User.delete(db, {"email": "bob@example.com"})
🗄️ Database Support
| Database | Connection String Example | CRUD | Foreign Keys | Migrations | CLI Support |
|---|---|---|---|---|---|
| SQLite | sqlite:///path/to/db.db |
✅ | ✅ | ✅ | ✅ |
| MySQL | mysql://user:pass@host:port/dbname |
✅ | ✅ | ✅ | ✅ |
| PostgreSQL | postgres://user:pass@host:port/dbname |
✅ | ✅ | ✅ | ✅ |
| MongoDB | mongodb://host:port/dbname |
✅ | ❌* | Schemaless | ✅ |
*MongoDB doesn't support traditional foreign keys but maintains the same API for document references.
Connection Examples
# SQLite (file-based)
db = Akron("sqlite:///myapp.db")
# SQLite (in-memory)
db = Akron("sqlite:///:memory:")
# MySQL
db = Akron("mysql://username:password@localhost:3306/mydatabase")
# PostgreSQL
db = Akron("postgres://username:password@localhost:5432/mydatabase")
# MongoDB
db = Akron("mongodb://localhost:27017/mydatabase")
🔗 Advanced Features
Foreign Key Relationships
# Create tables with foreign key relationships
db.create_table("users", {
"id": "int",
"name": "str",
"email": "str"
})
db.create_table("orders", {
"id": "int",
"user_id": "int->users.id", # Foreign key syntax
"product_name": "str",
"amount": "float",
"status": "str"
})
# Insert related data
user_id = db.insert("users", {"name": "Alice", "email": "alice@example.com"})
order_id = db.insert("orders", {
"user_id": user_id,
"product_name": "Laptop",
"amount": 999.99,
"status": "pending"
})
# Query with relationships
user_orders = db.find("orders", {"user_id": user_id})
Complex Queries and Filtering
# Multiple filter conditions
adults = db.find("users", {"age": 25, "is_active": True})
# Range queries (depends on driver capabilities)
expensive_orders = db.find("orders", {"amount": ">500"})
# Get all records
all_users = db.find("users") # No filters = all records
Pydantic Model Relationships
class User(BaseModel, ModelMixin):
id: int
name: str
email: str
age: int
class Order(BaseModel, ModelMixin):
id: int
user_id: int # Foreign key reference
product_name: str
amount: float
status: str
# Create tables
User.create_table(db)
Order.create_table(db)
# Work with related models
user = User(id=1, name="Charlie", email="charlie@example.com", age=30)
User.insert(db, user)
order = Order(id=1, user_id=1, product_name="Book", amount=24.99, status="shipped")
Order.insert(db, order)
# Query relationships
user_orders = Order.find(db, {"user_id": 1})
🔄 Schema Management (Prisma-like)
Akron now supports Prisma-like schema management with akron.json configuration files:
Initialize a New Project
# Initialize with SQLite (default)
akron db init
# Initialize with specific database
akron db init --provider postgresql --url "postgres://user:pass@localhost:5432/mydb"
akron db init --provider mysql --url "mysql://user:pass@localhost:3306/mydb"
akron db init --provider mongodb --url "mongodb://localhost:27017/mydb"
Define Your Schema
Edit the generated akron.json file:
{
"database": {
"provider": "sqlite",
"url": "sqlite:///app.db"
},
"tables": {
"users": {
"columns": {
"id": {
"type": "int",
"primary_key": true,
"auto_increment": true
},
"email": {
"type": "str",
"unique": true,
"nullable": false
},
"username": {
"type": "str",
"unique": true,
"nullable": false,
"max_length": 50
},
"created_at": {
"type": "datetime",
"default": "CURRENT_TIMESTAMP"
}
}
},
"posts": {
"columns": {
"id": {
"type": "int",
"primary_key": true,
"auto_increment": true
},
"title": {
"type": "str",
"nullable": false,
"max_length": 200
},
"content": {
"type": "text",
"nullable": true
},
"author_id": {
"type": "int",
"nullable": false
},
"published": {
"type": "bool",
"default": false
}
},
"foreign_keys": {
"author_id": {
"references": "users",
"column": "id",
"on_delete": "CASCADE"
}
}
}
}
}
Generate and Apply Migrations
# Generate migrations from schema changes
akron db makemigrations --name "add_user_posts"
# Preview what will be migrated
akron db migrate --dry-run
# Apply migrations
akron db migrate
# Check migration status
akron db status
Schema Management Workflow
- Initialize:
akron db initcreatesakron.jsonand.akron/directory - Define: Edit
akron.jsonto define your database schema - Generate:
akron db makemigrationscreates migration files - Apply:
akron db migrateapplies pending migrations - Monitor:
akron db statusshows current state
🔄 Legacy Migration System
For backward compatibility, Akron still supports the original migration commands:
Auto-Generate Migrations
# Create a migration for schema changes
akron makemigrations users --db sqlite:///app.db --schema '{"id": "int", "name": "str", "email": "str", "created_at": "str"}'
# Apply migrations
akron migrate users --db sqlite:///app.db
# View migration history
akron showmigrations users --db sqlite:///app.db
Migration Features
- Automatic Schema Diffing - Compares current vs target schema
- Migration File Generation - Creates JSON migration files in
migrations/directory - Version Tracking - Maintains migration history in
_akron_migrationstable - Rollback Support - Track applied migrations for potential rollbacks
🛠️ CLI Commands
Akron provides two command interfaces: modern schema management and legacy commands.
Modern Schema Management Commands
# Initialize a new Akron project
akron db init # SQLite default
akron db init --provider postgresql --url "..." # PostgreSQL
akron db init --provider mysql --url "..." # MySQL
akron db init --provider mongodb --url "..." # MongoDB
# Generate migrations from schema changes
akron db makemigrations # Auto-named migration
akron db makemigrations --name "add_user_table" # Custom name
# Apply migrations
akron db migrate # Apply all pending
akron db migrate --dry-run # Preview changes
# Check status
akron db status # Show schema and migration status
# Reset database (planned)
akron db reset --force # Drop all and reapply
Legacy Commands (Backward Compatibility)
# Table Management
akron create-table users --db sqlite:///app.db --schema '{"id": "int", "name": "str"}'
akron drop-table users --db sqlite:///app.db
akron inspect-schema users --db sqlite:///app.db
# Data Management
akron seed users --db sqlite:///app.db --data '{"name": "John", "email": "john@example.com"}'
akron raw-sql --db sqlite:///app.db --sql "SELECT COUNT(*) FROM users"
# Legacy Migration Commands
akron makemigrations orders --db mysql://user:pass@localhost/shop --schema '{"id": "int"}'
akron migrate orders --db mysql://user:pass@localhost/shop
akron showmigrations orders --db mysql://user:pass@localhost/shop
📊 Type System
Akron provides a flexible type system that maps Python types to database-specific types:
Supported Python Types
| Python Type | SQL Databases | MongoDB |
|---|---|---|
int |
INTEGER | Number |
str |
VARCHAR/TEXT | String |
float |
REAL/DOUBLE | Number |
bool |
BOOLEAN | Boolean |
Custom Type Mapping
# Define custom field types in Pydantic models
from pydantic import Field
from datetime import datetime
class User(BaseModel, ModelMixin):
id: int
name: str
email: str = Field(..., max_length=255)
age: int = Field(..., ge=0, le=150)
created_at: str # Store as ISO string
is_premium: bool = False
🔧 Configuration & Best Practices
Connection Pooling
# For production use, consider connection pooling
class DatabaseManager:
def __init__(self, db_url: str):
self.db_url = db_url
self._db = None
def get_db(self):
if self._db is None:
self._db = Akron(self.db_url)
return self._db
def close(self):
if self._db:
self._db.close()
self._db = None
# Usage
db_manager = DatabaseManager("sqlite:///app.db")
db = db_manager.get_db()
Error Handling
from akron.exceptions import AkronError, TableNotFoundError, SchemaError
try:
db = Akron("sqlite:///myapp.db")
users = db.find("nonexistent_table")
except TableNotFoundError:
print("Table doesn't exist - creating it...")
db.create_table("users", {"id": "int", "name": "str"})
except AkronError as e:
print(f"Database error: {e}")
Environment-Based Configuration
import os
from akron import Akron
# Use environment variables for database configuration
DATABASE_URL = os.getenv(
"DATABASE_URL",
"sqlite:///default.db" # fallback for development
)
db = Akron(DATABASE_URL)
🧪 Testing
Akron includes comprehensive test coverage and provides utilities for testing:
Test Database Setup
import pytest
from akron import Akron
from akron.models import ModelMixin
from pydantic import BaseModel
class User(BaseModel, ModelMixin):
id: int
name: str
email: str
@pytest.fixture
def test_db():
# Use in-memory database for testing
db = Akron("sqlite:///:memory:")
User.create_table(db)
yield db
db.close()
def test_user_creation(test_db):
user = User(id=1, name="Test User", email="test@example.com")
User.insert(test_db, user)
users = User.find(test_db, {"email": "test@example.com"})
assert len(users) == 1
assert users[0].name == "Test User"
Running Tests
# Run the full test suite
pytest tests/
# Run specific database tests
pytest tests/test_sqlite_pytest.py
pytest tests/test_mysql_pytest.py
📈 Performance Considerations
Batch Operations
# For large datasets, consider batch insertions
users_data = [
{"name": f"User {i}", "email": f"user{i}@example.com", "age": 20 + i}
for i in range(1000)
]
for user_data in users_data:
db.insert("users", user_data)
Connection Management
# Always close connections in production
try:
db = Akron("mysql://user:pass@localhost/prod_db")
# ... database operations ...
finally:
db.close()
# Or use context managers (if implementing __enter__/__exit__)
🔍 Examples
Check out the examples/ directory for more comprehensive examples:
basic_crud.py- Basic CRUD operationssqlite_multi_table.py- Multi-table relationships with SQLitepostgres_multi_table.py- PostgreSQL with foreign keys
🆚 Version Information
- Current Version: v0.1.5
- Python Requirements: Python 3.7+
- Dependencies:
pydantic- Type safety and validationmysql-connector-python- MySQL supportpsycopg2- PostgreSQL supportpymongo- MongoDB support
Changelog
See CHANGELOG.md for detailed version history and updates.
🤝 Contributing
We welcome contributions! Please feel free to:
- Report Issues - Found a bug? Let us know!
- Feature Requests - Have an idea? We'd love to hear it!
- Pull Requests - Code contributions are always welcome!
Development Setup
# Clone the repository
git clone https://github.com/Akash-nath29/akron.git
cd akron
# Install development dependencies
pip install -e .
pip install pytest
# Run tests
pytest tests/
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
- PyPI Package: https://pypi.org/project/akron/
- GitHub Repository: https://github.com/Akash-nath29/akron
- Documentation: https://akron-website.vercel.app/docs
- Issues & Support: https://github.com/Akash-nath29/akron/issues
Made with ❤️ by the Akron team
⭐ Star us on GitHub if you find Akron useful! ⭐
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 akron-0.2.0.tar.gz.
File metadata
- Download URL: akron-0.2.0.tar.gz
- Upload date:
- Size: 28.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f96b66a982b3bc94c6777412bb22032284a53c168cc444fcaf79368276724512
|
|
| MD5 |
6d34e7f83b5090f99813257919011556
|
|
| BLAKE2b-256 |
54f234e87ce7c70da80a58c251406bc364a7f5e8315002b5d2151dc52b52a896
|
File details
Details for the file akron-0.2.0-py3-none-any.whl.
File metadata
- Download URL: akron-0.2.0-py3-none-any.whl
- Upload date:
- Size: 25.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6abb96680083273c41c8d296458cf8024ab1a8f4bc4e316059889641061f97e0
|
|
| MD5 |
54bf52e15c17401e50da588a9ab0425f
|
|
| BLAKE2b-256 |
a5c4487fb6ce32ecb50bd0be1713734987c328efdc0b2c6aedb0533f704af3c3
|