Skip to content

Instantly share code, notes, and snippets.

@hgdeoro
Created July 20, 2012 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hgdeoro/3152320 to your computer and use it in GitHub Desktop.
Save hgdeoro/3152320 to your computer and use it in GitHub Desktop.
Django management command to assert all South migrations are applied
"""
Assert migrations are applied management command.
"""
import sys
from optparse import make_option
from django.core.management.base import BaseCommand
from django.conf import settings
from south import migration
from south.migration import Migrations
from south.exceptions import NoMigrations
from south.db import DEFAULT_DB_ALIAS
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--all', action='store_true', dest='all_apps', default=False,
help='Run the specified migration for all apps.'),
make_option('--database', action='store', dest='database',
default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. '
'Defaults to the "default" database.'),
)
help = "Fails if any migration is pending" #@ReservedAssignment
args = "[appname] [migrationname|zero] [--all] [--database=dbalias]"
def handle(self, app=None, database=DEFAULT_DB_ALIAS, **options):
# NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb
# This code imports any module named 'management' in INSTALLED_APPS.
# The 'management' module is the preferred way of listening to post_syncdb
# signals, and since we're sending those out with create_table migrations,
# we need apps to behave correctly.
for app_name in settings.INSTALLED_APPS:
try:
__import__(app_name + '.management', {}, {}, [''])
except ImportError, exc:
msg = exc.args[0]
if not msg.startswith('No module named') or 'management' not in msg:
raise
# END DJANGO DUPE CODE
# if all_apps flag is set, shift app over to target
if options.get('all_apps', False):
app = None
# Migrate each app
if app:
try:
apps = [Migrations(app)]
except NoMigrations:
print "The app '%s' does not appear to use migrations." % app
print "./manage.py migrate " + self.args
return
else:
apps = list(migration.all_migrations())
assert_synced(apps, database, **options)
sys.exit(1)
def assert_synced(apps, database=DEFAULT_DB_ALIAS, **options):
"""
Assert all migrations are applied
"""
from south.models import MigrationHistory
applied_migrations = MigrationHistory.objects.filter(app_name__in=[app.app_label() for app in apps])
if database != DEFAULT_DB_ALIAS:
applied_migrations = applied_migrations.using(database)
applied_migration_names = ['%s.%s' % (mi.app_name, mi.migration) for mi in applied_migrations]
res = []
for app in apps:
print " " + app.app_label()
# Get the migrations object
for migration in app:
if migration.app_label() + "." + migration.name() in applied_migration_names:
applied_migration = applied_migrations.get(app_name=migration.app_label(), migration=migration.name())
res += [format_migration_list_item(migration.name(), applied=applied_migration.applied, **options)]
else:
res += [format_migration_list_item(migration.name(), applied=False, **options)]
if False in res:
print "At least one migration isn't applied"
sys.exit(1)
sys.exit(0)
def format_migration_list_item(name, applied=True, **options):
if applied:
if int(options.get('verbosity')) >= 2:
print ' (*) %-80s (applied %s)' % (name, applied)
return True
else:
print ' (*) %s' % name
return True
else:
print ' ( ) %s' % name
return False
@hgdeoro
Copy link
Author

hgdeoro commented Jul 20, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment