A lightweight database migration tool for Python projects
Project description
๐ DB Migrator
A lightweight database migration tool for managing and automating schema changes effortlessly.
๐ Requirements
- Python: 3.7 or higher
- Database: PostgreSQL (primary) or MySQL
- Dependencies: SQLAlchemy 2.0+, psycopg2-binary, python-dotenv
๐ Python Version Compatibility
| Python Version | Status | Notes |
|---|---|---|
| 3.7 | โ Supported | Minimum required version |
| 3.8 | โ Supported | Full compatibility |
| 3.9 | โ Supported | Full compatibility |
| 3.10 | โ Supported | Full compatibility |
| 3.11 | โ Supported | Full compatibility |
| 3.12 | โ Supported | Full compatibility |
| 3.6 | โ Not Supported | Missing f-string support |
Note: Python 3.7+ is required due to the use of f-strings and modern importlib features.
๐ฆ Features
- โ Seamless migration management โ apply and rollback with ease
- โ
Tracks applied migrations using a
schema_migrationstable - โ Supports both PostgreSQL and MySQL
- โ Robust error handling and detailed logging
- โ Works in any Python project directory
- โ NEW: Define table columns when creating migrations
- โ NEW: Automatic SQLAlchemy ORM model generation
- โ NEW: ORM model synchronization with migrations
- โ NEW: Configurable ORM model folder and settings
๐ ๏ธ Installation
pip install john-migrator
๐ Quick Start
1. Initialize Your Project
First, create a default configuration file:
john-migrator init
This creates a john_migrator_config.py file in your project root with default settings.
2. Configure Your Database
Edit the generated john_migrator_config.py file:
# john_migrator_config.py
DB_USER = "your_username"
DB_PASSWORD = "your_password"
DB_HOST = "localhost"
DB_PORT = "5432"
DB_NAME = "your_database"
MIGRATION_FOLDER = "migrations" # Optional: defaults to ./migrations
Or use environment variables:
export DB_USER=your_username
export DB_PASSWORD=your_password
export DB_HOST=localhost
export DB_PORT=5432
export DB_NAME=your_database
3. Create Your First Migration
Simple Migration (with default columns):
john-migrator create create_users_table
Migration with Custom Columns:
john-migrator create users username:varchar(255) age:integer email:varchar(100) is_active:boolean
This creates a migration file in your migrations/ folder with the specified columns.
4. Edit the Migration (if needed)
Open the generated file and customize your SQL:
from john_migrator.migrations.base_migration import BaseMigration
class Users(BaseMigration):
def __init__(self):
self.table_name = "users"
def up(self):
return """
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(255),
age INTEGER,
email VARCHAR(100),
is_active BOOLEAN,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
"""
def down(self):
return 'DROP TABLE IF EXISTS "users";'
5. Run Migrations
# Apply all pending migrations
john-migrator up
# Rollback the latest migration
john-migrator down
# Create a new migration with columns
john-migrator create products name:varchar(255) price:decimal(10,2) category:varchar(100)
# Modify existing tables
john-migrator alter users add age:integer add email:varchar(100)
john-migrator alter products drop old_price rename product_name:name
๐ ๏ธ Commands
| Command | Description | Example |
|---|---|---|
init |
Create a default configuration file | john-migrator init |
create |
Create a new migration file | john-migrator create users name:varchar(255) age:integer |
alter |
Create an ALTER TABLE migration | john-migrator alter users add age:integer add email:varchar(100) |
up |
Apply pending migrations | john-migrator up |
down |
Rollback the latest migration | john-migrator down |
status |
Show migration status | john-migrator status |
run |
Run a specific migration | john-migrator run m_20250101120000_create_users up |
sync |
Sync ORM models with migrations | john-migrator sync |
from-model |
Generate migrations from existing ORM models | john-migrator from-model ./models |
Command Details
john-migrator init
Creates a john_migrator_config.py file with default database and migration settings. This is the first command you should run in a new project.
john-migrator create <name> [columns...]
Creates a new migration file with the specified name and optional column definitions.
Examples:
# Simple migration
john-migrator create users
# Migration with columns
john-migrator create products name:varchar(255) price:decimal(10,2) category:varchar(100)
john-migrator alter <table> <operations...>
Creates an ALTER TABLE migration to modify existing tables.
Operations:
add column_name:type- Add a new columndrop column_name- Drop an existing columnmodify column_name:new_type- Modify column typerename old_name:new_name- Rename a column
Examples:
# Add columns
john-migrator alter users add age:integer add email:varchar(100)
# Drop and modify columns
john-migrator alter users drop old_column modify name:varchar(500)
# Rename columns
john-migrator alter products rename product_name:name
# Complex operations
john-migrator alter products add price:decimal(10,2) drop old_price rename product_name:name
john-migrator up
Applies all pending migrations that haven't been run yet.
john-migrator down
Rolls back the most recent batch of migrations.
john-migrator status
Shows the status of all migrations (applied vs pending).
john-migrator run <migration> <action>
Runs a specific migration with the specified action (up or down).
Examples:
john-migrator run m_20250101120000_create_users up
john-migrator run m_20250101120000_create_users down
john-migrator sync
Synchronizes all ORM models with their corresponding migration files. Useful when:
- You've manually edited migration files
- You want to regenerate all models
- You've added new migrations from other sources
john-migrator sync
john-migrator from-model <models_path> [model_names...]
Generates migrations from existing SQLAlchemy ORM models. This is useful when you have existing models and want to create migrations for them.
Examples:
# Generate migrations from all models in a directory
john-migrator from-model ./models
# Generate migrations from a specific model file
john-migrator from-model ./models/user.py
# Generate migrations for specific models
john-migrator from-model ./models User Product Order
Features:
- Automatically detects SQLAlchemy model classes
- Extracts column information and constraints
- Converts SQLAlchemy types to SQL types
- Handles default values and constraints
- Generates proper up/down migration methods
๐๏ธ ORM Model Generation
NEW: DB Migrator now automatically generates SQLAlchemy ORM models when you create migrations!
Automatic ORM Model Generation
When you create a migration, DB Migrator automatically generates a corresponding SQLAlchemy model:
# Create a migration with columns
john-migrator create users username:varchar(255) age:integer email:varchar(100) is_active:boolean
This will create:
- Migration file:
migrations/m_20250101120000_users.py - ORM Model:
models/users.py
Generated ORM Model Example
from sqlalchemy import Column, Integer, String, Boolean, DateTime, Text, Float, BigInteger, Date, JSON
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
Base = declarative_base()
class Users(Base):
__tablename__ = 'users'
# Primary key
id = Column(Integer, primary_key=True, autoincrement=True)
# Custom columns
username = Column(String(255), nullable=True)
age = Column(Integer, nullable=True)
email = Column(String(100), nullable=True)
is_active = Column(Boolean, nullable=True)
# Timestamps
created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
def __repr__(self):
return f'<Users(id={self.id})>'
ORM Configuration
Configure ORM model generation in your john_migrator_config.py:
# ORM Model Configuration (optional)
MODELS_FOLDER = "models" # Default: ./models
GENERATE_ORM_MODELS = True # Set to False to disable ORM model generation
ORM_BASE_CLASS = "Base" # SQLAlchemy base class name
ORM Commands
| Command | Description | Example |
|---|---|---|
sync |
Sync all ORM models with migrations | john-migrator sync |
john-migrator sync
Synchronizes all ORM models with their corresponding migration files. Useful when:
- You've manually edited migration files
- You want to regenerate all models
- You've added new migrations from other sources
john-migrator sync
ORM Model Synchronization
DB Migrator automatically syncs ORM models when:
- โ
Creating new migrations with
createcommand - โ
Applying migrations with
upcommand - โ
Running the
synccommand manually
Model-to-Migration Generation
NEW: Generate migrations from existing SQLAlchemy ORM models!
If you already have SQLAlchemy models defined, you can generate migrations for them:
# Example ORM model (models/user.py)
from sqlalchemy import Column, Integer, String, Boolean, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(255), nullable=False)
email = Column(String(100), nullable=True)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=func.now())
# Generate migration from the model
john-migrator from-model ./models/user.py
This will create a migration file that matches your ORM model structure.
Supported SQL to SQLAlchemy Type Mapping
| SQL Type | SQLAlchemy Type | Notes |
|---|---|---|
varchar(n) |
String(n) |
Variable length string |
text |
Text |
Long text |
integer |
Integer |
Integer number |
bigint |
BigInteger |
Large integer |
decimal(p,s) |
Float(p,s) |
Decimal number |
boolean |
Boolean |
True/False |
timestamp |
DateTime |
Date and time |
date |
Date |
Date only |
json |
JSON |
JSON data |
๐๏ธ Architecture
The DB Migrator is built with a clean, modular architecture:
Core Classes
MigrationManager- Main orchestrator that coordinates all migration operationsDatabaseManager- Handles database connections and operationsMigrationGenerator- Creates migration files and manages templatesMigrationRunner- Executes migrations and handles rollbacksORMGenerator- Generates SQLAlchemy ORM models from migrationsModelToMigrationGenerator- Generates migrations from existing ORM models
File Structure
src/
โโโ __init__.py # Package initialization
โโโ config.py # Configuration management
โโโ cli.py # Command line interface
โโโ migrate.py # Legacy interface (backward compatibility)
โโโ migration_manager.py # Main migration orchestrator
โโโ database_manager.py # Database operations
โโโ migration_generator.py # Migration file generation
โโโ migration_runner.py # Migration execution
โโโ orm_generator.py # ORM model generation
โโโ model_to_migration_generator.py # Model to migration generation
โโโ migrations/
โโโ __init__.py
โโโ base_migration.py # Abstract base class
โโโ *.py # Generated migration files
Usage in Code
You can also use the package programmatically:
from john_migrator import MigrationManager
# Initialize the manager
manager = MigrationManager()
# Create a migration
manager.create_migration("users", ["name:varchar(255)", "age:integer"])
# Run migrations
manager.run_migrations()
# Check status
manager.get_status()
๐ ALTER TABLE Operations
The alter command supports various table modification operations:
Supported Operations
| Operation | Syntax | Description | Rollback |
|---|---|---|---|
| Add Column | add column_name:type |
Adds a new column to the table | โ Automatic (drops column) |
| Drop Column | drop column_name |
Removes a column from the table | โ ๏ธ Manual (requires original type) |
| Modify Column | modify column_name:new_type |
Changes column data type | โ ๏ธ Manual (requires original type) |
| Rename Column | rename old_name:new_name |
Renames a column | โ Automatic (renames back) |
Rollback Behavior
- โ Automatic Rollback: Operations that can be automatically reversed
- โ ๏ธ Manual Rollback: Operations that require manual intervention
Example Migration:
def up(self):
return """
ALTER TABLE users ADD COLUMN age INTEGER;
ALTER TABLE users DROP COLUMN old_column;
ALTER TABLE users RENAME COLUMN product_name TO name;
"""
def down(self):
return """
ALTER TABLE users DROP COLUMN age;
-- ALTER TABLE users ADD COLUMN old_column <original_type>; -- Manual rollback required
ALTER TABLE users RENAME COLUMN name TO product_name;
"""
Best Practices
- Test rollbacks before applying to production
- Document manual rollbacks for complex operations
- Use transactions for multiple operations
- Backup data before destructive operations
๐ Column Definition Syntax
When creating migrations, you can specify columns using the format: column_name:data_type
Examples:
# Basic types
john-migrator create users name:varchar(255) age:integer
# With constraints
john-migrator create posts title:varchar(255) content:text author_id:integer
# Boolean and other types
john-migrator create settings user_id:integer is_active:boolean created_at:timestamp
Supported Data Types:
varchar(n)- Variable length stringtext- Long textinteger- Integer numberbigint- Large integerdecimal(p,s)- Decimal number with precisionboolean- True/Falsetimestamp- Date and timedate- Date onlyjson- JSON datauuid- UUID/GUID
Default Behavior:
- If no columns are specified, a default
name VARCHAR(255)column is added - If a column is specified without a type (e.g.,
name), it defaults toVARCHAR(255) - All tables automatically get
id SERIAL PRIMARY KEY,created_at, andupdated_atcolumns
๐ Project Structure
After installation, your project structure will look like:
your-project/
โโโ john_migrator_config.py # Database configuration
โโโ migrations/ # Your migration files
โ โโโ m_20250101120000_create_users_table.py
โ โโโ m_20250101120001_add_user_profile.py
โโโ models/ # Generated ORM models
โ โโโ users.py
โ โโโ products.py
โโโ .env # Optional: environment variables
๐ง Configuration Options
| Option | Environment Variable | Default | Description |
|---|---|---|---|
DB_USER |
DB_USER |
default_user |
Database username |
DB_PASSWORD |
DB_PASSWORD |
default_password |
Database password |
DB_HOST |
DB_HOST |
localhost |
Database host |
DB_PORT |
DB_PORT |
5432 |
Database port |
DB_NAME |
DB_NAME |
default_db |
Database name |
MIGRATION_FOLDER |
MIGRATION_FOLDER |
./migrations |
Migration files location |
MIGRATION_TABLE |
MIGRATION_TABLE |
migrations |
Migration tracking table |
MODELS_FOLDER |
MODELS_FOLDER |
./models |
ORM model files location |
GENERATE_ORM_MODELS |
GENERATE_ORM_MODELS |
True |
Enable/disable ORM model generation |
ORM_BASE_CLASS |
ORM_BASE_CLASS |
Base |
SQLAlchemy base class name |
๐งช Development
Testing Different Python Versions
To test compatibility with different Python versions, you can use:
# Using pyenv (recommended)
pyenv install 3.7.17
pyenv install 3.8.18
pyenv install 3.9.18
pyenv install 3.10.13
pyenv install 3.11.7
pyenv install 3.12.1
# Test each version
pyenv local 3.7.17 && python -m pip install -e .
pyenv local 3.8.18 && python -m pip install -e .
pyenv local 3.9.18 && python -m pip install -e .
pyenv local 3.10.13 && python -m pip install -e .
pyenv local 3.11.7 && python -m pip install -e .
pyenv local 3.12.1 && python -m pip install -e .
Using Docker for Testing
# Dockerfile for testing multiple Python versions
FROM python:3.7-slim
WORKDIR /app
COPY . .
RUN pip install -e .
CMD ["john-migrator", "--help"]
๐ Migration Best Practices
- Always test migrations in a development environment first
- Keep migrations small and focused on a single change
- Use descriptive names for your migration files
- Always implement both
up()anddown()methods - Use transactions for complex migrations (handled automatically)
- Define columns when creating to save time and reduce errors
๐ Bidirectional Workflow
DB Migrator supports both directions of database schema management:
Migration โ ORM Model (Default)
# Create migration with columns
john-migrator create users name:varchar(255) email:varchar(100)
# Automatically generates:
# 1. migrations/m_20250101120000_users.py
# 2. models/users.py
ORM Model โ Migration (Reverse)
# Start with existing ORM models
# models/user.py, models/product.py, etc.
# Generate migrations from models
john-migrator from-model ./models
# Automatically generates:
# migrations/m_20250101120000_create_users_table.py
# migrations/m_20250101120001_create_products_table.py
Synchronization
# Keep models in sync with migrations
john-migrator sync
# Apply migrations (also syncs models)
john-migrator up
This bidirectional approach gives you maximum flexibility in your database workflow!
Stay in control of your database schema with DB Migrator! โจ
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 john_migrator-1.3.0.tar.gz.
File metadata
- Download URL: john_migrator-1.3.0.tar.gz
- Upload date:
- Size: 22.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebcbea11367d9cdc50c057ce3703dc0e3b6e72e2580ea200f47ecddbbf3ad573
|
|
| MD5 |
02e87098830893b48427e72ce2b37ee9
|
|
| BLAKE2b-256 |
988f5d69999ccd1f3eef4f56e5701ad3b9c0f62111db4027f06c5421fbc9d3d1
|
File details
Details for the file john_migrator-1.3.0-py3-none-any.whl.
File metadata
- Download URL: john_migrator-1.3.0-py3-none-any.whl
- Upload date:
- Size: 27.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd34114a2ec6bdae71d9d39cac94efb4d9f99c8e424f3ce8d81d98d9e7452523
|
|
| MD5 |
77200c075a5a7fe0ebab52de1c4d7d67
|
|
| BLAKE2b-256 |
55ecfa7b2a5c168d58aa6862294767e3343edae638395ac98fe3a473b106f0e4
|