dbporter


Namedbporter JSON
Version 0.1.6 PyPI version JSON
download
home_pagehttps://github.com/karan-kap00r/dbPorter
SummaryA powerful database migration tool with DAG support, automatic rollback, and schema inspection
upload_time2025-09-14 19:20:15
maintainerNone
docs_urlNone
authorKaran Kapoor
requires_python>=3.8
licenseMIT
keywords database migration schema sqlalchemy yaml dag rollback postgresql mysql sqlite oracle sqlserver version-control database-versioning schema-management
VCS
bugtrack_url
requirements typer sqlalchemy pyyaml python-dotenv tabulate typing-extensions
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # dbPorter - Database Migration Tool

A powerful, flexible database migration tool built with Python that supports both YAML-based declarative migrations and Python-based programmatic migrations. This tool provides comprehensive schema management capabilities with automatic rollback support and metadata preservation.

## 🚀 Features

- **Dual Migration Support**: YAML-based declarative migrations and Python-based programmatic migrations
- **Migration Graph (DAG)**: Support for branching migrations with dependency management like Alembic
- **Automatic Rollback**: Intelligent rollback system with metadata preservation for safe reversions
- **Schema Auto-Generation**: Automatically detect and generate migrations from schema differences
- **Enhanced Metadata**: Captures column metadata for accurate rollback operations
- **Table Rename Support**: Handle table renames with mapping configuration
- **Dry-Run Capability**: Preview migration changes before applying them
- **Comprehensive Logging**: Track all applied migrations with detailed payload information
- **Multiple Database Support**: Works with any SQLAlchemy-supported database
- **Parallel Development**: Support for multiple developers working on migrations simultaneously
- **Conflict Detection**: Automatic detection and resolution of migration conflicts
- **Schema Inspection**: Comprehensive database and migration status inspection with visual indicators
- **Sync Validation**: Automatic detection of database schema sync issues

## 📋 Prerequisites

- **Python 3.8+** (Python 3.9+ recommended)
- **Core Dependencies**: SQLAlchemy, PyYAML, Typer, python-dotenv, tabulate
- **Database Driver**: Choose based on your database:
  - **SQLite**: No additional driver needed (included with Python)
  - **PostgreSQL**: `psycopg2-binary` or `psycopg2`
  - **MySQL**: `PyMySQL` or `mysqlclient`
  - **SQL Server**: `pyodbc` or `pymssql`
  - **Oracle**: `cx-Oracle`

## 🛠️ Installation

1. **Clone the repository**
   ```bash
   git clone <repository-url>
   cd dbPorter
   ```

2. **Install dependencies**
   
   **Option A: Automated installation (recommended)**
   ```bash
   # For SQLite (default)
   python install.py
   
   # For PostgreSQL
   python install.py --database postgresql
   
   # For MySQL
   python install.py --database mysql
   
   # For development
   python install.py --dev
   ```
   
   **Option B: Manual installation**
   ```bash
   # Full installation (recommended)
   pip install -r requirements.txt
   
   # Minimal installation (SQLite only)
   pip install -r requirements-minimal.txt
   
   # Development installation
   pip install -r requirements-dev.txt
   ```
   
   **Option C: Quick installation**
   ```bash
   pip install sqlalchemy pyyaml typer python-dotenv tabulate
   ```

3. **Set up database configuration (optional)**
   The tool auto-discovers database URLs from multiple sources:
   
   **Option A: Environment Variables**
   ```bash
   export DB_URL="sqlite:///your_database.db"
   # or for PostgreSQL: postgresql://user:password@localhost/dbname
   # or for MySQL: mysql://user:password@localhost/dbname
   ```
   
   **Option B: .env file**
   Create a `.env` file in the project root:
   ```env
   DB_URL=sqlite:///your_database.db
   DATABASE_URL=postgresql://user:password@localhost/dbname
   ```
   
   **Option C: Configuration files**
   The tool also looks for database URLs in:
   - `config.py` (DATABASE_URL variable)
   - `settings.py` (DB_URL variable)
   - `database.py` (database_url variable)
   
   **Option D: Default fallback**
   If no database URL is found, defaults to `sqlite:///migrate.db`

## 🏗️ Project Structure

```
dbPorter/
├── main.py                 # Entry point
├── commands.py             # CLI commands implementation
├── models.py              # SQLAlchemy metadata definitions
├── migrations/            # Migration files directory
│   ├── *.yml             # YAML migration files
│   └── *.py              # Python migration files
├── src/                  # Core migration logic
│   ├── applier.py        # Migration application logic
│   ├── db.py             # Database connection and metadata
│   ├── executors.py      # SQL operation executors
│   ├── migration_loader.py # Migration file parsing
│   └── planner.py        # Migration planning logic
└── utils/                # Utility functions
    └── utils.py          # Helper functions
```

## 🚀 Quick Start

1. **Initialize the migration system**
   ```bash
   python main.py init-db
   ```

2. **Define your schema in a models file**
   ```python
   # models.py, schema.py, database.py, or any Python file
   from sqlalchemy import Table, Column, Integer, String, MetaData
   
   metadata = MetaData()
   
   users = Table(
       "users", metadata,
       Column("id", Integer, primary_key=True),
       Column("name", String(100), nullable=False),
       Column("email", String(255), unique=True)
   )
   ```

3. **Auto-generate your first migration**
   ```bash
   python main.py autogenerate -m "Initial schema"
   ```

4. **Apply the migration**
   ```bash
   python main.py apply
   ```

## 📖 Command Reference

### Database Initialization

```bash
# Initialize migration metadata table
python main.py init-db [--db DATABASE_URL]
```

### Migration Planning

```bash
# Plan a migration (dry-run)
python main.py plan [MIGRATION_FILE] [--rename-map RENAME_MAP_FILE]

# Examples:
python main.py plan                                    # Use latest migration
python main.py plan migrations/20250101120000_add_users.yml
python main.py plan --rename-map custom_renames.yml
```

### Migration Application

