async def check_current_migrations_status(self, target): self.check_migration_dir() latest_db_migration = self._migration_integer_number(await self.latest_db_migration()) forward = False if target is None: target_fs_migration = self._migration_integer_number(self.latest_fs_migration()) else: target_fs_migration = [ fn for fn in next(os.walk(self.migrations_dir))[2] if fn.startswith(target)] if not target_fs_migration: raise MigrationError('the migration {} does not exist for app {}'.format(target, self.name)) if latest_db_migration is not None and target_fs_migration is not None: if latest_db_migration > target_fs_migration: raise MigrationError( 'There is an inconsistency, the database has a migration named "{}" ' 'more advanced than the filesystem "{}"'.format( latest_db_migration, target_fs_migration, ) ) if latest_db_migration < target_fs_migration: forward = True return forward
async def makemigrations(self, apps): """Creates the file that can be used to migrate the table from a state to the next.""" logger.info('migrations for {}'.format(apps)) for app in [self.orm.apps[m] for m in apps]: logger.info('##### checking models for "{}" #####'.format(app.name)) try: _migration_status = await app._construct_migrations_status() _latest_fs_declared = _migration_status['_latest_fs_declared'] logger.info(_latest_fs_declared) initial = self.args.initial if not initial and not _latest_fs_declared: raise MigrationError( 'No migration defined in filesystem for app "{}" ' 'and makemigration not marked as initial.'.format(app.name) ) if initial and _latest_fs_declared: raise MigrationError( 'Makemigrations marked as initial where there is already an initial ' 'migration declared.' ) file_name = app.next_fs_migration_name(stage='initial' if initial else 'auto') MigrationConstructor( app.get_absolute_migration('{}.py'.format(file_name)), app.get_migration_depends(), app.get_migration_actions(), initial=True ) except MigrationError as e: logger.error('\nMigration Error: {}\n'.format(e))
async def _construct_migrations_status(self): fs_declared = self.fs_migration_list() db_migrated = await self._app_db_applied_migrations() migrations_status = {} for migration in fs_declared: migrations_status.update({ migration: { "migrated": True if migration in db_migrated else False, "initial": True if "__initial_" in migration else False, } }) try: _latest_db_migrated = (migrations_status[db_migrated[-1]] if db_migrated else {}) except KeyError: raise MigrationError( 'Something went wrong, migration "{}" does not exist in the filesystem.' .format(db_migrated[-1])) migrations_status.update({ "_latest_db_migrated": _latest_db_migrated, "_latest_fs_declared": migrations_status[fs_declared[-1]] if fs_declared else {}, }) return migrations_status
async def check_makemigrations_status(self): """ Checks that the migration is correcly synced and everything is fine returns the latest migration applied file_name """ _migration_status = await self._construct_migrations_status() _latest_db_migrated = _migration_status['_latest_db_migrated'] _latest_db_migrated_number = self._migration_integer_number(_latest_db_migrated) _latest_fs_declared = _migration_status['_latest_fs_declared'] _latest_fs_declared_number = self._migration_integer_number(_latest_fs_declared) self._migration_integer_number(_latest_fs_declared) # the database doesn't have any migration if not _latest_db_migrated: if _latest_fs_declared: raise MigrationError( 'The model is not in the latest filesystem status, so the migration created will ' 'not be consistent.\nPlease "migrate" the database before "makemigrations" again.' ) else: if not _latest_fs_declared: raise MigrationError( 'Severe inconsistence detected, the database has at least one migration applied and no ' 'migration described in the filesystem.') if _latest_db_migrated_number > _latest_fs_declared_number: raise MigrationError( 'There is an inconsistency, the database has a migration named "{}" ' 'more advanced than the filesystem "{}"'.format( _latest_db_migrated, _latest_fs_declared, ) ) elif _latest_db_migrated_number < _latest_fs_declared_number: raise MigrationError( 'The model is not in the latest filesystem status, so the migration created will ' 'not be consistent.\nPlease "migrate" the database before "makemigrations" again.' ) elif _latest_fs_declared != _latest_db_migrated: raise MigrationError( 'The migration in the filesystem "{}" is not the same migration ' 'applied in the database "{}" .'.format( _latest_fs_declared, _latest_db_migrated, ) )
async def check_makemigrations_status(self): """ Checks that the migration is correcly synced and everything is fine returns the latest migration applied file_name """ latest_fs_migration = self.latest_fs_migration() latest_db_migration = await self.latest_db_migration() latest_fs_migration_number = self.migration_integer_number( latest_fs_migration) latest_db_migration_number = self.migration_integer_number( latest_db_migration) # the database doesn't have any migration if not latest_db_migration: if latest_fs_migration: raise MigrationError( 'The model is not in the latest filesystem status, so the migration created will ' 'not be consistent.\nPlease "migrate" the database before "makemigrations" again.' ) else: if not latest_fs_migration: raise MigrationError( 'Severe inconsistence detected, the database has at least one migration applied and no ' 'migration described in the filesystem.') if latest_db_migration_number > latest_fs_migration_number: raise MigrationError( 'There is an inconsistency, the database has a migration named "{}" ' 'more advanced than the filesystem "{}"'.format( latest_db_migration, latest_fs_migration, )) elif latest_db_migration_number < latest_fs_migration_number: raise MigrationError( 'The model is not in the latest filesystem status, so the migration created will ' 'not be consistent.\nPlease "migrate" the database before "makemigrations" again.' ) elif latest_fs_migration != latest_db_migration: raise MigrationError( 'The migration in the filesystem "{}" is not the same migration ' 'applied in the database "{}" .'.format( latest_fs_migration, latest_db_migration, )) return latest_fs_migration
def next_fs_migration_name(self, stage="auto"): if stage not in ("auto", "data", "initial"): raise MigrationError("that migration stage is not supported") target_fs_migration = self._migration_integer_number( self.latest_fs_migration()) random_hash = hashlib.sha1() random_hash.update("{}{}".format(target_fs_migration, str(datetime.now())).encode("utf-8")) return "{}__{}_{}".format("000{}".format(target_fs_migration + 1)[-4:], stage, random_hash.hexdigest())[:26]
def next_fs_migration_name(self, stage='auto'): if stage not in ('auto', 'data', 'initial'): raise MigrationError('that migration stage is not supported') target_fs_migration = self._migration_integer_number(self.latest_fs_migration()) random_hash = hashlib.sha1() random_hash.update('{}{}'.format(target_fs_migration, str(datetime.now())).encode('utf-8')) return '{}__{}_{}'.format( '000{}'.format(target_fs_migration + 1)[-4:], stage, random_hash.hexdigest(), )[:26]