def test_clean(self): Migration.create_table(if_not_exists=True).run_sync() real_migration_ids = [ "2020-12-17T18:44:30", "2020-12-17T18:44:39", "2020-12-17T18:44:44", ] orphaned_migration_id = "2010-01-101T00:00:00" migration_ids = real_migration_ids + [orphaned_migration_id] Migration.insert( *[Migration(name=i, app_name="example_app") for i in migration_ids] ).run_sync() run_sync(clean(app_name="example_app", auto_agree=True)) remaining_rows = ( Migration.select(Migration.name) .where(Migration.app_name == "example_app") .output(as_list=True) .order_by(Migration.name) .run_sync() ) self.assertEqual(remaining_rows, real_migration_ids) Migration.alter().drop_table(if_exists=True).run_sync()
def get_migration_ids_to_remove(self) -> t.List[str]: """ Returns a list of migration ID strings, which are rows in the table, but don't have a corresponding migration module on disk. """ app_config = self.get_app_config(app_name=self.app_name) migration_module_dict = self.get_migration_modules( folder_path=app_config.migrations_folder_path ) # The migration IDs which are in migration modules. migration_ids = self.get_migration_ids( migration_module_dict=migration_module_dict ) query = ( Migration.select(Migration.name) .where(Migration.app_name == self.app_name) .output(as_list=True) ) if len(migration_ids) > 0: query = query.where(Migration.name.not_in(migration_ids)) migration_ids_to_remove = query.run_sync() return migration_ids_to_remove
async def run_migrations(self, app_config: AppConfig) -> MigrationResult: already_ran = await Migration.get_migrations_which_ran( app_name=app_config.app_name) migration_modules: t.Dict[ str, MigrationModule] = self.get_migration_modules( app_config.migrations_folder_path) ids = self.get_migration_ids(migration_modules) n = len(ids) print(f"👍 {n} migration{'s' if n != 1 else ''} already complete") havent_run = sorted(set(ids) - set(already_ran)) if len(havent_run) == 0: # Make sure this still appears successful, as we don't want this # to appear as an error in automated scripts. message = "🏁 No migrations need to be run" print(message) return MigrationResult(success=True, message=message) else: n = len(havent_run) print(f"⏩ {n} migration{'s' if n != 1 else ''} not yet run") if self.migration_id == "all": subset = havent_run elif self.migration_id == "1": subset = havent_run[:1] else: try: index = havent_run.index(self.migration_id) except ValueError: message = f"{self.migration_id} is unrecognised" print(message, file=sys.stderr) return MigrationResult(success=False, message=message) else: subset = havent_run[:index + 1] if subset: n = len(subset) print(f"🚀 Running {n} migration{'s' if n != 1 else ''}:") for _id in subset: if self.fake: print(f"- {_id}: faked! ⏭️") else: migration_module = migration_modules[_id] response = await migration_module.forwards() if isinstance(response, MigrationManager): await response.run() print("ok! ✔️") await Migration.insert().add( Migration(name=_id, app_name=app_config.app_name)).run() return MigrationResult(success=True, message="migration succeeded")
async def run_migrations(self, app_config: AppConfig) -> MigrationResult: already_ran = await Migration.get_migrations_which_ran( app_name=self.app_name) migration_modules: t.Dict[ str, MigrationModule] = self.get_migration_modules( app_config.migrations_folder_path) ids = self.get_migration_ids(migration_modules) print(f"All migration ids = {ids}") havent_run = sorted(set(ids) - set(already_ran)) print(f"Haven't run = {havent_run}") if len(havent_run) == 0: # Make sure this still appears successful, as we don't want this # to appear as an error in automated scripts. message = "No migrations left to run!" print(message) return MigrationResult(success=True, message=message) if self.migration_id == "all": subset = havent_run elif self.migration_id == "1": subset = havent_run[:1] else: try: index = havent_run.index(self.migration_id) except ValueError: message = f"{self.migration_id} is unrecognised" print(message, file=sys.stderr) return MigrationResult(success=False, message=message) else: subset = havent_run[:index + 1] for _id in subset: if self.fake: print(f"Faked {_id}") else: migration_module = migration_modules[_id] response = await migration_module.forwards() if isinstance(response, MigrationManager): await response.run() print(f"-> Ran {_id}") await Migration.insert().add( Migration(name=_id, app_name=self.app_name)).run() return MigrationResult(success=True, message="Ran successfully")
def test_forwards_fake(self): """ Test running the migrations if they've already run. """ run_sync( forwards(app_name="example_app", migration_id="all", fake=True)) for table_class in TABLE_CLASSES: self.assertTrue(not table_class.table_exists().run_sync()) ran_migration_names = (Migration.select( Migration.name).output(as_list=True).run_sync()) self.assertEqual( ran_migration_names, # TODO - rather than hardcoding, might fetch these dynamically. [ "2020-12-17T18:44:30", "2020-12-17T18:44:39", "2020-12-17T18:44:44", ], )
def test_forwards_fake(self): """ Test running the migrations if they've already run. """ run_sync(forwards(app_name="music", migration_id="all", fake=True)) for table_class in TABLE_CLASSES: self.assertTrue(not table_class.table_exists().run_sync()) ran_migration_names = (Migration.select( Migration.name).output(as_list=True).run_sync()) self.assertEqual( ran_migration_names, # TODO - rather than hardcoding, might fetch these dynamically. [ "2020-12-17T18:44:30", "2020-12-17T18:44:39", "2020-12-17T18:44:44", "2021-07-25T22:38:48:009306", "2021-09-06T13:58:23:024723", "2021-11-13T14:01:46:114725", ], )
def test_migration_table(self): Migration.create_table().run_sync() Migration.select().run_sync() Migration.alter().drop_table().run_sync()
def tearDown(self): create_table_class("MyTable").alter().drop_table( if_exists=True).run_sync() Migration.alter().drop_table(if_exists=True).run_sync()
def test_migration_table(self): Migration.create_table(if_not_exists=True).run_sync() Migration.select().run_sync() Migration.alter().drop_table().run_sync()