```bash
# Apply migrations
python main.py apply [MIGRATION_FILE] [OPTIONS]

# Options:
#   --db DATABASE_URL        Database connection string
#   --rename-map FILE        Table rename mapping file
#   --dry-run               Show what would be done without executing
#   --latest                Use the latest migration file

# Examples:
python main.py apply                                    # Apply latest migration
python main.py apply --latest                          # Explicitly use latest
python main.py apply --dry-run                         # Preview changes
python main.py apply migrations/20250101120000_add_users.yml
```

### Migration Rollback

```bash
# Rollback the last applied migration
python main.py rollback [--db DATABASE_URL]

# Examples:
python main.py rollback
python main.py rollback --db "postgresql://user:pass@localhost/db"
```

### Auto-Generation

```bash
# Auto-generate migration from schema differences
python main.py autogenerate [--db DATABASE_URL] [-m MESSAGE]

# Examples:
python main.py autogenerate
python main.py autogenerate -m "Add user profile table"
python main.py autogenerate --db "sqlite:///mydb.db"
```

### Migration Registration

```bash
# Register existing migration with timestamp
python main.py revision MIGRATION_FILE

# Example:
python main.py revision my_migration.yml
# Creates: migrations/20250101120000_my_migration.yml
```

### Models Discovery

```bash
# Discover and validate models files
python main.py discover-models [--models-file PATH]

# Examples:
python main.py discover-models                    # Auto-discover models file
python main.py discover-models --models-file "my_schema.py"
```

### Database Discovery

```bash
# Discover and validate database configuration
python main.py discover-db [--db URL]

# Examples:
python main.py discover-db                        # Auto-discover database URL
python main.py discover-db --db "postgresql://user:pass@localhost/db"
```

### One-Time Database Configuration

**Configure once, use everywhere!** Set up your database connection once during `init-db`, and all future commands will automatically use the same configuration.

#### **Step 1: Configure Database (One Time Only)**
```bash
# PostgreSQL (most common)
python main.py init-db --host localhost --port 5432 --user myuser --password mypass --database mydb --type postgresql

# MySQL
python main.py init-db --host localhost --port 3306 --user myuser --password mypass --database mydb --type mysql

# SQLite (no credentials needed)
python main.py init-db --database myapp.db --type sqlite

# Using complete URL
python main.py init-db --db "postgresql://user:pass@localhost/db"
```

#### **Step 2: Use Commands Without Database Parameters**
```bash
# All these commands automatically use the saved configuration!
python main.py apply
python main.py rollback
python main.py autogenerate -m "Add new table"
python main.py plan
```

#### **Configuration Management**
```bash
# Show current configuration
python main.py show-config

# Reset configuration (go back to auto-discovery)
python main.py reset-config
```

**Benefits:**
- ✅ **Configure Once**: Set database connection once during `init-db`
- ✅ **Use Everywhere**: All commands automatically use saved configuration
- ✅ **Override When Needed**: Can still override with command-line arguments
- ✅ **Secure**: Credentials stored in local config file (not in code)
- ✅ **Flexible**: Easy to change configuration anytime

## 🌳 Migration Graph (DAG) System

**Advanced dependency management for complex migration scenarios!** The tool now supports Directed Acyclic Graphs (DAG) for managing migration dependencies, enabling parallel development and complex branching scenarios.

### **Key DAG Features:**

#### **1. Dependency Management**
```yaml
# Migration with dependencies
version: '20250113120000'
description: Add user authentication system
branch: feature-auth
dependencies: ['20250113100000']  # Depends on previous migration
revision_id: 'abc12345'
changes:
  - add_table:
      name: users
      columns:
        - name: id
          type: INTEGER
          primary_key: true
        - name: username
          type: VARCHAR(50)
          unique: true
```

#### **2. Branch Support**
```bash
# Create a new migration branch
python main.py create-branch feature-auth

# Create a branch from specific migration
python main.py create-branch feature-payments --base 20250113100000
```

#### **3. Parallel Development**
```bash
# Developer A works on auth branch
python main.py autogenerate -m "Add user table" --branch feature-auth

# Developer B works on payments branch  
python main.py autogenerate -m "Add payment table" --branch feature-payments

# Both can work simultaneously without conflicts
```

#### **4. Merge Branches**
```bash
# Merge two branches when ready
python main.py merge-branches feature-auth feature-payments -m "Merge auth and payments"
```

### **DAG Commands:**

| Command | Description | Example |
|---------|-------------|---------|
| `graph` | Show migration dependency graph | `python main.py graph` |
| `validate-migration` | Validate migration for conflicts | `python main.py validate-migration migrations/20250113_add_users.yml` |
| `create-branch` | Create new migration branch | `python main.py create-branch feature-auth` |
| `merge-branches` | Merge two branches | `python main.py merge-branches feature-auth feature-payments` |
| `status` | Comprehensive migration & schema status | `python main.py status` |
| `status-quick` | Quick status overview | `python main.py status-quick` |

### **DAG Workflow Example:**

#### **Scenario: Multiple Developers Working in Parallel**

```bash
# 1. Initial setup
python main.py init-db --host localhost --user myuser --password mypass --database mydb --type postgresql

# 2. Developer A creates auth branch
python main.py create-branch feature-auth
python main.py autogenerate -m "Add users table" --branch feature-auth
python main.py apply migrations/20250113120000_add_users_table.yml

# 3. Developer B creates payments branch (from same base)
python main.py create-branch feature-payments
python main.py autogenerate -m "Add payments table" --branch feature-payments
python main.py apply migrations/20250113130000_add_payments_table.yml

# 4. Check migration graph
python main.py graph
# Output:
# Migration Graph:
# ==================================================
# 
# Branch: main
# --------------------
#   20250113100000: Initial schema
#     Dependencies: none
#     Revision ID: def45678
# 
# Branch: feature-auth
# --------------------
#   20250113120000: Add users table
#     Dependencies: 20250113100000
#     Revision ID: abc12345
# 
# Branch: feature-payments
# --------------------
#   20250113130000: Add payments table
#     Dependencies: 20250113100000
#     Revision ID: ghi78901

# 5. Merge branches when ready
python main.py merge-branches feature-auth feature-payments -m "Merge auth and payments"
python main.py apply migrations/20250113140000_merge_feature_auth_feature_payments.yml
```

