Skip to content

type_bridge.migration.generator

generator

Migration generator for auto-generating migrations from model changes.

MigrationGenerator

MigrationGenerator(db, migrations_dir)

Generates migration files from model changes.

Compares current models against the last migration state and generates appropriate operations for the detected changes.

Example

generator = MigrationGenerator(db, Path("migrations"))

Generate migration from models

path = generator.generate([Person, Company, Employment], name="initial")

Creates: migrations/0001_initial.py

Generate empty migration for manual editing

path = generator.generate([], name="custom_changes", empty=True)

Initialize generator.

Parameters:

Name Type Description Default
db Database

Database connection

required
migrations_dir Path

Directory to write migration files

required
Source code in type_bridge/migration/generator.py
def __init__(self, db: Database, migrations_dir: Path):
    """Initialize generator.

    Args:
        db: Database connection
        migrations_dir: Directory to write migration files
    """
    self.db = db
    self.migrations_dir = migrations_dir
    self.loader = MigrationLoader(migrations_dir)

generate

generate(models, name='auto', empty=False)

Generate a migration file.

Parameters:

Name Type Description Default
models list[type[Entity | Relation]]

Model classes to check for changes

required
name str

Migration name suffix (e.g., "initial", "add_company")

'auto'
empty bool

Create empty migration for manual editing

False

Returns:

Type Description
Path | None

Path to created file, or None if no changes detected

Source code in type_bridge/migration/generator.py
def generate(
    self,
    models: list[type[Entity | Relation]],
    name: str = "auto",
    empty: bool = False,
) -> Path | None:
    """Generate a migration file.

    Args:
        models: Model classes to check for changes
        name: Migration name suffix (e.g., "initial", "add_company")
        empty: Create empty migration for manual editing

    Returns:
        Path to created file, or None if no changes detected
    """
    # Get current state
    existing = self.loader.discover()

    # Determine next migration number
    next_num = self.loader.get_next_number()

    # Determine dependencies
    dependencies: list[tuple[str, str]] = []
    if existing:
        last = existing[-1]
        dependencies.append((last.migration.app_label, last.migration.name))

    if empty:
        operations_code = "    operations: ClassVar[list[Operation]] = []"
        models_code = ""
        imports_code = self._generate_empty_imports()
        description = "empty migration"
    else:
        # Detect changes - now always returns operations
        operations, _ = self._detect_changes(models, existing)

        if not operations:
            logger.info("No changes detected")
            return None

        # Always use operations-based migration
        operations_code = self._render_operations(operations)
        models_code = ""
        imports_code = self._generate_operations_imports(operations)
        description = self._describe_operations(operations)

    # Generate filename
    migration_name = f"{next_num:04d}_{name}"
    filename = f"{migration_name}.py"
    filepath = self.migrations_dir / filename

    # Ensure directory exists
    self.migrations_dir.mkdir(parents=True, exist_ok=True)

    # Generate content
    content = self._render_migration(
        class_name=self._to_class_name(name),
        dependencies=dependencies,
        operations_code=operations_code,
        models_code=models_code,
        imports_code=imports_code,
        description=description,
    )

    filepath.write_text(content)
    logger.info(f"Created migration: {filepath}")

    return filepath