def test_init_on_fresh_db_creates_new_table(self): si = MigrationState() self.assert_equal(False, si.migration_table_present()) si.init() self.assert_equal(True, si.migration_table_present())
def test_init_on_initialized_db_does_nothing(self): self.cursor.execute(create_new) si = MigrationState() self.assert_equal(True, si.migration_table_present()) si.init() self.assert_equal(True, si.migration_table_present())
def test_all_migrations_applied(self): db = MigrationDb(migrations = ['001_foo', '002_DEV_bar', '005_omg', '006_DEV_hello']) si = MigrationState(migration_db=db) si.init() si.mark_as_applied('005_omg') si.mark_as_applied('001_foo') si.mark_as_applied('009_bogus') self.assert_equal(['001_foo', '005_omg', '009_bogus'], si.all_migrations_applied())
def test_when_doing_something_then_loggged(self): db = MigrationDb(directory=self.mock_migrations_dir) db.warn = WarningsMocker() si = MigrationState(migration_db=db, dev=True) si.init() si.apply('001_foo') si.mark_as_unapplied('001_foo') si.apply('001_foo') si.mark_as_applied('005_omg') si.unapply('001_foo') self.assert_equal([ ("apply", "001_foo", "success"), ("mark_as_unapplied", "001_foo", "success"), ("apply", "001_foo", "success"), ("mark_as_applied", "005_omg", "success"), ("unapply", "001_foo", "success"), ], [row[:3] for row in get_log()]) self.assert_equal(True, isinstance(get_log()[0][3], datetime))
def test_when_doing_something_then_loggged(self): db = MigrationDb(directory=self.mock_migrations_dir) db.warn = WarningsMocker() si = MigrationState(migration_db=db, dev=True) si.init() si.apply("001_foo") si.mark_as_unapplied("001_foo") si.apply("001_foo") si.mark_as_applied("005_omg") si.unapply("001_foo") self.assert_equal( [ ("apply", "001_foo", "success"), ("mark_as_unapplied", "001_foo", "success"), ("apply", "001_foo", "success"), ("mark_as_applied", "005_omg", "success"), ("unapply", "001_foo", "success"), ], [row[:3] for row in get_log()], ) self.assert_equal(True, isinstance(get_log()[0][3], datetime))
def handle(self, *args, **options): try: migrations_dir = settings.DMIGRATIONS_DIR except AttributeError: print "You need to add DMIGRATIONS_DIR to your settings" return migration_db = MigrationDb(directory = migrations_dir) migration_state = MigrationState( migration_db = migration_db, dev = options.get('dev') ) verbosity = int(options.get('verbosity', 1)) if not args or args[0] == 'help': # TODO: Do this without calling os.system os.system('python manage.py help dmigrate') return elif args[0] in 'all up down upto downto to apply unapply'.split(): migration_state.init() for (migration_name, action) in migration_state.plan(*args): migration = migration_db.load_migration_object(migration_name) if action == 'up': if verbosity >= 1: print "Applying migration %s" % migration.name if not options.get('print_plan'): migration_state.apply(migration_name) else: if verbosity >= 1: print "Unapplying migration %s" % migration.name if not options.get('print_plan'): migration_state.unapply(migration_name) elif args[0] == 'mark_as_applied': migration_state.init() for name in args[1:]: resolved_name = migration_state.resolve_name(name) if resolved_name == None: raise NoSuchMigrationError(name) migration_state.mark_as_applied(resolved_name) elif args[0] == 'mark_as_unapplied': migration_state.init() for name in args[1:]: resolved_name = migration_state.resolve_name(name) if resolved_name == None: raise NoSuchMigrationError(name) migration_state.mark_as_unapplied(resolved_name) elif args[0] == 'list': migration_state.init() for migration_name in migration_db.list(): if migration_state.is_applied(migration_name): print "* [+] %s" % migration_name else: print "* [ ] %s" % migration_name migrations_not_in_db = migration_state.applied_but_not_in_db() if migrations_not_in_db: print "These migrations are marked as applied but cannot " \ "be found:" for migration_name in migrations_not_in_db: print "* [?] %s" % migration_name return elif args[0] == 'init': migration_state.init() elif args[0] == 'cat': for name in args[1:]: print open( migration_db.resolve_migration_path(name), 'r' ).read() return else: raise CommandError( 'Argument should be one of: list, help, up, down, all, init, ' 'apply, unapply, to, downto, upto, mark_as_applied, ' 'mark_as_unapplied' ) # Ensure Django permissions and content_types have been created # NOTE: Don't run if django_content_type doesn't exist yet. if table_present('django_content_type'): from django.contrib.auth.management import create_permissions from django.db import models for app in models.get_apps(): if verbosity >= 1: create_permissions(app, set(), 2) else: create_permissions(app, set(), 1)
def test_plan(self): db = MigrationDb(migrations = ['001_foo', '002_bar', '005_omg', '005_hello']) si = MigrationState(migration_db=db) si.init() self.assert_plans(si, ['apply', '1'], [('001_foo', 'up')], ['apply', '001_foo'], [('001_foo', 'up')], ['apply', '1', '2'], [('001_foo', 'up'), ('002_bar', 'up')], ['unapply', '001_foo'], [], ['unapply', '1', '2'], [], ['all'], [('001_foo', 'up'), ('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')], ['up'], [('001_foo', 'up')], ['down'], [], ['to', '1'], [('001_foo', 'up')], ['to', '2'], [('001_foo', 'up'), ('002_bar', 'up')], ['upto', '2'], [('001_foo', 'up'), ('002_bar', 'up')], ['upto', '002_bar'], [('001_foo', 'up'), ('002_bar', 'up')], ['upto', '4'], [('001_foo', 'up'), ('002_bar', 'up')], ['upto', '004_foo'], NoSuchMigrationError, ['upto', '5'], AmbiguousMigrationNameError, ['upto', '005_hello'], [('001_foo', 'up'), ('002_bar', 'up'), ('005_hello', 'up')], ['upto', '005_omg'], [('001_foo', 'up'), ('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')], ['downto', '1'], [], ['downto', '2'], [], ) si.mark_as_applied('002_bar') self.assert_plans(si, ['apply', '1'], [('001_foo', 'up')], ['apply', '001_foo'], [('001_foo', 'up')], ['apply', '1', '2'], [('001_foo', 'up')], ['unapply', '001_foo'], [], ['unapply', '1', '2'], [('002_bar', 'down')], ['all'], [('001_foo', 'up'), ('005_hello', 'up'), ('005_omg', 'up')], ['up'], [('001_foo', 'up')], ['down'], [('002_bar', 'down')], ['to', '1'], [('002_bar', 'down'), ('001_foo', 'up')], ['to', '2'], [('001_foo', 'up')], ['upto', '2'], [('001_foo', 'up')], ['upto', '002_bar'], [('001_foo', 'up')], ['upto', '4'], [('001_foo', 'up')], ['upto', '004_foo'], NoSuchMigrationError, ['upto', '5'], AmbiguousMigrationNameError, ['upto', '005_hello'], [('001_foo', 'up'), ('005_hello', 'up')], ['upto', '005_omg'], [('001_foo', 'up'), ('005_hello', 'up'), ('005_omg', 'up')], ['downto', '1'], [('002_bar', 'down')], ['downto', '2'], [], ) si.mark_as_applied('001_foo') self.assert_plans(si, ['apply', '1'], [], ['apply', '001_foo'], [], ['apply', '1', '2'], [], ['unapply', '001_foo'], [('001_foo', 'down')], ['unapply', '1', '2'], [('001_foo', 'down'), ('002_bar', 'down')], ['all'], [('005_hello', 'up'), ('005_omg', 'up')], ['up'], [('005_hello', 'up')], ['down'], [('002_bar', 'down')], ['to', '1'], [('002_bar', 'down')], ['to', '2'], [], ['upto', '2'], [], ['upto', '002_bar'], [], ['upto', '4'], [], ['upto', '004_foo'], NoSuchMigrationError, ['upto', '5'], AmbiguousMigrationNameError, ['upto', '005_hello'], [('005_hello', 'up')], ['upto', '005_omg'], [('005_hello', 'up'), ('005_omg', 'up')], ['downto', '1'], [('002_bar', 'down')], ['downto', '2'], [], ) si.mark_as_unapplied('002_bar') self.assert_plans(si, ['apply', '1'], [], ['apply', '001_foo'], [], ['apply', '1', '2'], [('002_bar', 'up')], ['unapply', '001_foo'], [('001_foo', 'down')], ['unapply', '1', '2'], [('001_foo', 'down')], ['all'], [('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')], ['up'], [('002_bar', 'up')], ['down'], [('001_foo', 'down')], ['to', '1'], [], ['to', '2'], [('002_bar', 'up')], ['upto', '2'], [('002_bar', 'up')], ['upto', '002_bar'], [('002_bar', 'up')], ['upto', '4'], [('002_bar', 'up')], ['upto', '004_foo'], NoSuchMigrationError, ['upto', '5'], AmbiguousMigrationNameError, ['upto', '005_hello'], [('002_bar', 'up'), ('005_hello', 'up')], ['upto', '005_omg'], [('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')], ['downto', '1'], [], ['downto', '2'], [], ) si.mark_as_applied('002_bar') si.mark_as_applied('005_hello') si.mark_as_applied('005_omg') self.assert_plans(si, ['apply', '1'], [], ['apply', '001_foo'], [], ['apply', '1', '2'], [], ['unapply', '001_foo'], [('001_foo', 'down')], ['unapply', '1', '2'], [('001_foo', 'down'), ('002_bar', 'down')], ['all'], [], ['up'], [], ['down'], [('005_omg', 'down')], ['to', '1'], [('005_omg', 'down'), ('005_hello', 'down'), ('002_bar', 'down')], ['to', '2'], [('005_omg', 'down'), ('005_hello', 'down')], ['upto', '2'], [], ['upto', '002_bar'], [], ['upto', '4'], [], ['upto', '004_foo'], NoSuchMigrationError, ['upto', '5'], AmbiguousMigrationNameError, ['upto', '005_hello'], [], ['upto', '005_omg'], [], ['downto', '1'], [('005_omg', 'down'), ('005_hello', 'down'), ('002_bar', 'down')], ['downto', '2'], [('005_omg', 'down'), ('005_hello', 'down')], )
def test_plan_with_dev(self): # NOTE: si.mark_as_applied modifies global state, not si (MigrationState) object. # There is only one meaningful MigrationState object per database, # so it's an almost-singleton unless we support multiple databases at the same time. # This makes testing quite ugly. db = MigrationDb(migrations = ['001_foo', '002_DEV_bar', '005_omg', '006_DEV_hello']) si = MigrationState(migration_db=db) si.init() self.assert_plans(si, ['up'], [('001_foo', 'up')], ['upto', '5'], [('001_foo', 'up'), ('005_omg', 'up')], ['upto', '6'], [('001_foo', 'up'), ('005_omg', 'up')], ['all'], [('001_foo', 'up'), ('005_omg', 'up')], ) si = MigrationState(migration_db=db, dev=True) si.init() self.assert_plans(si, ['up'], [('001_foo', 'up')], ['upto', '5'], [('001_foo', 'up'), ('002_DEV_bar', 'up'), ('005_omg', 'up')], ['upto', '6'], [('001_foo', 'up'), ('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')], ['all'], [('001_foo', 'up'), ('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')], ) si.mark_as_applied('001_foo') si = MigrationState(migration_db=db) si.init() self.assert_plans(si, ['up'], [('005_omg', 'up')], ['upto', '5'], [('005_omg', 'up')], ['upto', '6'], [('005_omg', 'up')], ['all'], [('005_omg', 'up')], ) si = MigrationState(migration_db=db, dev=True) si.init() self.assert_plans(si, ['up'], [('002_DEV_bar', 'up')], ['upto', '5'], [('002_DEV_bar', 'up'), ('005_omg', 'up')], ['upto', '6'], [('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')], ['all'], [('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')], ) si.mark_as_applied('002_DEV_bar') si = MigrationState(migration_db=db) si.init() self.assert_plans(si, ['up'], [('005_omg', 'up')], ['upto', '5'], [('005_omg', 'up')], ['upto', '6'], [('005_omg', 'up')], ['all'], [('005_omg', 'up')], ['down'], [('001_foo', 'down')], # Is it better to always assume --dev on down ? ) si = MigrationState(migration_db=db, dev=True) si.init() self.assert_plans(si, ['up'], [('005_omg', 'up')], ['upto', '5'], [('005_omg', 'up')], ['upto', '6'], [('005_omg', 'up'), ('006_DEV_hello', 'up')], ['all'], [('005_omg', 'up'), ('006_DEV_hello', 'up')], ['down'], [('002_DEV_bar', 'down')], )
def handle(self, *args, **options): try: migrations_dir = settings.DMIGRATIONS_DIR except AttributeError: print "You need to add DMIGRATIONS_DIR to your settings" return migration_db = MigrationDb(directory = migrations_dir) migration_state = MigrationState( migration_db = migration_db, dev = options.get('dev') ) verbosity = int(options.get('verbosity', 1)) if not args or args[0] == 'help': self.print_help(sys.argv[0], 'dmigrate') return elif args[0] in 'all all_hard up down upto downto to apply unapply'.split(): migration_state.init() for (migration_name, action) in migration_state.plan(*args): migration = migration_db.load_migration_object(migration_name) start_time = time.time() if action == 'up': if verbosity >= 1: print "Applying migration %s" % migration.name if not options.get('print_plan'): migration_state.apply(migration_name) else: if verbosity >= 1: print "Unapplying migration %s" % migration.name if not options.get('print_plan'): migration_state.unapply(migration_name) if options.get('print_time'): print "Migration %s ran %.1f seconds" % (migration.name, time.time() - start_time) elif args[0] == 'mark_as_applied': migration_state.init() for name in args[1:]: resolved_name = migration_state.resolve_name(name) if resolved_name == None: raise NoSuchMigrationError(name) migration_state.mark_as_applied(resolved_name) elif args[0] == 'mark_as_unapplied': migration_state.init() for name in args[1:]: resolved_name = migration_state.resolve_name(name) if resolved_name == None: raise NoSuchMigrationError(name) migration_state.mark_as_unapplied(resolved_name) elif args[0] == 'list': migration_state.init() for migration_name in migration_db.list(): if migration_state.is_applied(migration_name, use_cache=True): print "* [+] %s" % migration_name else: print "* [ ] %s" % migration_name migrations_not_in_db = migration_state.applied_but_not_in_db() if migrations_not_in_db: print "These migrations are marked as applied but cannot " \ "be found:" for migration_name in migrations_not_in_db: print "* [?] %s" % migration_name return elif args[0] == 'init': migration_state.init() elif args[0] == 'cat': for name in args[1:]: print open( migration_db.resolve_migration_path(name), 'r' ).read() return else: raise CommandError( 'Argument should be one of: list, help, up, down, all, all_hard, init, ' 'apply, unapply, to, downto, upto, mark_as_applied, ' 'mark_as_unapplied' ) # Ensure Django permissions and content_types have been created # NOTE: Don't run if django_content_type doesn't exist yet. if table_present('django_content_type'): from django.contrib.auth.management import create_permissions from django.db import models for app in models.get_apps(): if verbosity >= 1: create_permissions(app, set(), 2) else: create_permissions(app, set(), 1)