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)
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)
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)
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
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)
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
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)
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)