### **DAG Benefits:**

- ✅ **Parallel Development**: Multiple developers can work on migrations simultaneously
- ✅ **Dependency Tracking**: Clear dependency relationships between migrations
- ✅ **Conflict Detection**: Automatic detection of migration conflicts
- ✅ **Branch Management**: Easy creation and merging of migration branches
- ✅ **Graph Visualization**: Visual representation of migration dependencies
- ✅ **Cycle Detection**: Prevents circular dependencies
- ✅ **Backward Compatible**: Existing linear migrations continue to work

## 🔍 Schema Inspection Utilities

**Comprehensive database and migration status inspection!** The tool provides powerful commands to inspect your database schema and migration status with clear visual indicators.

### **Status Commands:**

#### **1. Comprehensive Status (`status`)**
```bash
# Full status report with schema validation
python main.py status

# Verbose mode with detailed information
python main.py status --verbose

# Check against specific models file
python main.py status --models-file custom_models.py

# Skip sync checking for faster execution
python main.py status --no-check-sync
```

**Output Example:**
```
🔍 Migration & Schema Status Report
============================================================

📊 MIGRATION STATUS
------------------------------
✅ Applied migrations: 6
⏳ Pending migrations: 0

🔄 DATABASE SYNC STATUS
------------------------------
Status: ⚠️ Out of Sync
  • Extra tables: migration_log

🔗 DEPENDENCY HEALTH
------------------------------
✅ DAG is valid - no cycles detected
✅ No dependency conflicts

🎯 CURRENT STATE
------------------------------
Current heads: 20250913122220, 20250913122712

📋 SUMMARY
------------------------------
✅ All migrations applied - database is up to date
⚠️ Database schema may be out of sync - consider running 'python main.py autogenerate'
```

#### **2. Quick Status (`status-quick`)**
```bash
# Quick overview for CI/CD pipelines
python main.py status-quick
```

**Output Example:**
```
✅ All migrations applied
📊 Database has 5 tables
🎯 Current heads: 20250913122220, 20250913122712
```

### **Status Indicators:**

| Indicator | Meaning | Action Required |
|-----------|---------|-----------------|
| ✅ **Applied** | Migration successfully applied to database | None |
| ⏳ **Pending** | Migration exists but not applied | Run `python main.py apply` |
| ⚠️ **Out of Sync** | Database schema differs from models | Run `python main.py autogenerate` |
| ❌ **Error** | Migration or database error | Check logs and fix issues |
| ❓ **Unknown** | Cannot determine status | Check database connection |

### **Schema Validation Features:**

- **Table Comparison**: Compares current database tables with target models
- **Missing Tables**: Identifies tables that should exist but don't
- **Extra Tables**: Identifies tables that exist but aren't in models
- **Dependency Health**: Validates migration dependency graph
- **Conflict Detection**: Identifies migration conflicts and circular dependencies
- **Branch Summary**: Shows migration status by branch

### **Use Cases:**

#### **Development Workflow:**
```bash
# Check status before starting work
python main.py status

# Quick check during development
python main.py status-quick

# Detailed inspection when debugging
python main.py status --verbose
```

#### **CI/CD Pipeline:**
```bash
# Quick status check in CI
python main.py status-quick

# Full validation in staging
python main.py status --check-sync
```

#### **Production Monitoring:**
```bash
# Monitor migration status
python main.py status --no-check-sync

# Validate against production models
python main.py status --models-file production_models.py
```

## 📝 Migration File Formats

### YAML Migrations

YAML migrations use a declarative format for schema changes:

```yaml
version: '20250101120000'
description: Add users table with indexes
changes:
- create_table:
    table: users
    columns:
    - name: id
      type: INTEGER
      nullable: false
      primary_key: true
    - name: name
      type: VARCHAR(100)
      nullable: false
    - name: email
      type: VARCHAR(255)
      nullable: true
      unique: true

- add_index:
    table: users
    name: idx_users_email
    columns: [email]

- add_column:
    table: users
    column: created_at
    type: DATETIME
    nullable: true

- drop_column:
    table: users
    column: old_field
```

### Python Migrations

Python migrations provide full programmatic control:

```python
def upgrade(engine):
    """Apply the migration."""
    with engine.connect() as conn:
        conn.execute(text("""
            CREATE TABLE users (
                id INTEGER PRIMARY KEY,
                name VARCHAR(100) NOT NULL,
                email VARCHAR(255) UNIQUE
            )
        """))

def downgrade(engine):
    """Rollback the migration."""
    with engine.connect() as conn:
        conn.execute(text("DROP TABLE users"))
```

## 🔄 Supported Operations

### Table Operations
- `create_table` / `drop_table`
- `rename_table`

### Column Operations
- `add_column` / `drop_column`
- `alter_column` (type changes, nullable modifications)

### Index Operations
- `add_index` / `drop_index`

### Advanced Features
- **Metadata Preservation**: All operations store metadata for accurate rollback
- **Table Rename Mapping**: Handle table renames with `rename_map.yml`
- **Enhanced Rollback**: Automatic reversal of all supported operations
- **Schema Validation**: Compare current schema with target schema

## ⚙️ Configuration

### 🔐 Programmatic Configuration (Security-Conscious)

For organizations that prefer not to store database credentials in files, you can set the database URL programmatically:

```python
# In your application code
from dbPorter import set_database_url

# Set database URL directly in code
set_database_url("postgresql://user:password@localhost:5432/mydatabase")

# Now all migration commands will use this URL automatically
# dbporter status
# dbporter apply migrations/20250101_add_users.yml
```

**Benefits:**
- ✅ **No credential files**: Database URL not stored on disk
- ✅ **Environment variables**: Can use `os.getenv("DATABASE_URL")`
- ✅ **Application integration**: Works with existing app configuration
- ✅ **CI/CD friendly**: Perfect for automated deployments
- ✅ **Multi-tenant ready**: Dynamic database URLs per tenant

**Example with environment variables:**
```python
import os
from dbPorter import set_database_url

# From environment variable
db_url = os.getenv("DATABASE_URL")
if db_url:
    set_database_url(db_url)
else:
    raise ValueError("DATABASE_URL environment variable not set")
```

