Index
invariants
Django migration audit invariants.
This package contains all invariants for verifying migration consistency.
Base invariants (in base.py): - NoMissingMigrationFiles - SquashMigrationsProperlyReplaced - AllExpectedTablesExist - NoUnexpectedTables - AllExpectedColumnsExist
Column invariants (in columns.py): - NoUnexpectedColumns - ColumnNullabilityMatches - NoMissingPrimaryKeys
Table invariants (in tables.py): - NoEmptyTables - TableNamingConvention - NoLegacyTables - TableCountReasonable
Constraint invariants (in constraints.py): - ForeignKeyColumnsExist - NoOrphanedForeignKeys - PrimaryKeyExists - UniqueConstraintHint - AllExpectedIndexesExist - AllExpectedConstraintsExist - NoUnexpectedIndexes - NoUnexpectedConstraints
__all__ = ['Invariant', 'ComparisonAInvariant', 'ComparisonBInvariant', 'Violation', 'Severity', 'NoMissingMigrationFiles', 'SquashMigrationsProperlyReplaced', 'AllExpectedTablesExist', 'NoUnexpectedTables', 'AllExpectedColumnsExist', 'NoUnexpectedColumns', 'ColumnNullabilityMatches', 'NoMissingPrimaryKeys', 'NoEmptyTables', 'TableNamingConvention', 'NoLegacyTables', 'TableCountReasonable', 'ForeignKeyColumnsExist', 'NoOrphanedForeignKeys', 'PrimaryKeyExists', 'UniqueConstraintHint', 'AllExpectedIndexesExist', 'AllExpectedConstraintsExist', 'NoUnexpectedIndexes', 'NoUnexpectedConstraints']
module-attribute
AllExpectedColumnsExist
Bases: ComparisonBInvariant
Verify that all expected columns exist with correct types.
name
property
description
property
check(expected_schema, actual_schema)
AllExpectedTablesExist
Bases: ComparisonBInvariant
Verify that all expected tables exist in the actual database.
name
property
description
property
check(expected_schema, actual_schema)
ComparisonAInvariant
Bases: Invariant
Base class for Comparison A invariants (Trust Verification).
These invariants verify migration history ↔ migration code consistency.
ComparisonBInvariant
Bases: Invariant
Base class for Comparison B invariants (Reality Check).
These invariants verify expected schema ↔ actual schema consistency.
Invariant
Bases: ABC
Base class for all invariants.
Invariants are verification rules that check for consistency between different inputs in the django-migration-audit system.
name
abstractmethod
property
Human-readable name for this invariant.
description
abstractmethod
property
Description of what this invariant checks.
check(**kwargs)
abstractmethod
Check the invariant and return any violations.
Returns:
| Type | Description |
|---|---|
List[Violation]
|
List of Violation objects (empty list if no violations) |
NoMissingMigrationFiles
Bases: ComparisonAInvariant
Verify that all applied migrations have corresponding files on disk.
name
property
description
property
check(migration_history)
NoUnexpectedTables
Bases: ComparisonBInvariant
Verify that no unexpected tables exist in the actual database.
name
property
description
property
check(expected_schema, actual_schema)
Severity
Bases: Enum
Severity levels for invariant violations.
ERROR = 'error'
class-attribute
instance-attribute
WARNING = 'warning'
class-attribute
instance-attribute
INFO = 'info'
class-attribute
instance-attribute
SquashMigrationsProperlyReplaced
Bases: ComparisonAInvariant
Verify that squashed migrations properly replace their originals.
name
property
description
property
check(migration_history)
Violation(invariant_name, severity, message, details=None)
dataclass
Represents a single invariant violation.
invariant_name
instance-attribute
severity
instance-attribute
message
instance-attribute
details = None
class-attribute
instance-attribute
__str__()
ColumnNullabilityMatches
Bases: ComparisonBInvariant
Verify column nullability matches between expected and actual schema.
This checks that columns have the correct NULL/NOT NULL constraint. Mismatches can occur when migrations are modified or database is manually altered.
name
property
description
property
check(expected_schema, actual_schema)
NoMissingPrimaryKeys
Bases: ComparisonBInvariant
Verify all tables have a primary key column.
This is a best practice check to ensure all tables have a primary key. Most Django models have an 'id' field as primary key.
name
property
description
property
check(expected_schema, actual_schema)
NoUnexpectedColumns
Bases: ComparisonBInvariant
Verify no unexpected columns exist in actual schema.
This checks for columns that exist in the database but are not defined in the expected schema (from migrations). This can happen when columns are manually added to the database.
name
property
description
property
check(expected_schema, actual_schema)
AllExpectedConstraintsExist
Bases: ComparisonBInvariant
Verify that all constraints defined in migrations exist in the actual database.
name
property
description
property
check(expected_schema, actual_schema)
AllExpectedIndexesExist
Bases: ComparisonBInvariant
Verify that all indexes defined in migrations exist in the actual database.
name
property
description
property
check(expected_schema, actual_schema)
ForeignKeyColumnsExist
Bases: ComparisonBInvariant
Verify foreign key columns exist for relationship fields.
Django creates foreign key columns with '_id' suffix. This invariant checks that these columns exist when expected.
name
property
description
property
check(expected_schema, actual_schema)
NoOrphanedForeignKeys
Bases: ComparisonBInvariant
Verify no foreign key columns exist without corresponding tables.
This checks that tables referenced by foreign keys actually exist. Note: This is a heuristic check based on column naming patterns.
name
property
description
property
check(expected_schema, actual_schema)
NoUnexpectedConstraints
Bases: ComparisonBInvariant
Verify no constraints exist in the database that aren't defined in migrations.
Reports WARNING because Django creates implicit unique constraints for fields with unique=True and unique_together, which are not tracked via AddConstraint operations. Users should review violations rather than treating them all as hard errors.
name
property
description
property
check(expected_schema, actual_schema)
NoUnexpectedIndexes
Bases: ComparisonBInvariant
Verify no indexes exist in the database that aren't defined in migrations.
Reports WARNING because Django also creates implicit indexes (e.g. for ForeignKey columns) that are not tracked via AddIndex operations. Users should review violations rather than treating them all as hard errors.
name
property
description
property
check(expected_schema, actual_schema)
PrimaryKeyExists
Bases: ComparisonBInvariant
Verify each table has a primary key column.
This checks that tables have an 'id' column which is typically the primary key in Django models.
name
property
description
property
check(expected_schema, actual_schema)
UniqueConstraintHint
Bases: ComparisonBInvariant
Provide hints about potential unique constraint issues.
This is a placeholder for future unique constraint checking. Currently, it just checks for common patterns that suggest unique constraints should exist.
name
property
description
property
check(expected_schema, actual_schema)
NoEmptyTables
Bases: ComparisonBInvariant
Verify no tables exist without any columns.
This is a sanity check to detect corrupted or improperly created tables.
name
property
description
property
check(expected_schema, actual_schema)
NoLegacyTables
Bases: ComparisonBInvariant
Verify no tables with legacy/deprecated prefixes exist.
This helps identify old tables that should have been removed. Customize the LEGACY_PREFIXES set for your project.
LEGACY_PREFIXES = {'old_', 'legacy_', 'temp_', 'tmp_', 'backup_', 'deprecated_'}
class-attribute
instance-attribute
name
property
description
property
check(expected_schema, actual_schema)
TableCountReasonable
Bases: ComparisonBInvariant
Verify the number of tables is reasonable.
This is a sanity check to detect issues like: - Too many tables (possible test pollution) - Too few tables (possible data loss)
MIN_TABLES = 1
class-attribute
instance-attribute
MAX_TABLES = 500
class-attribute
instance-attribute
name
property
description
property
check(expected_schema, actual_schema)
TableNamingConvention
Bases: ComparisonBInvariant
Verify tables follow Django's naming convention.
Django typically names tables as 'app_modelname'. This invariant checks that all non-Django tables follow this pattern.