From 9a44d9bd5728a581ab2561793f557071b2964a7b Mon Sep 17 00:00:00 2001 From: "christian.simms" Date: Thu, 24 Apr 2008 18:52:36 +0000 Subject: [PATCH] almost done issue 12: generate downgrade method for schema migration --- migrate/versioning/genmodel.py | 18 ++++++++++-------- migrate/versioning/script/py.py | 14 +++++--------- test/versioning/test_schemadiff.py | 9 +++++---- test/versioning/test_shell.py | 2 +- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/migrate/versioning/genmodel.py b/migrate/versioning/genmodel.py index 209f77d..1437c0b 100644 --- a/migrate/versioning/genmodel.py +++ b/migrate/versioning/genmodel.py @@ -80,25 +80,27 @@ class ModelGenerator(object): out.append("") return '\n'.join(out) - def toUpgradePython(self, indent=' '): + def toUpgradeDowngradePython(self, indent=' '): ''' Assume model is most current and database is out-of-date. ''' decls = ['meta = MetaData(migrate_engine)'] for table in self.diff.tablesMissingInModel + self.diff.tablesMissingInDatabase: decls.extend(self.getTableDefn(table)) - cmds = [] + upgradeCommands, downgradeCommands = [], [] for table in self.diff.tablesMissingInModel: tableName = table.name - cmds.append("%(table)s.drop()" % {'table': tableName}) + upgradeCommands.append("%(table)s.drop()" % {'table': tableName}) + downgradeCommands.append("%(table)s.create()" % {'table': tableName}) for table in self.diff.tablesMissingInDatabase: tableName = table.name - cmds.append("%(table)s.create()" % {'table': tableName}) + upgradeCommands.append("%(table)s.create()" % {'table': tableName}) + downgradeCommands.append("%(table)s.drop()" % {'table': tableName}) - return '\n'.join(decls), '\n'.join(['%s%s' % (indent, line) for line in cmds]) - - def toDowngradePython(self, indent=' '): - return ' pass #TODO DOWNGRADE' + return ('\n'.join(decls), + '\n'.join(['%s%s' % (indent, line) for line in upgradeCommands]), + '\n'.join(['%s%s' % (indent, line) for line in downgradeCommands]) + ) def applyModel(self): ''' Apply model to current database. ''' diff --git a/migrate/versioning/script/py.py b/migrate/versioning/script/py.py index 1f2685a..45dd9b3 100644 --- a/migrate/versioning/script/py.py +++ b/migrate/versioning/script/py.py @@ -22,7 +22,6 @@ class PythonScript(base.BaseScript): @classmethod def make_update_script_for_model(cls,engine,oldmodel,model,repository,**opts): """Create a migration script""" - #cls.require_notfound(path) # TODO: yank? # Compute differences. if isinstance(repository, basestring): @@ -31,20 +30,17 @@ class PythonScript(base.BaseScript): oldmodel = loadModel(oldmodel) model = loadModel(model) diff = schemadiff.getDiffOfModelAgainstModel(oldmodel, model, engine, excludeTables=[repository.version_table]) - upgradeDecls, upgradeCommands = genmodel.ModelGenerator(diff).toUpgradePython() - #downgradeCommands = genmodel.ModelGenerator(diff).toDowngradePython() + decls, upgradeCommands, downgradeCommands = genmodel.ModelGenerator(diff).toUpgradeDowngradePython() - # TODO: Use the default script template (defined in the template - # module) for now, but we might want to allow people to specify a - # different one later. + # Store differences into file. template_file = None src = template.get_script(template_file) contents = open(src).read() search = 'def upgrade():' - contents = contents.replace(search, upgradeDecls + '\n\n' + search, 1) + contents = contents.replace(search, decls + '\n\n' + search, 1) if upgradeCommands: contents = contents.replace(' pass', upgradeCommands, 1) - #if downgradeCommands: contents = contents.replace(' pass', downgradeCommands, 1) # TODO - return contents # TODO: reinstate? open(path, 'w').write(contents) + if downgradeCommands: contents = contents.replace(' pass', downgradeCommands, 1) + return contents @classmethod def verify_module(cls,path): diff --git a/test/versioning/test_schemadiff.py b/test/versioning/test_schemadiff.py index d9df0dd..0a7b322 100644 --- a/test/versioning/test_schemadiff.py +++ b/test/versioning/test_schemadiff.py @@ -50,10 +50,10 @@ class TestSchemaDiff(fixture.DB): # Model is defined but database is empty. assertDiff(True, [self.table_name], [], []) - # Check Python upgrade of database from updated model. + # Check Python upgrade and downgrade of database from updated model. diff = schemadiff.getDiffOfModelAgainstDatabase(self.meta, self.engine, excludeTables=['migrate_version']) - decl, commands = genmodel.ModelGenerator(diff).toUpgradePython() - self.assertEqualsIgnoreWhitespace(decl, ''' + decls, upgradeCommands, downgradeCommands = genmodel.ModelGenerator(diff).toUpgradeDowngradePython() + self.assertEqualsIgnoreWhitespace(decls, ''' meta = MetaData(migrate_engine) tmp_schemadiff = Table('tmp_schemadiff',meta, Column('id',Integer(),primary_key=True,nullable=False), @@ -61,7 +61,8 @@ class TestSchemaDiff(fixture.DB): Column('data',UnicodeText(length=None)), ) ''') - self.assertEqualsIgnoreWhitespace(commands, '''tmp_schemadiff.create()''') + self.assertEqualsIgnoreWhitespace(upgradeCommands, '''tmp_schemadiff.create()''') + self.assertEqualsIgnoreWhitespace(downgradeCommands, '''tmp_schemadiff.drop()''') # Create table in database, now model should match database. self._applyLatestModel() diff --git a/test/versioning/test_shell.py b/test/versioning/test_shell.py index 441f5bb..7f1366f 100644 --- a/test/versioning/test_shell.py +++ b/test/versioning/test_shell.py @@ -542,7 +542,7 @@ class TestShellDatabase(Shell,fixture.DB): def downgrade(): # Operations to reverse the above upgrade go here. - pass + tmp_account_rundiffs.drop() """) # Commit the change.