Beispiel #1
0
    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
Beispiel #2
0
    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))
Beispiel #3
0
    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
Beispiel #4
0
    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,
                    )
                )
Beispiel #5
0
    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
Beispiel #6
0
 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]
Beispiel #7
0
 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]