### 🔄 Configuration Priority

The tool uses the following priority order for database configuration:

1. **Command-line arguments** (highest priority)
   ```bash
   dbporter status --db "postgresql://user:pass@host:port/db"
   ```

2. **Programmatic configuration** (security-conscious)
   ```python
   from dbPorter import set_database_url
   set_database_url("postgresql://user:pass@host:port/db")
   ```

3. **Saved configuration** (traditional)
   ```bash
   dbporter init-db --host localhost --user myuser --password mypass
   ```

4. **Environment variables** (fallback)
   ```bash
   export DB_URL="postgresql://user:pass@host:port/db"
   dbporter status
   ```

5. **Auto-discovery** (lowest priority)
   - Automatically detects database from common patterns

### 📁 File-Based Configuration (Traditional)

### Environment Variables

Create a `.env` file in your project root:

```env
# Database connection
DB_URL=sqlite:///your_database.db

# For PostgreSQL
# DB_URL=postgresql://username:password@localhost:5432/database_name

# For MySQL
# DB_URL=mysql://username:password@localhost:3306/database_name
```

### Table Rename Mapping

Create `rename_map.yml` to handle table renames:

```yaml
table_renames:
  old_table_name: new_table_name
  legacy_users: users
```

## 🔒 Safety Features

- **Transaction Support**: All migrations run in database transactions
- **Rollback Capability**: Every migration can be safely rolled back
- **Metadata Preservation**: Column types, constraints, and indexes are preserved
- **Dry-Run Mode**: Preview changes before applying
- **Migration Logging**: Complete audit trail of all applied migrations

## 🐛 Troubleshooting

### Common Issues

1. **Migration not found**
   ```bash
   # Ensure migration file exists and is properly formatted
   python main.py plan migrations/your_migration.yml
   ```

2. **Database connection failed**
   ```bash
   # Check your DB_URL in .env file
   python main.py init-db --db "sqlite:///test.db"
   ```

3. **Rollback failed**
   ```bash
   # Check migration log for the last applied migration
   # Ensure database is in a consistent state
   ```

### Debug Mode

Enable verbose logging by modifying the commands to include debug output:

```python
# Add logging configuration in your migration files
import logging
logging.basicConfig(level=logging.DEBUG)
```

## 🤝 Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## 📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

## 🙏 Acknowledgments

