def test_all(self): M1 = Migrations(__import__("fakeapp", {}, {}, [''])) M2 = Migrations(__import__("otherfakeapp", {}, {}, [''])) self.assertEqual( [M1, M2], list(all_migrations()), )
def test_plans(self): circular_a = Migrations('circular_a') circular_b = Migrations('circular_b') self.assertRaises(exceptions.CircularDependency, Migration.forwards_plan, circular_a[-1]) self.assertRaises(exceptions.CircularDependency, Migration.forwards_plan, circular_b[-1]) self.assertRaises(exceptions.CircularDependency, Migration.backwards_plan, circular_a[-1]) self.assertRaises(exceptions.CircularDependency, Migration.backwards_plan, circular_b[-1])
def test_not_deleted_auto(self): empty_defs = {} old_defs = freezer.freeze_apps(["non_managed"]) class InitialMigration(SchemaMigration): "Serves as fake previous migration" def forwards(self, orm): pass def backwards(self, orm): pass models = self.full_defs complete_apps = ['non_managed'] migrations = Migrations("non_managed") initial_orm = FakeORM(InitialMigration, "non_managed") changes = AutoChanges( migrations=migrations, old_defs=self.full_defs, old_orm=initial_orm, new_defs=empty_defs, ) change_list = changes.get_changes() if list(change_list): self.fail("Auto migration deletes table for non-managed model")
def test_guess_migration(self): # Can't use vanilla import, modules beginning with numbers aren't in grammar M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration migration = Migrations('fakeapp') self.assertEqual( M1, migration.guess_migration("0001_spam").migration().Migration) self.assertEqual( M1, migration.guess_migration("0001_spa").migration().Migration) self.assertEqual( M1, migration.guess_migration("0001_sp").migration().Migration) self.assertEqual( M1, migration.guess_migration("0001_s").migration().Migration) self.assertEqual( M1, migration.guess_migration("0001_").migration().Migration) self.assertEqual( M1, migration.guess_migration("0001").migration().Migration) self.assertRaises(exceptions.UnknownMigration, migration.guess_migration, "0001-spam") self.assertRaises(exceptions.MultiplePrefixMatches, migration.guess_migration, "000") self.assertRaises(exceptions.MultiplePrefixMatches, migration.guess_migration, "") self.assertRaises(exceptions.UnknownMigration, migration.guess_migration, "0001_spams") self.assertRaises(exceptions.UnknownMigration, migration.guess_migration, "0001_jam")
def test_not_added_auto(self): empty_defs = {} class EmptyMigration(SchemaMigration): "Serves as fake previous migration" def forwards(self, orm): pass def backwards(self, orm): pass models = empty_defs complete_apps = ['non_managed'] migrations = Migrations("non_managed") empty_orm = FakeORM(EmptyMigration, "non_managed") changes = AutoChanges( migrations=migrations, old_defs=empty_defs, old_orm=empty_orm, new_defs=self.full_defs, ) change_list = changes.get_changes() if list(change_list): self.fail("Auto migration creates table for non-managed model")
def test_not_added_init(self): migrations = Migrations("non_managed") changes = InitialChanges(migrations) change_list = changes.get_changes() if list(change_list): self.fail("Initial migration creates table for non-managed model")
def test_migration_merge_forwards(self): MigrationHistory.objects.all().delete() migrations = Migrations("fakeapp") # We should start with no migrations self.assertEqual(list(MigrationHistory.objects.all()), []) # Insert one in the wrong order MigrationHistory.objects.create(app_name="fakeapp", migration="0002_eggs", applied=datetime.datetime.now()) # Did it go in? self.assertListEqual( ((u"fakeapp", u"0002_eggs"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # Apply them normally self.assertRaises(exceptions.InconsistentMigrationHistory, migrate_app, migrations, target_name=None, fake=False) self.assertRaises(exceptions.InconsistentMigrationHistory, migrate_app, migrations, target_name='zero', fake=False) try: migrate_app(migrations, target_name=None, fake=False) except exceptions.InconsistentMigrationHistory, e: self.assertEqual( [(migrations['0002_eggs'], [migrations['0001_spam']])], e.problems)
def test_suggest_name(self): migrations = Migrations('fakeapp') change = ManualChanges(migrations, [], ['fakeapp.slug'], []) self.assertEquals(change.suggest_name(), 'add_field_fakeapp_slug') change = ManualChanges(migrations, [], [], ['fakeapp.slug']) self.assertEquals(change.suggest_name(), 'add_index_fakeapp_slug')
def test_apply_migrations(self): MigrationHistory.objects.all().delete() migrations = Migrations("fakeapp") # We should start with no migrations self.assertEqual(list(MigrationHistory.objects.all()), []) # Apply them normally migrate_app(migrations, target_name=None, fake=False, load_initial_data=True) # We should finish with all migrations self.assertListEqual( ( (u"fakeapp", u"0001_spam"), (u"fakeapp", u"0002_eggs"), (u"fakeapp", u"0003_alter_spam"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # Now roll them backwards migrate_app(migrations, target_name="zero", fake=False) # Finish with none self.assertEqual(list(MigrationHistory.objects.all()), [])
def test_dependencies(self): fakeapp = Migrations("fakeapp") otherfakeapp = Migrations("otherfakeapp") # Test a simple path self.assertEqual([ fakeapp['0001_spam'], fakeapp['0002_eggs'], fakeapp['0003_alter_spam'] ], fakeapp['0003_alter_spam'].forwards_plan()) # And a complex one. self.assertEqual([ fakeapp['0001_spam'], otherfakeapp['0001_first'], otherfakeapp['0002_second'], fakeapp['0002_eggs'], fakeapp['0003_alter_spam'], otherfakeapp['0003_third'] ], otherfakeapp['0003_third'].forwards_plan())
def test_verify_invalid_code_is_not_created(self): m = Migrations("arm_access_support", force_creation=False) c = changes.InitialChanges(m) params = c.get_changes().next()[1] actor = actions.AddModel(**params) code = actor.forwards_code() self.assertNotRegexpMatches(code, r"to=orm\['arm_access.AccessObject'\]")
def test_migration(self): # Can't use vanilla import, modules beginning with numbers aren't in grammar M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration migration = Migrations('fakeapp') self.assertEqual(M1, migration['0001_spam'].migration().Migration) self.assertEqual(M2, migration['0002_eggs'].migration().Migration) self.assertRaises(exceptions.UnknownMigration, migration['0001_jam'].migration)
def test_alter_column_null(self): def null_ok(): from django.db import connection, transaction # the DBAPI introspection module fails on postgres NULLs. cursor = connection.cursor() # SQLite has weird now() if db.backend_name == "sqlite3": now_func = "DATETIME('NOW')" else: now_func = "NOW()" try: cursor.execute("INSERT INTO southtest_spam (id, weight, expires, name) VALUES (100, 10.1, %s, NULL);" % now_func) except: transaction.rollback() return False else: cursor.execute("DELETE FROM southtest_spam") transaction.commit() return True MigrationHistory.objects.all().delete() migrations = Migrations("fakeapp") # by default name is NOT NULL migrate_app(migrations, target_name="0002", fake=False) self.failIf(null_ok()) self.assertListEqual( ((u"fakeapp", u"0001_spam"), (u"fakeapp", u"0002_eggs"),), MigrationHistory.objects.values_list("app_name", "migration"), ) # after 0003, it should be NULL migrate_app(migrations, target_name="0003", fake=False) self.assert_(null_ok()) self.assertListEqual( ((u"fakeapp", u"0001_spam"), (u"fakeapp", u"0002_eggs"), (u"fakeapp", u"0003_alter_spam"),), MigrationHistory.objects.values_list("app_name", "migration"), ) # make sure it is NOT NULL again migrate_app(migrations, target_name="0002", fake=False) self.failIf(null_ok(), 'name not null after migration') self.assertListEqual( ((u"fakeapp", u"0001_spam"), (u"fakeapp", u"0002_eggs"),), MigrationHistory.objects.values_list("app_name", "migration"), ) # finish with no migrations, otherwise other tests fail... migrate_app(migrations, target_name="zero", fake=False) self.assertEqual(list(MigrationHistory.objects.all()), [])
def test_plans(self): Migrations.calculate_dependencies() circular_a = Migrations('circular_a') circular_b = Migrations('circular_b') self.assertRaises( exceptions.CircularDependency, circular_a[-1].forwards_plan, ) self.assertRaises( exceptions.CircularDependency, circular_b[-1].forwards_plan, ) self.assertRaises( exceptions.CircularDependency, circular_a[-1].backwards_plan, ) self.assertRaises( exceptions.CircularDependency, circular_b[-1].backwards_plan, )
def test_not_modified_auto(self): fake_defs = { 'non_managed.legacy': { 'Meta': { 'object_name': 'Legacy', 'db_table': "'legacy_table'", 'managed': 'False' }, 'id': ('django.db.models.fields.AutoField', [], { 'primary_key': 'True' }), 'name': ('django.db.models.fields.CharField', [], { 'max_length': '10', 'null': 'True' }), #'size': ('django.db.models.fields.IntegerField', [], {}) # The "change" is the addition of this field } } class InitialMigration(SchemaMigration): "Serves as fake previous migration" def forwards(self, orm): pass def backwards(self, orm): pass models = fake_defs complete_apps = ['non_managed'] from non_managed import models as dummy_import_to_force_loading_models # TODO: Does needing this indicate a bug in MokeyPatcher? reload_module(dummy_import_to_force_loading_models) # really force... migrations = Migrations("non_managed") initial_orm = FakeORM(InitialMigration, "non_managed") changes = AutoChanges(migrations=migrations, old_defs=fake_defs, old_orm=initial_orm, new_defs=self.full_defs) change_list = changes.get_changes() if list(change_list): self.fail("Auto migration changes table for non-managed model")
def custom_user_frozen_models(user_model): migration_name = getattr(settings, 'INITIAL_CUSTOM_USER_MIGRATION', '0001_initial.py') if user_model != 'auth.User': from south.migration.base import Migrations from south.exceptions import NoMigrations from south.creator.freezer import freeze_apps user_app, user_model = user_model.split('.') try: user_migrations = Migrations(user_app) except NoMigrations: extra_model = freeze_apps(user_app) else: initial_user_migration = user_migrations.migration(migration_name) extra_model = initial_user_migration.migration_class().models else: extra_model = {} return extra_model
def get_user_frozen_models(user_model): from south.creator.freezer import freeze_apps user_app, user_class = user_model.split('.') if user_model != 'auth.User': from south.migration.base import Migrations from south.exceptions import NoMigrations try: user_migrations = Migrations(user_app) except NoMigrations: extra_model = freeze_apps(user_app) else: from noticeapp import defaults migration_name = defaults.PYBB_INITIAL_CUSTOM_USER_MIGRATION or '0001_initial.py' initial_user_migration = user_migrations.migration(migration_name) extra_model = initial_user_migration.migration_class().models else: extra_model = freeze_apps(user_app) return extra_model
def test_full_name(self): names = ['fakeapp', 'otherfakeapp'] self.assertEqual([n + '.migrations' for n in names], [Migrations(n).full_name() for n in names])
def test_app_label(self): names = ['fakeapp', 'otherfakeapp'] self.assertEqual(names, [Migrations(n).app_label() for n in names])
def test_application(self): fakeapp = Migrations("fakeapp") application = __import__("fakeapp", {}, {}, ['']) self.assertEqual(application, fakeapp.application)
def test(self): M1 = Migrations(__import__("fakeapp", {}, {}, [''])) self.assertEqual(M1, Migrations("fakeapp")) self.assertEqual(M1, Migrations(self.create_fake_app("fakeapp")))
def test_dev_setup(appnexus_api_requests, cdn_api): """ Test preparing kanary to development #. drop current database #. run syncdb. Since pytest-django turns off south's syncdb command, we have to import it manually. Only this overwritten command, can sync apps that does not have migrations #. migrate database #. Check report adverts count - should be none, since they're being created in fill_campaigns only #. run fill_campaigns and fill_reports command #. check number of report adverts #. Try to read data from all models. If someone will forget about migrations, that's where we'll hit exceptions #. Check whether model differs from last migration """ from south.management.commands.syncdb import Command as SyncCommand """Run commands as a fresh dev.""" management.call_command('drop_kanary', interactive=False) sync = SyncCommand() sync.execute(verbosity=0, database=settings.DATABASES.keys()[0]) management.call_command('migrate', interactive=False) assert ReportAdvert.objects.count() == 0 management.call_command('fill_campaigns', interactive=False) management.call_command('fill_reports', interactive=False) assert ReportAdvert.objects.count() > 0 app_models = [] for app_mod in get_apps(): app_models.extend(get_models(app_mod)) for model in app_models: print('Querying for: ' + model.__name__) model.objects.first() for app in settings.INSTALLED_APPS: if app.split('.')[0] == 'ui': app = app.split('.')[-1] try: migrations = Migrations(app, force_creation=False, verbose_creation=False) # if there is no migrations directory except NoMigrations: continue # if there are no models except ImproperlyConfigured: continue # if migrations directory is empty if not migrations: continue last_migration = migrations[-1] # Two models saved in dictionary, one based migration, second on models.py migration_defs = dict( (k, v) for k, v in last_migration.migration_class().models.items() if k.split(".")[0] == migrations.app_label()) model_defs = dict((k, v) for k, v in freezer.freeze_apps( [migrations.app_label()]).items() if k.split(".")[0] == migrations.app_label()) change_source = AutoChanges( migrations=migrations, old_defs=migration_defs, old_orm=last_migration.orm(), new_defs=model_defs, ) assert list(change_source.get_changes()) == []
def setUp(self): super(TestMigration, self).setUp() self.fakeapp = Migrations('fakeapp') self.otherfakeapp = Migrations('otherfakeapp') Migrations.calculate_dependencies()
def setUp(self): super(TestMigrationDependencies, self).setUp() self.deps_a = Migrations('deps_a') self.deps_b = Migrations('deps_b') self.deps_c = Migrations('deps_c') Migrations.calculate_dependencies()
def get_migrations(self): from south.migration.base import Migrations return Migrations(self.app_name)
def list_migrations(app_name): """List schema migrations in the given app.""" app = ask_for_it_by_name(app_name) return [migration.name() for migration in Migrations(app)]
def test_migration_merge_forwards(self): migrations = Migrations("fakeapp") # We should start with no migrations self.assertEqual(list(MigrationHistory.objects.all()), []) # Insert one in the wrong order MigrationHistory.objects.create(app_name="fakeapp", migration="0002_eggs", applied=datetime.datetime.now()) # Did it go in? self.assertListEqual( (("fakeapp", "0002_eggs"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # Apply them normally self.assertRaises(exceptions.InconsistentMigrationHistory, migrate_app, migrations, target_name=None, fake=False) self.assertRaises(exceptions.InconsistentMigrationHistory, migrate_app, migrations, target_name='zero', fake=False) try: migrate_app(migrations, target_name=None, fake=False) except exceptions.InconsistentMigrationHistory as e: self.assertEqual( [( migrations['0002_eggs'], migrations['0001_spam'], )], e.problems, ) try: migrate_app(migrations, target_name="zero", fake=False) except exceptions.InconsistentMigrationHistory as e: self.assertEqual( [( migrations['0002_eggs'], migrations['0001_spam'], )], e.problems, ) # Nothing should have changed (no merge mode!) self.assertListEqual( (("fakeapp", "0002_eggs"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # Apply with merge migrate_app(migrations, target_name=None, merge=True, fake=False) # We should finish with all migrations self.assertListEqual( ( ("fakeapp", "0001_spam"), ("fakeapp", "0002_eggs"), ("fakeapp", "0003_alter_spam"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # Now roll them backwards migrate_app(migrations, target_name="0002", fake=False) migrate_app(migrations, target_name="0001", fake=True) migrate_app(migrations, target_name="zero", fake=False) # Finish with none self.assertEqual(list(MigrationHistory.objects.all()), [])
def test_alter_column_null(self): def null_ok(eat_exception=True): from django.db import connection, transaction # the DBAPI introspection module fails on postgres NULLs. cursor = connection.cursor() # SQLite has weird now() if db.backend_name == "sqlite3": now_func = "DATETIME('NOW')" # So does SQLServer... should we be using a backend attribute? elif db.backend_name == "pyodbc": now_func = "GETDATE()" elif db.backend_name == "oracle": now_func = "SYSDATE" else: now_func = "NOW()" try: if db.backend_name == "pyodbc": cursor.execute("SET IDENTITY_INSERT southtest_spam ON;") cursor.execute( "INSERT INTO southtest_spam (id, weight, expires, name) VALUES (100, NULL, %s, 'whatever');" % now_func) except: if eat_exception: transaction.rollback() return False else: raise else: cursor.execute("DELETE FROM southtest_spam") transaction.commit() return True MigrationHistory.objects.all().delete() migrations = Migrations("fakeapp") # by default name is NOT NULL migrate_app(migrations, target_name="0002", fake=False) self.failIf(null_ok()) self.assertListEqual( ( ("fakeapp", "0001_spam"), ("fakeapp", "0002_eggs"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # after 0003, it should be NULL migrate_app(migrations, target_name="0003", fake=False) self.assert_(null_ok(False)) self.assertListEqual( ( ("fakeapp", "0001_spam"), ("fakeapp", "0002_eggs"), ("fakeapp", "0003_alter_spam"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # make sure it is NOT NULL again migrate_app(migrations, target_name="0002", fake=False) self.failIf(null_ok(), 'weight not null after migration') self.assertListEqual( ( ("fakeapp", "0001_spam"), ("fakeapp", "0002_eggs"), ), MigrationHistory.objects.values_list("app_name", "migration"), ) # finish with no migrations, otherwise other tests fail... migrate_app(migrations, target_name="zero", fake=False) self.assertEqual(list(MigrationHistory.objects.all()), [])
def handle(self, *args, **options): migrations = Migrations('foundry') print migrations[-1].name()
def setUp(self): super(TestMigration, self).setUp() self.fakeapp = Migrations('fakeapp') self.otherfakeapp = Migrations('otherfakeapp') self.brokenapp = Migrations('brokenapp')