Beispiel #1
0
    def __init__(self, path):
        # __init__ from pathed.Pathed
        self.path = path
        if self.__class__.parent is not None:
            self._init_parent(path)

        # Create temporary list of files, allowing skipped version numbers.
        files = listdir(path)
        tempVersions = dict()
        if '1' in files:
            raise Exception('It looks like you have a repository in the old '
                            'format (with directories for each version). '
                            'Please convert repository before proceeding.')
        for filename in files:
            match = self.FILENAME_WITH_VERSION.match(filename)
            if match:
                num = int(match.group(1))
                tempVersions.setdefault(num, []).append(filename)
            else:
                pass  # Must be a helper file or something, let's ignore it.

        # Create the versions member where the keys
        # are VerNum's and the values are Version's.
        self.versions = dict()
        for num, files in tempVersions.items():
            self.versions[api.VerNum(num)] = Version(num, path, files)
Beispiel #2
0
 def __init__(self, start, *changes, **k):
     """
     Give a start version; step must be explicitly stated.
     """
     self.step = k.pop('step', 1)
     self.start = api.VerNum(start)
     self.end = self.start
     for change in changes:
         self.add(change)
Beispiel #3
0
    def test_walk_versions_all_false(self, migrate_up, migrate_down):
        self.REPOSITORY.latest = versioning_api.VerNum(20)
        self.migration_api.db_version.return_value = self.INIT_VERSION

        self.walk_versions(snake_walk=False, downgrade=False)

        versions = range(int(self.INIT_VERSION) + 1,
                         int(self.REPOSITORY.latest) + 1)

        upgraded = [mock.call(v, with_data=True) for v in versions]
        self.assertEqual(upgraded, self.migrate_up.call_args_list)
Beispiel #4
0
    def changeset(self, database, start, end=None):
        """Create a changeset to migrate this database from version
        start to end/latest.

        :param database: name of database to generate changeset
        :param start: version to start at
        :param end: version to end at (latest if None given)
        :type database: string
        :type start: int
        :type end: int
        :returns: :class:`Changeset instance
                  <migration.versioning.repository.Changeset>`
        """
        start = api.VerNum(start)

        if end is None:
            end = self.latest
        else:
            end = api.VerNum(end)

        if start <= end:
            step = 1
            range_mod = 1
            op = 'upgrade'
        else:
            step = -1
            range_mod = 0
            op = 'downgrade'

        versions = range(start + range_mod, end + range_mod, step)
        changes = []
        for version in versions:
            try:
                changes.append(self.version(version).script(database, op))
            except KeyError:
                # trying to upgrade to version later than the latest?
                pass
        ret = Changeset(start, step=step, *changes)
        return ret
Beispiel #5
0
    def test_walk_versions_all_default(self, migrate_up, migrate_down):
        self.REPOSITORY.latest = versioning_api.VerNum(20)
        self.migration_api.db_version.return_value = self.INIT_VERSION

        self.walk_versions()

        self.migration_api.version_control.assert_called_with(
            self.engine, self.REPOSITORY, self.INIT_VERSION)
        self.migration_api.db_version.assert_called_with(
            self.engine, self.REPOSITORY)

        versions = range(
            int(self.INIT_VERSION) + 1,
            int(self.REPOSITORY.latest) + 1)
        upgraded = [mock.call(v, with_data=True) for v in versions]
        self.assertEqual(upgraded, self.migrate_up.call_args_list)

        downgraded = [mock.call(v - 1) for v in reversed(versions)]
        self.assertEqual(downgraded, self.migrate_down.call_args_list)
Beispiel #6
0
 def _migrate_version(self, schema, version, upgrade):
     if version is None:
         return version
     if version < 0:
         raise KnownError("Already at version 0.")
     # Version is specified: ensure we're upgrading in the right direction
     # (current version < target version for upgrading; reverse for down)
     version = api.VerNum(version)
     cur = schema.version
     if upgrade:
         direction = cur <= version
     else:
         direction = cur >= version
     if not direction:
         msg = ("Cannot %s a database of version %%s to version %%s. "
                "Try '%s' instead.")
         if upgrade:
             msg = msg % ('upgrade', 'downgrade')
         else:
             msg = msg % ('downgrade', 'upgrade')
         raise KnownError(msg % (cur, version))
     return version
Beispiel #7
0
    def test_walk_versions_all_true(self, migrate_up, migrate_down):
        self.REPOSITORY.latest = versioning_api.VerNum(20)
        self.migration_api.db_version.return_value = self.INIT_VERSION

        self.walk_versions(snake_walk=True, downgrade=True)

        versions = range(int(self.INIT_VERSION) + 1,
                         int(self.REPOSITORY.latest) + 1)
        upgraded = []
        for v in versions:
            upgraded.append(mock.call(v, with_data=True))
            upgraded.append(mock.call(v))
        upgraded.extend([mock.call(v) for v in reversed(versions)])
        self.assertEqual(upgraded, self.migrate_up.call_args_list)

        downgraded_1 = [mock.call(v - 1, with_data=True) for v in versions]
        downgraded_2 = []
        for v in reversed(versions):
            downgraded_2.append(mock.call(v - 1))
            downgraded_2.append(mock.call(v - 1))
        downgraded = downgraded_1 + downgraded_2
        self.assertEqual(downgraded, self.migrate_down.call_args_list)