- Built with [SQLAlchemy](https://www.sqlalchemy.org/) for database abstraction
- CLI powered by [Typer](https://typer.tiangolo.com/)
- YAML support via [PyYAML](https://pyyaml.org/)

---

**Need help?** Check the command help with `python main.py --help` or `python main.py [command] --help`

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/karan-kap00r/dbPorter",
    "name": "dbporter",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Karan Kapoor <karankapoor0062@gmail.com>",
    "keywords": "database, migration, schema, sqlalchemy, yaml, dag, rollback, postgresql, mysql, sqlite, oracle, sqlserver, version-control, database-versioning, schema-management",
    "author": "Karan Kapoor",
    "author_email": "Karan Kapoor <karankapoor0062@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/9e/8b/8e0c413513342c0e6cca292dab998998cb657f984ea5f3db66d34d70d37b/dbporter-0.1.6.tar.gz",
    "platform": "any",
    "description": "# dbPorter - Database Migration Tool\n\nA powerful, flexible database migration tool built with Python that supports both YAML-based declarative migrations and Python-based programmatic migrations. This tool provides comprehensive schema management capabilities with automatic rollback support and metadata preservation.\n\n## \ud83d\ude80 Features\n\n- **Dual Migration Support**: YAML-based declarative migrations and Python-based programmatic migrations\n- **Migration Graph (DAG)**: Support for branching migrations with dependency management like Alembic\n- **Automatic Rollback**: Intelligent rollback system with metadata preservation for safe reversions\n- **Schema Auto-Generation**: Automatically detect and generate migrations from schema differences\n- **Enhanced Metadata**: Captures column metadata for accurate rollback operations\n- **Table Rename Support**: Handle table renames with mapping configuration\n- **Dry-Run Capability**: Preview migration changes before applying them\n- **Comprehensive Logging**: Track all applied migrations with detailed payload information\n- **Multiple Database Support**: Works with any SQLAlchemy-supported database\n- **Parallel Development**: Support for multiple developers working on migrations simultaneously\n- **Conflict Detection**: Automatic detection and resolution of migration conflicts\n- **Schema Inspection**: Comprehensive database and migration status inspection with visual indicators\n- **Sync Validation**: Automatic detection of database schema sync issues\n\n## \ud83d\udccb Prerequisites\n\n- **Python 3.8+** (Python 3.9+ recommended)\n- **Core Dependencies**: SQLAlchemy, PyYAML, Typer, python-dotenv, tabulate\n- **Database Driver**: Choose based on your database:\n  - **SQLite**: No additional driver needed (included with Python)\n  - **PostgreSQL**: `psycopg2-binary` or `psycopg2`\n  - **MySQL**: `PyMySQL` or `mysqlclient`\n  - **SQL Server**: `pyodbc` or `pymssql`\n  - **Oracle**: `cx-Oracle`\n\n## \ud83d\udee0\ufe0f Installation\n\n1. **Clone the repository**\n   ```bash\n   git clone <repository-url>\n   cd dbPorter\n   ```\n\n2. **Install dependencies**\n   \n   **Option A: Automated installation (recommended)**\n   ```bash\n   # For SQLite (default)\n   python install.py\n   \n   # For PostgreSQL\n   python install.py --database postgresql\n   \n   # For MySQL\n   python install.py --database mysql\n   \n   # For development\n   python install.py --dev\n   ```\n   \n   **Option B: Manual installation**\n   ```bash\n   # Full installation (recommended)\n   pip install -r requirements.txt\n   \n   # Minimal installation (SQLite only)\n   pip install -r requirements-minimal.txt\n   \n   # Development installation\n   pip install -r requirements-dev.txt\n   ```\n   \n   **Option C: Quick installation**\n   ```bash\n   pip install sqlalchemy pyyaml typer python-dotenv tabulate\n   ```\n\n3. **Set up database configuration (optional)**\n   The tool auto-discovers database URLs from multiple sources:\n   \n   **Option A: Environment Variables**\n   ```bash\n   export DB_URL=\"sqlite:///your_database.db\"\n   # or for PostgreSQL: postgresql://user:password@localhost/dbname\n   # or for MySQL: mysql://user:password@localhost/dbname\n   ```\n   \n   **Option B: .env file**\n   Create a `.env` file in the project root:\n   ```env\n   DB_URL=sqlite:///your_database.db\n   DATABASE_URL=postgresql://user:password@localhost/dbname\n   ```\n   \n   **Option C: Configuration files**\n   The tool also looks for database URLs in:\n   - `config.py` (DATABASE_URL variable)\n   - `settings.py` (DB_URL variable)\n   - `database.py` (database_url variable)\n   \n   **Option D: Default fallback**\n   If no database URL is found, defaults to `sqlite:///migrate.db`\n\n## \ud83c\udfd7\ufe0f Project Structure\n\n```\ndbPorter/\n\u251c\u2500\u2500 main.py                 # Entry point\n\u251c\u2500\u2500 commands.py             # CLI commands implementation\n\u251c\u2500\u2500 models.py              # SQLAlchemy metadata definitions\n\u251c\u2500\u2500 migrations/            # Migration files directory\n\u2502   \u251c\u2500\u2500 *.yml             # YAML migration files\n\u2502   \u2514\u2500\u2500 *.py              # Python migration files\n\u251c\u2500\u2500 src/                  # Core migration logic\n\u2502   \u251c\u2500\u2500 applier.py        # Migration application logic\n\u2502   \u251c\u2500\u2500 db.py             # Database connection and metadata\n\u2502   \u251c\u2500\u2500 executors.py      # SQL operation executors\n\u2502   \u251c\u2500\u2500 migration_loader.py # Migration file parsing\n\u2502   \u2514\u2500\u2500 planner.py        # Migration planning logic\n\u2514\u2500\u2500 utils/                # Utility functions\n    \u2514\u2500\u2500 utils.py          # Helper functions\n```\n\n## \ud83d\ude80 Quick Start\n\n1. **Initialize the migration system**\n   ```bash\n   python main.py init-db\n   ```\n\n2. **Define your schema in a models file**\n   ```python\n   # models.py, schema.py, database.py, or any Python file\n   from sqlalchemy import Table, Column, Integer, String, MetaData\n   \n   metadata = MetaData()\n   \n   users = Table(\n       \"users\", metadata,\n       Column(\"id\", Integer, primary_key=True),\n       Column(\"name\", String(100), nullable=False),\n       Column(\"email\", String(255), unique=True)\n   )\n   ```\n\n3. **Auto-generate your first migration**\n   ```bash\n   python main.py autogenerate -m \"Initial schema\"\n   ```\n\n4. **Apply the migration**\n   ```bash\n   python main.py apply\n   ```\n\n## \ud83d\udcd6 Command Reference\n\n### Database Initialization\n\n```bash\n# Initialize migration metadata table\npython main.py init-db [--db DATABASE_URL]\n```\n\n### Migration Planning\n\n```bash\n# Plan a migration (dry-run)\npython main.py plan [MIGRATION_FILE] [--rename-map RENAME_MAP_FILE]\n\n# Examples:\npython main.py plan                                    # Use latest migration\npython main.py plan migrations/20250101120000_add_users.yml\npython main.py plan --rename-map custom_renames.yml\n```\n\n### Migration Application\n\n```bash\n# Apply migrations\npython main.py apply [MIGRATION_FILE] [OPTIONS]\n\n# Options:\n#   --db DATABASE_URL        Database connection string\n#   --rename-map FILE        Table rename mapping file\n#   --dry-run               Show what would be done without executing\n#   --latest                Use the latest migration file\n\n# Examples:\npython main.py apply                                    # Apply latest migration\npython main.py apply --latest                          # Explicitly use latest\npython main.py apply --dry-run                         # Preview changes\npython main.py apply migrations/20250101120000_add_users.yml\n```\n\n### Migration Rollback\n\n```bash\n# Rollback the last applied migration\npython main.py rollback [--db DATABASE_URL]\n\n# Examples:\npython main.py rollback\npython main.py rollback --db \"postgresql://user:pass@localhost/db\"\n```\n\n### Auto-Generation\n\n```bash\n# Auto-generate migration from schema differences\npython main.py autogenerate [--db DATABASE_URL] [-m MESSAGE]\n\n# Examples:\npython main.py autogenerate\npython main.py autogenerate -m \"Add user profile table\"\npython main.py autogenerate --db \"sqlite:///mydb.db\"\n```\n\n### Migration Registration\n\n```bash\n# Register existing migration with timestamp\npython main.py revision MIGRATION_FILE\n\n# Example:\npython main.py revision my_migration.yml\n# Creates: migrations/20250101120000_my_migration.yml\n```\n\n### Models Discovery\n\n```bash\n# Discover and validate models files\npython main.py discover-models [--models-file PATH]\n\n# Examples:\npython main.py discover-models                    # Auto-discover models file\npython main.py discover-models --models-file \"my_schema.py\"\n```\n\n### Database Discovery\n\n```bash\n# Discover and validate database configuration\npython main.py discover-db [--db URL]\n\n# Examples:\npython main.py discover-db                        # Auto-discover database URL\npython main.py discover-db --db \"postgresql://user:pass@localhost/db\"\n```\n\n### One-Time Database Configuration\n\n**Configure once, use everywhere!** Set up your database connection once during `init-db`, and all future commands will automatically use the same configuration.\n\n#### **Step 1: Configure Database (One Time Only)**\n```bash\n# PostgreSQL (most common)\npython main.py init-db --host localhost --port 5432 --user myuser --password mypass --database mydb --type postgresql\n\n# MySQL\npython main.py init-db --host localhost --port 3306 --user myuser --password mypass --database mydb --type mysql\n\n# SQLite (no credentials needed)\npython main.py init-db --database myapp.db --type sqlite\n\n# Using complete URL\npython main.py init-db --db \"postgresql://user:pass@localhost/db\"\n```\n\n#### **Step 2: Use Commands Without Database Parameters**\n```bash\n# All these commands automatically use the saved configuration!\npython main.py apply\npython main.py rollback\npython main.py autogenerate -m \"Add new table\"\npython main.py plan\n```\n\n#### **Configuration Management**\n```bash\n# Show current configuration\npython main.py show-config\n\n# Reset configuration (go back to auto-discovery)\npython main.py reset-config\n```\n\n**Benefits:**\n- \u2705 **Configure Once**: Set database connection once during `init-db`\n- \u2705 **Use Everywhere**: All commands automatically use saved configuration\n- \u2705 **Override When Needed**: Can still override with command-line arguments\n- \u2705 **Secure**: Credentials stored in local config file (not in code)\n- \u2705 **Flexible**: Easy to change configuration anytime\n\n## \ud83c\udf33 Migration Graph (DAG) System\n\n**Advanced dependency management for complex migration scenarios!** The tool now supports Directed Acyclic Graphs (DAG) for managing migration dependencies, enabling parallel development and complex branching scenarios.\n\n### **Key DAG Features:**\n\n#### **1. Dependency Management**\n```yaml\n# Migration with dependencies\nversion: '20250113120000'\ndescription: Add user authentication system\nbranch: feature-auth\ndependencies: ['20250113100000']  # Depends on previous migration\nrevision_id: 'abc12345'\nchanges:\n  - add_table:\n      name: users\n      columns:\n        - name: id\n          type: INTEGER\n          primary_key: true\n        - name: username\n          type: VARCHAR(50)\n          unique: true\n```\n\n#### **2. Branch Support**\n```bash\n# Create a new migration branch\npython main.py create-branch feature-auth\n\n# Create a branch from specific migration\npython main.py create-branch feature-payments --base 20250113100000\n```\n\n#### **3. Parallel Development**\n```bash\n# Developer A works on auth branch\npython main.py autogenerate -m \"Add user table\" --branch feature-auth\n\n# Developer B works on payments branch  \npython main.py autogenerate -m \"Add payment table\" --branch feature-payments\n\n# Both can work simultaneously without conflicts\n```\n\n#### **4. Merge Branches**\n```bash\n# Merge two branches when ready\npython main.py merge-branches feature-auth feature-payments -m \"Merge auth and payments\"\n```\n\n### **DAG Commands:**\n\n| Command | Description | Example |\n|---------|-------------|---------|\n| `graph` | Show migration dependency graph | `python main.py graph` |\n| `validate-migration` | Validate migration for conflicts | `python main.py validate-migration migrations/20250113_add_users.yml` |\n| `create-branch` | Create new migration branch | `python main.py create-branch feature-auth` |\n| `merge-branches` | Merge two branches | `python main.py merge-branches feature-auth feature-payments` |\n| `status` | Comprehensive migration & schema status | `python main.py status` |\n| `status-quick` | Quick status overview | `python main.py status-quick` |\n\n### **DAG Workflow Example:**\n\n#### **Scenario: Multiple Developers Working in Parallel**\n\n```bash\n# 1. Initial setup\npython main.py init-db --host localhost --user myuser --password mypass --database mydb --type postgresql\n\n# 2. Developer A creates auth branch\npython main.py create-branch feature-auth\npython main.py autogenerate -m \"Add users table\" --branch feature-auth\npython main.py apply migrations/20250113120000_add_users_table.yml\n\n# 3. Developer B creates payments branch (from same base)\npython main.py create-branch feature-payments\npython main.py autogenerate -m \"Add payments table\" --branch feature-payments\npython main.py apply migrations/20250113130000_add_payments_table.yml\n\n# 4. Check migration graph\npython main.py graph\n# Output:\n# Migration Graph:\n# ==================================================\n# \n# Branch: main\n# --------------------\n#   20250113100000: Initial schema\n#     Dependencies: none\n#     Revision ID: def45678\n# \n# Branch: feature-auth\n# --------------------\n#   20250113120000: Add users table\n#     Dependencies: 20250113100000\n#     Revision ID: abc12345\n# \n# Branch: feature-payments\n# --------------------\n#   20250113130000: Add payments table\n#     Dependencies: 20250113100000\n#     Revision ID: ghi78901\n\n# 5. Merge branches when ready\npython main.py merge-branches feature-auth feature-payments -m \"Merge auth and payments\"\npython main.py apply migrations/20250113140000_merge_feature_auth_feature_payments.yml\n```\n\n### **DAG Benefits:**\n\n- \u2705 **Parallel Development**: Multiple developers can work on migrations simultaneously\n- \u2705 **Dependency Tracking**: Clear dependency relationships between migrations\n- \u2705 **Conflict Detection**: Automatic detection of migration conflicts\n- \u2705 **Branch Management**: Easy creation and merging of migration branches\n- \u2705 **Graph Visualization**: Visual representation of migration dependencies\n- \u2705 **Cycle Detection**: Prevents circular dependencies\n- \u2705 **Backward Compatible**: Existing linear migrations continue to work\n\n## \ud83d\udd0d Schema Inspection Utilities\n\n**Comprehensive database and migration status inspection!** The tool provides powerful commands to inspect your database schema and migration status with clear visual indicators.\n\n### **Status Commands:**\n\n#### **1. Comprehensive Status (`status`)**\n```bash\n# Full status report with schema validation\npython main.py status\n\n# Verbose mode with detailed information\npython main.py status --verbose\n\n# Check against specific models file\npython main.py status --models-file custom_models.py\n\n# Skip sync checking for faster execution\npython main.py status --no-check-sync\n```\n\n**Output Example:**\n```\n\ud83d\udd0d Migration & Schema Status Report\n============================================================\n\n\ud83d\udcca MIGRATION STATUS\n------------------------------\n\u2705 Applied migrations: 6\n\u23f3 Pending migrations: 0\n\n\ud83d\udd04 DATABASE SYNC STATUS\n------------------------------\nStatus: \u26a0\ufe0f Out of Sync\n  \u2022 Extra tables: migration_log\n\n\ud83d\udd17 DEPENDENCY HEALTH\n------------------------------\n\u2705 DAG is valid - no cycles detected\n\u2705 No dependency conflicts\n\n\ud83c\udfaf CURRENT STATE\n------------------------------\nCurrent heads: 20250913122220, 20250913122712\n\n\ud83d\udccb SUMMARY\n------------------------------\n\u2705 All migrations applied - database is up to date\n\u26a0\ufe0f Database schema may be out of sync - consider running 'python main.py autogenerate'\n```\n\n#### **2. Quick Status (`status-quick`)**\n```bash\n# Quick overview for CI/CD pipelines\npython main.py status-quick\n```\n\n**Output Example:**\n```\n\u2705 All migrations applied\n\ud83d\udcca Database has 5 tables\n\ud83c\udfaf Current heads: 20250913122220, 20250913122712\n```\n\n### **Status Indicators:**\n\n| Indicator | Meaning | Action Required |\n|-----------|---------|-----------------|\n| \u2705 **Applied** | Migration successfully applied to database | None |\n| \u23f3 **Pending** | Migration exists but not applied | Run `python main.py apply` |\n| \u26a0\ufe0f **Out of Sync** | Database schema differs from models | Run `python main.py autogenerate` |\n| \u274c **Error** | Migration or database error | Check logs and fix issues |\n| \u2753 **Unknown** | Cannot determine status | Check database connection |\n\n### **Schema Validation Features:**\n\n- **Table Comparison**: Compares current database tables with target models\n- **Missing Tables**: Identifies tables that should exist but don't\n- **Extra Tables**: Identifies tables that exist but aren't in models\n- **Dependency Health**: Validates migration dependency graph\n- **Conflict Detection**: Identifies migration conflicts and circular dependencies\n- **Branch Summary**: Shows migration status by branch\n\n### **Use Cases:**\n\n#### **Development Workflow:**\n```bash\n# Check status before starting work\npython main.py status\n\n# Quick check during development\npython main.py status-quick\n\n# Detailed inspection when debugging\npython main.py status --verbose\n```\n\n#### **CI/CD Pipeline:**\n```bash\n# Quick status check in CI\npython main.py status-quick\n\n# Full validation in staging\npython main.py status --check-sync\n```\n\n#### **Production Monitoring:**\n```bash\n# Monitor migration status\npython main.py status --no-check-sync\n\n# Validate against production models\npython main.py status --models-file production_models.py\n```\n\n## \ud83d\udcdd Migration File Formats\n\n### YAML Migrations\n\nYAML migrations use a declarative format for schema changes:\n\n```yaml\nversion: '20250101120000'\ndescription: Add users table with indexes\nchanges:\n- create_table:\n    table: users\n    columns:\n    - name: id\n      type: INTEGER\n      nullable: false\n      primary_key: true\n    - name: name\n      type: VARCHAR(100)\n      nullable: false\n    - name: email\n      type: VARCHAR(255)\n      nullable: true\n      unique: true\n\n- add_index:\n    table: users\n    name: idx_users_email\n    columns: [email]\n\n- add_column:\n    table: users\n    column: created_at\n    type: DATETIME\n    nullable: true\n\n- drop_column:\n    table: users\n    column: old_field\n```\n\n### Python Migrations\n\nPython migrations provide full programmatic control:\n\n```python\ndef upgrade(engine):\n    \"\"\"Apply the migration.\"\"\"\n    with engine.connect() as conn:\n        conn.execute(text(\"\"\"\n            CREATE TABLE users (\n                id INTEGER PRIMARY KEY,\n                name VARCHAR(100) NOT NULL,\n                email VARCHAR(255) UNIQUE\n            )\n        \"\"\"))\n\ndef downgrade(engine):\n    \"\"\"Rollback the migration.\"\"\"\n    with engine.connect() as conn:\n        conn.execute(text(\"DROP TABLE users\"))\n```\n\n## \ud83d\udd04 Supported Operations\n\n### Table Operations\n- `create_table` / `drop_table`\n- `rename_table`\n\n### Column Operations\n- `add_column` / `drop_column`\n- `alter_column` (type changes, nullable modifications)\n\n### Index Operations\n- `add_index` / `drop_index`\n\n### Advanced Features\n- **Metadata Preservation**: All operations store metadata for accurate rollback\n- **Table Rename Mapping**: Handle table renames with `rename_map.yml`\n- **Enhanced Rollback**: Automatic reversal of all supported operations\n- **Schema Validation**: Compare current schema with target schema\n\n## \u2699\ufe0f Configuration\n\n### \ud83d\udd10 Programmatic Configuration (Security-Conscious)\n\nFor organizations that prefer not to store database credentials in files, you can set the database URL programmatically:\n\n```python\n# In your application code\nfrom dbPorter import set_database_url\n\n# Set database URL directly in code\nset_database_url(\"postgresql://user:password@localhost:5432/mydatabase\")\n\n# Now all migration commands will use this URL automatically\n# dbporter status\n# dbporter apply migrations/20250101_add_users.yml\n```\n\n**Benefits:**\n- \u2705 **No credential files**: Database URL not stored on disk\n- \u2705 **Environment variables**: Can use `os.getenv(\"DATABASE_URL\")`\n- \u2705 **Application integration**: Works with existing app configuration\n- \u2705 **CI/CD friendly**: Perfect for automated deployments\n- \u2705 **Multi-tenant ready**: Dynamic database URLs per tenant\n\n**Example with environment variables:**\n```python\nimport os\nfrom dbPorter import set_database_url\n\n# From environment variable\ndb_url = os.getenv(\"DATABASE_URL\")\nif db_url:\n    set_database_url(db_url)\nelse:\n    raise ValueError(\"DATABASE_URL environment variable not set\")\n```\n\n### \ud83d\udd04 Configuration Priority\n\nThe tool uses the following priority order for database configuration:\n\n1. **Command-line arguments** (highest priority)\n   ```bash\n   dbporter status --db \"postgresql://user:pass@host:port/db\"\n   ```\n\n2. **Programmatic configuration** (security-conscious)\n   ```python\n   from dbPorter import set_database_url\n   set_database_url(\"postgresql://user:pass@host:port/db\")\n   ```\n\n3. **Saved configuration** (traditional)\n   ```bash\n   dbporter init-db --host localhost --user myuser --password mypass\n   ```\n\n4. **Environment variables** (fallback)\n   ```bash\n   export DB_URL=\"postgresql://user:pass@host:port/db\"\n   dbporter status\n   ```\n\n5. **Auto-discovery** (lowest priority)\n   - Automatically detects database from common patterns\n\n### \ud83d\udcc1 File-Based Configuration (Traditional)\n\n### Environment Variables\n\nCreate a `.env` file in your project root:\n\n```env\n# Database connection\nDB_URL=sqlite:///your_database.db\n\n# For PostgreSQL\n# DB_URL=postgresql://username:password@localhost:5432/database_name\n\n# For MySQL\n# DB_URL=mysql://username:password@localhost:3306/database_name\n```\n\n### Table Rename Mapping\n\nCreate `rename_map.yml` to handle table renames:\n\n```yaml\ntable_renames:\n  old_table_name: new_table_name\n  legacy_users: users\n```\n\n## \ud83d\udd12 Safety Features\n\n- **Transaction Support**: All migrations run in database transactions\n- **Rollback Capability**: Every migration can be safely rolled back\n- **Metadata Preservation**: Column types, constraints, and indexes are preserved\n- **Dry-Run Mode**: Preview changes before applying\n- **Migration Logging**: Complete audit trail of all applied migrations\n\n## \ud83d\udc1b Troubleshooting\n\n### Common Issues\n\n1. **Migration not found**\n   ```bash\n   # Ensure migration file exists and is properly formatted\n   python main.py plan migrations/your_migration.yml\n   ```\n\n2. **Database connection failed**\n   ```bash\n   # Check your DB_URL in .env file\n   python main.py init-db --db \"sqlite:///test.db\"\n   ```\n\n3. **Rollback failed**\n   ```bash\n   # Check migration log for the last applied migration\n   # Ensure database is in a consistent state\n   ```\n\n### Debug Mode\n\nEnable verbose logging by modifying the commands to include debug output:\n\n```python\n# Add logging configuration in your migration files\nimport logging\nlogging.basicConfig(level=logging.DEBUG)\n```\n\n## \ud83e\udd1d Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## \ud83d\ude4f Acknowledgments\n\n- Built with [SQLAlchemy](https://www.sqlalchemy.org/) for database abstraction\n- CLI powered by [Typer](https://typer.tiangolo.com/)\n- YAML support via [PyYAML](https://pyyaml.org/)\n\n---\n\n**Need help?** Check the command help with `python main.py --help` or `python main.py [command] --help`\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A powerful database migration tool with DAG support, automatic rollback, and schema inspection",
    "version": "0.1.6",
    "project_urls": {
        "Bug Tracker": "https://github.com/karan-kap00r/dbPorter/issues",
        "Documentation": "https://github.com/karan-kap00r/dbPorter/blob/main/README.md",
        "Homepage": "https://github.com/karan-kap00r/dbPorter",
        "Repository": "https://github.com/karan-kap00r/dbPorter.git"
    },
    "split_keywords": [
        "database",
        " migration",
        " schema",
        " sqlalchemy",
        " yaml",
        " dag",
        " rollback",
        " postgresql",
        " mysql",
        " sqlite",
        " oracle",
        " sqlserver",
        " version-control",
        " database-versioning",
        " schema-management"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "ab5e62d3f4c8c5b4e6ed048c4c806c4c46b8406433766ddc0e9e76991b2dc35b",
                "md5": "719d5051c2dd48ddf4ad03fcdf84d185",
                "sha256": "abd88008632f4fbffd1fe018a77303d5f3f891523b0b3ee03a500d368f7a1bce"
            },
            "downloads": -1,
            "filename": "dbporter-0.1.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "719d5051c2dd48ddf4ad03fcdf84d185",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 36091,
            "upload_time": "2025-09-14T19:20:13",
            "upload_time_iso_8601": "2025-09-14T19:20:13.405504Z",
            "url": "https://files.pythonhosted.org/packages/ab/5e/62d3f4c8c5b4e6ed048c4c806c4c46b8406433766ddc0e9e76991b2dc35b/dbporter-0.1.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9e8b8e0c413513342c0e6cca292dab998998cb657f984ea5f3db66d34d70d37b",
                "md5": "db38e0193f4f052f9f254b5f7586ae79",
                "sha256": "5d94dff58c092b224b80c043fe1c5921bdc59fb878d28f0d93558c3d19e02cb7"
            },
            "downloads": -1,
            "filename": "dbporter-0.1.6.tar.gz",
            "has_sig": false,
            "md5_digest": "db38e0193f4f052f9f254b5f7586ae79",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 40073,
            "upload_time": "2025-09-14T19:20:15",
            "upload_time_iso_8601": "2025-09-14T19:20:15.398885Z",
            "url": "https://files.pythonhosted.org/packages/9e/8b/8e0c413513342c0e6cca292dab998998cb657f984ea5f3db66d34d70d37b/dbporter-0.1.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-14 19:20:15",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "karan-kap00r",
    "github_project": "dbPorter",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "typer",
            "specs": [
                [
                    ">=",
                    "0.9.0"
                ]
            ]
        },
        {
            "name": "sqlalchemy",
            "specs": [
                [
                    ">=",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "pyyaml",
            "specs": [
                [
                    ">=",
                    "6.0"
                ]
            ]
        },
        {
            "name": "python-dotenv",
            "specs": [
                [
                    ">=",
                    "1.0.0"
                ]
            ]
        },
        {
            "name": "tabulate",
            "specs": [
                [
                    ">=",
                    "0.9.0"
                ]
            ]
        },
        {
            "name": "typing-extensions",
            "specs": [
                [
                    ">=",
                    "4.0.0"
                ]
            ]
        }
    ],
    "lcname": "dbporter"
}
        
Elapsed time: 1.59355s