Beispiel #8
0
class TestWalkVersions(test.BaseTestCase, migrate.WalkVersionsMixin):
    migration_api = mock.MagicMock()
    REPOSITORY = mock.MagicMock()
    engine = mock.MagicMock()
    INIT_VERSION = versioning_api.VerNum(4)

    @property
    def migrate_engine(self):
        return self.engine

    def test_migrate_up(self):
        self.migration_api.db_version.return_value = 141

        self.migrate_up(141)

        self.migration_api.upgrade.assert_called_with(self.engine,
                                                      self.REPOSITORY, 141)
        self.migration_api.db_version.assert_called_with(
            self.engine, self.REPOSITORY)

    @staticmethod
    def _fake_upgrade_boom(*args, **kwargs):
        raise exc.DBMigrationError("boom")

    def test_migrate_up_fail(self):
        version = 141
        self.migration_api.db_version.return_value = version
        expected_output = (u"Failed to migrate to version %(version)s on "
                           "engine %(engine)s\n" % {
                               'version': version,
                               'engine': self.engine
                           })

        with mock.patch.object(self.migration_api,
                               'upgrade',
                               side_effect=self._fake_upgrade_boom):
            log = self.useFixture(fixtures.FakeLogger())
            self.assertRaises(exc.DBMigrationError, self.migrate_up, version)
            self.assertEqual(expected_output, log.output)

    def test_migrate_up_with_data(self):
        test_value = {"a": 1, "b": 2}
        self.migration_api.db_version.return_value = 141
        self._pre_upgrade_141 = mock.MagicMock()
        self._pre_upgrade_141.return_value = test_value
        self._check_141 = mock.MagicMock()

        self.migrate_up(141, True)

        self._pre_upgrade_141.assert_called_with(self.engine)
        self._check_141.assert_called_with(self.engine, test_value)

    def test_migrate_down(self):
        self.migration_api.db_version.return_value = 42

        self.assertTrue(self.migrate_down(42))
        self.migration_api.db_version.assert_called_with(
            self.engine, self.REPOSITORY)

    def test_migrate_down_not_implemented(self):
        with mock.patch.object(self.migration_api,
                               'downgrade',
                               side_effect=NotImplementedError):
            self.assertFalse(self.migrate_down(self.engine, 42))

    def test_migrate_down_with_data(self):
        self._post_downgrade_043 = mock.MagicMock()
        self.migration_api.db_version.return_value = 42

        self.migrate_down(42, True)

        self._post_downgrade_043.assert_called_with(self.engine)

    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_up')
    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_down')
    def test_walk_versions_all_default(self, migrate_up, migrate_down):
        self.REPOSITORY.latest = versioning_api.VerNum(20)
        self.migration_api.db_version.return_value = self.INIT_VERSION

        self.walk_versions()

        self.migration_api.version_control.assert_called_with(
            self.engine, self.REPOSITORY, self.INIT_VERSION)
        self.migration_api.db_version.assert_called_with(
            self.engine, self.REPOSITORY)

        versions = range(
            int(self.INIT_VERSION) + 1,
            int(self.REPOSITORY.latest) + 1)
        upgraded = [mock.call(v, with_data=True) for v in versions]
        self.assertEqual(upgraded, self.migrate_up.call_args_list)

        downgraded = [mock.call(v - 1) for v in reversed(versions)]
        self.assertEqual(downgraded, self.migrate_down.call_args_list)

    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_up')
    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_down')
    def test_walk_versions_all_true(self, migrate_up, migrate_down):
        self.REPOSITORY.latest = versioning_api.VerNum(20)
        self.migration_api.db_version.return_value = self.INIT_VERSION

        self.walk_versions(snake_walk=True, downgrade=True)

        versions = range(
            int(self.INIT_VERSION) + 1,
            int(self.REPOSITORY.latest) + 1)
        upgraded = []
        for v in versions:
            upgraded.append(mock.call(v, with_data=True))
            upgraded.append(mock.call(v))
        upgraded.extend([mock.call(v) for v in reversed(versions)])
        self.assertEqual(upgraded, self.migrate_up.call_args_list)

        downgraded_1 = [mock.call(v - 1, with_data=True) for v in versions]
        downgraded_2 = []
        for v in reversed(versions):
            downgraded_2.append(mock.call(v - 1))
            downgraded_2.append(mock.call(v - 1))
        downgraded = downgraded_1 + downgraded_2
        self.assertEqual(downgraded, self.migrate_down.call_args_list)

    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_up')
    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_down')
    def test_walk_versions_true_false(self, migrate_up, migrate_down):
        self.REPOSITORY.latest = versioning_api.VerNum(20)
        self.migration_api.db_version.return_value = self.INIT_VERSION

        self.walk_versions(snake_walk=True, downgrade=False)

        versions = range(
            int(self.INIT_VERSION) + 1,
            int(self.REPOSITORY.latest) + 1)

        upgraded = []
        for v in versions:
            upgraded.append(mock.call(v, with_data=True))
            upgraded.append(mock.call(v))
        self.assertEqual(upgraded, self.migrate_up.call_args_list)

        downgraded = [mock.call(v - 1, with_data=True) for v in versions]
        self.assertEqual(downgraded, self.migrate_down.call_args_list)

    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_up')
    @mock.patch.object(migrate.WalkVersionsMixin, 'migrate_down')
    def test_walk_versions_all_false(self, migrate_up, migrate_down):
        self.REPOSITORY.latest = versioning_api.VerNum(20)
        self.migration_api.db_version.return_value = self.INIT_VERSION

        self.walk_versions(snake_walk=False, downgrade=False)

        versions = range(
            int(self.INIT_VERSION) + 1,
            int(self.REPOSITORY.latest) + 1)

        upgraded = [mock.call(v, with_data=True) for v in versions]
        self.assertEqual(upgraded, self.migrate_up.call_args_list)