make repository format flatter and get rid of commit command

This commit is contained in:
christian.simms 2008-05-30 18:21:14 +00:00
parent 02da42cba6
commit 95b666783e
11 changed files with 213 additions and 304 deletions

View File

@ -11,8 +11,8 @@ __all__=[
'help',
'create',
'script',
'script_sql',
'make_update_script_for_model',
'commit',
'version',
'source',
'version_control',
@ -61,57 +61,42 @@ def create(repository,name,**opts):
except exceptions.PathFoundError,e:
raise exceptions.KnownError("The path %s already exists"%e.args[0])
def script(path,**opts):
"""%prog script PATH
def script(description,repository=None,**opts):
"""%prog script [--repository=REPOSITORY_PATH] DESCRIPTION
Create an empty change script at the specified path.
Create an empty change script using the next unused version number appended with the given description.
For instance, manage.py script "Add initial tables" creates: repository/versions/001_Add_initial_tables.py
"""
try:
cls_script_python.create(path,**opts)
if repository is None:
raise exceptions.UsageError("A repository must be specified")
repos = cls_repository(repository)
repos.create_script(description,**opts)
except exceptions.PathFoundError,e:
raise exceptions.KnownError("The path %s already exists"%e.args[0])
def commit(script,repository,database=None,operation=None,version=None,**opts):
"""%prog commit SCRIPT_PATH.py REPOSITORY_PATH [VERSION]
def script_sql(database,repository=None,**opts):
"""%prog script_sql [--repository=REPOSITORY_PATH] DATABASE
%prog commit SCRIPT_PATH.sql REPOSITORY_PATH DATABASE OPERATION [VERSION]
Commit a script to this repository. The committed script is added to the
repository, and the file disappears.
Once a script has been committed, you can use it to upgrade a database with
the 'upgrade' command.
If a version is given, that version will be replaced instead of creating a
new version.
Normally, when writing change scripts in Python, you'll use the first form
of this command (DATABASE and OPERATION aren't specified). If you write
change scripts as .sql files, you'll need to specify DATABASE ('postgres',
'mysql', 'oracle', 'sqlite'...) and OPERATION ('upgrade' or 'downgrade').
You may commit multiple .sql files under the same version to complete
functionality for a particular version::
%prog commit upgrade.postgres.sql /repository/path postgres upgrade 1
%prog commit downgrade.postgres.sql /repository/path postgres downgrade 1
%prog commit upgrade.sqlite.sql /repository/path sqlite upgrade 1
%prog commit downgrade.sqlite.sql /repository/path sqlite downgrade 1
[etc...]
Create empty change SQL scripts for given DATABASE, where DATABASE is either specific ('postgres', 'mysql',
'oracle', 'sqlite', etc.) or generic ('default').
For instance, manage.py script_sql postgres creates:
repository/versions/001_upgrade_postgres.py and repository/versions/001_downgrade_postgres.py
"""
if (database is not None) and (operation is None) and (version is None):
# Version was supplied as a positional
version = database
database = None
repos = cls_repository(repository)
repos.commit(script,version,database=database,operation=operation)
try:
if repository is None:
raise exceptions.UsageError("A repository must be specified")
repos = cls_repository(repository)
repos.create_script_sql(database,**opts)
except exceptions.PathFoundError,e:
raise exceptions.KnownError("The path %s already exists"%e.args[0])
def test(script,repository,url=None,**opts):
"""%prog test SCRIPT_PATH REPOSITORY_PATH URL [VERSION]
def test(repository,url=None,**opts):
"""%prog test REPOSITORY_PATH URL [VERSION]
"""
engine=create_engine(url)
schema = cls_schema(engine,repository)
script = cls_script_python(script)
repos=cls_repository(repository)
script = repos.version(None).script()
# Upgrade
print "Upgrading...",
try:

View File

@ -126,9 +126,6 @@ class ModelGenerator(object):
for modelTable in self.diff.tablesWithDiff:
modelTable = modelTable.tometadata(meta)
dbTable = self.diff.reflected_model.tables[modelTable.name]
#print 'TODO DEBUG.cols1', [x.name for x in dbTable.columns]
#dbTable = dbTable.tometadata(meta)
#print 'TODO DEBUG.cols2', [x.name for x in dbTable.columns]
tableName = modelTable.name
missingInDatabase, missingInModel, diffDecl = self.diff.colDiffs[tableName]
if dbCanHandleThisChange(missingInDatabase, missingInModel, diffDecl):

View File

@ -0,0 +1,35 @@
''' Script to migrate repository. This shouldn't use any other migrate modules, so that it can work in any version. '''
import os, sys
def usage():
print '''Usage: %(prog)s repository-to-migrate
Upgrade your repository to the new flat format.
NOTE: You should probably make a backup before running this.
''' % {'prog': sys.argv[0]}
raise SystemExit(1)
def migrate_repository(repos):
print 'Migrating repository at: %s to new format' % repos
versions = '%s/versions' % repos
dirs = os.listdir(versions)
numdirs = [ int(dir) for dir in dirs if dir.isdigit() ] # Only use int's in list.
numdirs.sort() # Sort list.
for dir in numdirs:
origdir = '%s/%s' % (versions, dir)
print ' Working on directory: %s' % origdir
files = os.listdir(origdir)
pass # finish TODO xxx
if __name__ == '__main__':
if len(sys.argv) != 2:
usage()
migrate_repository(sys.argv[1])

View File

@ -113,9 +113,11 @@ class Repository(pathed.Pathed):
log.error("There was an error creating your repository")
return cls(path)
def commit(self,*p,**k):
reqd = self.config.get('db_settings','required_dbs')
return self.versions.commit(required=reqd,*p,**k)
def create_script(self,description,**k):
self.versions.createNewVersion(description,**k)
def create_script_sql(self,database,**k):
self.versions.createNewSQLVersion(database,**k)
latest=property(lambda self: self.versions.latest)
version_table=property(lambda self: self.config.get('db_settings','version_table'))

View File

@ -8,7 +8,6 @@ import inspect
alias = dict(
s=api.script,
ci=api.commit,
vc=api.version_control,
dbv=api.db_version,
v=api.version,

View File

@ -1,5 +1,5 @@
from migrate.versioning import exceptions,pathed,script
import os,shutil
import os,re,shutil
@ -31,21 +31,38 @@ class VerNum(object):
return int(self)-int(value)
def strToFilename(s):
s = s.replace(' ', '_').replace('"', '_').replace("'", '_')
while '__' in s:
s = s.replace('__', '_')
return s
class Collection(pathed.Pathed):
"""A collection of versioning scripts in a repository"""
FILENAME_WITH_VERSION = re.compile(r'^(\d+).*')
def __init__(self,path):
super(Collection,self).__init__(path)
self.versions=dict()
# Create temporary list of files, allowing skipped version numbers.
files = os.listdir(path)
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.')
tempVersions = dict()
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[VerNum(num)] = Version(num, path, files)
self.latest = max([VerNum(0)] + self.versions.keys()) # calculate latest version
ver=self.latest=VerNum(1)
vers=os.listdir(path)
# This runs up to the latest *complete* version; stops when one's missing
while str(ver) in vers:
verpath=self.version_path(ver)
self.versions[ver]=Version(verpath)
ver+=1
self.latest=ver-1
def version_path(self,ver):
return os.path.join(self.path,str(ver))
@ -54,47 +71,52 @@ class Collection(pathed.Pathed):
vernum = self.latest
return self.versions[VerNum(vernum)]
def commit(self,path,ver=None,*p,**k):
"""Commit a script to this collection of scripts
"""
maxver = self.latest+1
if ver is None:
ver = maxver
# Ver must be valid: can't upgrade past the next version
def getNewVersion(self):
ver = self.latest+1
# No change scripts exist for 0 (even though it's a valid version)
if ver > maxver or ver == 0:
if ver <= 0:
raise exceptions.InvalidVersionError()
verpath = self.version_path(ver)
tmpname = None
try:
# If replacing an old version, copy it in case it gets trashed
if os.path.exists(verpath):
tmpname = os.path.join(os.path.split(verpath)[0],"%s_tmp"%ver)
shutil.copytree(verpath,tmpname)
version = Version(verpath)
else:
# Create version folder
version = Version.create(verpath)
self.versions[ver] = version
# Commit the individual script
script = version.commit(path,*p,**k)
except:
# Rollback everything we did in the try before dying, and reraise
# Remove the created version folder
shutil.rmtree(verpath)
# Rollback if a version already existed above
if tmpname is not None:
shutil.move(tmpname,verpath)
raise
# Success: mark latest; delete old version
if tmpname is not None:
shutil.rmtree(tmpname)
self.latest = ver
return ver
def createNewVersion(self, description, **k):
ver = self.getNewVersion()
extra = strToFilename(description)
if extra:
if extra == '_':
extra = ''
elif not extra.startswith('_'):
extra = '_%s' % extra
filename = '%03d%s.py' % (ver, extra)
filepath = self.version_path(filename)
if os.path.exists(filepath):
raise Exception('Script already exists: %s' % filepath)
else:
script.PythonScript.create(filepath)
self.versions[ver] = Version(ver, self.path, [filename])
def createNewSQLVersion(self, database, **k):
# Determine version number to use.
if (not self.versions) or self.versions[self.latest].python:
# First version or current version already contains python script, so create a new version.
ver = self.getNewVersion()
self.versions[ver] = Version(ver, self.path, [])
else:
ver = self.latest
# Create new files.
for op in ('upgrade', 'downgrade'):
filename = '%03d_%s_%s.sql' % (ver, database, op)
filepath = self.version_path(filename)
if os.path.exists(filepath):
raise Exception('Script already exists: %s' % filepath)
else:
open(filepath, "w").close()
self.versions[ver]._add_script(filepath)
@classmethod
def clear(cls):
super(Collection,cls).clear()
Version.clear()
class extensions:
@ -103,28 +125,25 @@ class extensions:
sql='sql'
class Version(pathed.Pathed):
class Version(object): # formerly inherit from: (pathed.Pathed):
"""A single version in a repository
"""
def __init__(self,path):
super(Version,self).__init__(path)
def __init__(self,vernum,path,filelist):
# Version must be numeric
try:
self.version=VerNum(os.path.basename(path))
self.version=VerNum(vernum)
except:
raise exceptions.InvalidVersionError(path)
raise exceptions.InvalidVersionError(vernum)
# Collect scripts in this folder
self.sql = dict()
self.python = None
try:
for script in os.listdir(path):
# skip __init__.py, because we assume that it's
# just there to mark the package
if script == '__init__.py':
continue
self._add_script(os.path.join(path,script))
except:
raise exceptions.InvalidVersionError(path)
for script in filelist:
# skip __init__.py, because we assume that it's
# just there to mark the package
if script == '__init__.py':
continue
self._add_script(os.path.join(path,script))
def script(self,database=None,operation=None):
#if database is None and operation is None:
@ -163,10 +182,13 @@ class Version(pathed.Pathed):
self._add_script_py(path)
elif path.endswith(extensions.sql):
self._add_script_sql(path)
SQL_FILENAME = re.compile(r'^(\d+)_([^_]+)_([^_]+).sql')
def _add_script_sql(self,path):
try:
version,dbms,op,ext=os.path.basename(path).split('.',3)
except:
match = self.SQL_FILENAME.match(os.path.basename(path))
if match:
version, dbms, op = match.group(1), match.group(2), match.group(3)
else:
raise exceptions.ScriptError("Invalid sql script name %s"%path)
# File the script into a dictionary
@ -176,6 +198,8 @@ class Version(pathed.Pathed):
ops = dbmses[dbms]
ops[op] = script.SqlScript(path)
def _add_script_py(self,path):
if self.python is not None:
raise Exception('You can only have one Python script per version, but you have: %s and %s' % (self.python, path))
self.python = script.PythonScript(path)
def _rm_ignore(self,path):
@ -185,29 +209,3 @@ class Version(pathed.Pathed):
except OSError:
pass
def commit(self,path,database=None,operation=None,required=None):
if (database is not None) and (operation is not None):
return self._commit_sql(path,database,operation)
return self._commit_py(path,required)
def _commit_sql(self,path,database,operation):
if not path.endswith(extensions.sql):
msg = "Bad file extension: should end with %s"%extensions.sql
raise exceptions.ScriptError(msg)
dest=os.path.join(self.path,'%s.%s.%s.%s'%(
str(self.version),str(database),str(operation),extensions.sql))
# Move the committed py script to this version's folder
shutil.move(path,dest)
self._add_script(dest)
def _commit_py(self,path_py,required=None):
if (not os.path.exists(path_py)) or (not os.path.isfile(path_py)):
raise exceptions.InvalidVersionError(path_py)
dest = os.path.join(self.path,'%s.%s'%(str(self.version),extensions.py))
# Move the committed py script to this version's folder
shutil.move(path_py,dest)
self._add_script(dest)
# Also delete the .pyc file, if it exists
path_pyc = path_py+'c'
if os.path.exists(path_pyc):
self._rm_ignore(path_pyc)

View File

@ -53,28 +53,11 @@ class TestVersionedRepository(fixture.Pathed):
def setUp(self):
Repository.clear()
self.path_repos=self.tmp_repos()
self.path_script=self.tmp_py()
# Create repository, script
Repository.create(self.path_repos,'repository_name')
def test_commit(self):
"""Commit scripts to a repository and detect repository version"""
# Load repository; commit script by pathname; script should go away
self.script_cls.create(self.path_script)
repos=Repository(self.path_repos)
self.assert_(os.path.exists(self.path_script))
repos.commit(self.path_script)
self.assert_(not os.path.exists(self.path_script))
# .pyc file from the committed script shouldn't exist either
self.assert_(not os.path.exists(self.path_script+'c'))
version = repos.versions.version()
self.assert_(os.path.exists(os.path.join(version.path,
"%s.py" % version.version)))
self.assert_(os.path.exists(os.path.join(version.path,
"__init__.py")))
def test_version(self):
"""We should correctly detect the version of a repository"""
self.script_cls.create(self.path_script)
repos=Repository(self.path_repos)
# Get latest version, or detect if a specified version exists
self.assertEquals(repos.latest,0)
@ -82,15 +65,14 @@ class TestVersionedRepository(fixture.Pathed):
# (so we can't just assume the following tests are correct)
self.assert_(repos.latest>=0)
self.assert_(repos.latest<1)
# Commit a script and test again
repos.commit(self.path_script)
# Create a script and test again
repos.create_script('')
self.assertEquals(repos.latest,1)
self.assert_(repos.latest>=0)
self.assert_(repos.latest>=1)
self.assert_(repos.latest<2)
# Commit a new script and test again
self.script_cls.create(self.path_script)
repos.commit(self.path_script)
# Create a new script and test again
repos.create_script('')
self.assertEquals(repos.latest,2)
self.assert_(repos.latest>=0)
self.assert_(repos.latest>=1)
@ -98,62 +80,27 @@ class TestVersionedRepository(fixture.Pathed):
self.assert_(repos.latest<3)
def test_source(self):
"""Get a script object by version number and view its source"""
self.script_cls.create(self.path_script)
# Load repository and commit script
repos=Repository(self.path_repos)
repos.commit(self.path_script)
repos.create_script('')
# Get script object
source=repos.version(1).script().source()
# Source is valid: script must have an upgrade function
# (not a very thorough test, but should be plenty)
self.assert_(source.find('def upgrade')>=0)
def test_latestversion(self):
self.script_cls.create(self.path_script)
"""Repository.version() (no params) returns the latest version"""
repos=Repository(self.path_repos)
repos.commit(self.path_script)
repos.create_script('')
self.assert_(repos.version(repos.latest) is repos.version())
self.assert_(repos.version() is not None)
def xtest_commit_fail(self):
"""Failed commits shouldn't corrupt the repository
Test disabled - logsql ran the script on commit; now that that's gone,
the content of the script is not checked before commit
"""
repos=Repository(self.path_repos)
path_script=self.tmp_py()
text_script = """
from sqlalchemy import *
from migrate import *
# Upgrade is not declared; commit should fail
#def upgrade():
# raise Exception()
def downgrade():
raise Exception()
""".replace("\n ","\n")
fd=open(path_script,'w')
fd.write(text_script)
fd.close()
# Record current state, and commit
ver_pre = os.listdir(repos.versions.path)
repos_pre = os.listdir(repos.path)
self.assertRaises(Exception,repos.commit,path_script)
# Version is unchanged
self.assertEquals(repos.latest,0)
# No new files created; committed script not moved
self.assert_(os.path.exists(path_script))
self.assertEquals(os.listdir(repos.versions.path),ver_pre)
self.assertEquals(os.listdir(repos.path),repos_pre)
def test_changeset(self):
"""Repositories can create changesets properly"""
# Create a nonzero-version repository of empty scripts
repos=Repository(self.path_repos)
for i in range(10):
self.script_cls.create(self.path_script)
repos.commit(self.path_script)
repos.create_script('')
def check_changeset(params,length):
"""Creates and verifies a changeset"""

View File

@ -8,7 +8,6 @@ class TestRunChangeset(fixture.Pathed,fixture.DB):
def setUp(self):
Repository.clear()
self.path_repos=self.tmp_repos()
self.path_script=self.tmp_py()
# Create repository, script
Repository.create(self.path_repos,'repository_name')
@ -17,8 +16,7 @@ class TestRunChangeset(fixture.Pathed,fixture.DB):
"""Running a changeset against a repository gives expected results"""
repos=Repository(self.path_repos)
for i in range(10):
script.PythonScript.create(self.path_script)
repos.commit(self.path_script)
repos.create_script('')
try:
ControlledSchema(self.engine,repos).drop()
except:

View File

@ -58,11 +58,9 @@ class TestControlledSchema(fixture.Pathed,fixture.DB):
dbcontrol.drop()
# Now try it with a nonzero value
script_path = self.tmp_py()
version=10
for i in range(version):
script.PythonScript.create(script_path)
self.repos.commit(script_path)
self.repos.create_script('')
self.assertEquals(self.repos.latest,version)
# Test with some mid-range value

View File

@ -120,17 +120,24 @@ class TestShellCommands(Shell):
def test_script(self):
"""We can create a migration script via the command line"""
script=self.tmp_py()
# Creating a file that doesn't exist should succeed
self.assertSuccess(self.cmd('script',script))
self.assert_(os.path.exists(script))
repos=self.tmp_repos()
self.assertSuccess(self.cmd('create',repos,'repository_name'))
self.assertSuccess(self.cmd('script', '--repository=%s' % repos, 'Desc'))
self.assert_(os.path.exists('%s/versions/001_Desc.py' % repos))
# 's' instead of 'script' should work too
os.remove(script)
self.assert_(not os.path.exists(script))
self.assertSuccess(self.cmd('s',script))
self.assert_(os.path.exists(script))
self.assertSuccess(self.cmd('script', '--repository=%s' % repos, 'More'))
self.assert_(os.path.exists('%s/versions/002_More.py' % repos))
def test_script_sql(self):
"""We can create a migration sql script via the command line"""
repos=self.tmp_repos()
self.assertSuccess(self.cmd('create',repos,'repository_name'))
self.assertSuccess(self.cmd('script_sql', '--repository=%s' % repos, 'mydb'))
self.assert_(os.path.exists('%s/versions/001_mydb_upgrade.sql' % repos))
self.assert_(os.path.exists('%s/versions/001_mydb_downgrade.sql' % repos))
# Can't create it again: it already exists
self.assertFailure(self.cmd('script',script))
self.assertFailure(self.cmd('script_sql', '--repository=%s' % repos, 'mydb'))
def test_manage(self):
"""Create a project management script"""
@ -145,20 +152,8 @@ class TestShellRepository(Shell):
def setUp(self):
"""Create repository, python change script"""
self.path_repos=repos=self.tmp_repos()
self.path_script=script=self.tmp_py()
self.assertSuccess(self.cmd('create',repos,'repository_name'))
self.assertSuccess(self.cmd('script',script))
def test_commit_1(self):
"""Commits should work correctly; script should vanish after commit"""
self.assert_(os.path.exists(self.path_script))
self.assertSuccess(self.cmd('commit',self.path_script,self.path_repos))
self.assert_(not os.path.exists(self.path_script))
def test_commit_2(self):
"""Commits should work correctly with repository as a keyword param"""
self.assert_(os.path.exists(self.path_script))
self.assertSuccess(self.cmd('commit',self.path_script,'--repository=%s'%self.path_repos))
self.assert_(not os.path.exists(self.path_script))
def test_version(self):
"""Correctly detect repository version"""
# Version: 0 (no scripts yet); successful execution
@ -169,17 +164,17 @@ class TestShellRepository(Shell):
fd=self.execute(self.cmd('version',self.path_repos))
self.assertEquals(fd.read().strip(),"0")
self.assertSuccess(fd)
# Commit a script and version should increment
self.assertSuccess(self.cmd('commit',self.path_script,'--repository=%s'%self.path_repos))
# Create a script and version should increment
self.assertSuccess(self.cmd('script', '--repository=%s' % self.path_repos, 'Desc'))
fd=self.execute(self.cmd('version',self.path_repos))
self.assertEquals(fd.read().strip(),"1")
self.assertSuccess(fd)
def test_source(self):
"""Correctly fetch a script's source"""
source=open(self.path_script).read()
self.assertSuccess(self.cmd('script', '--repository=%s' % self.path_repos, 'Desc'))
filename='%s/versions/001_Desc.py' % self.path_repos
source=open(filename).read()
self.assert_(source.find('def upgrade')>=0)
self.assertSuccess(self.cmd('commit',self.path_script,'--repository=%s'%self.path_repos))
# Later, we'll want to make repos optional somehow
# Version is now 1
fd=self.execute(self.cmd('version',self.path_repos))
self.assert_(fd.read().strip()=="1")
@ -190,50 +185,11 @@ class TestShellRepository(Shell):
self.assertSuccess(fd)
self.assert_(result.strip()==source.strip())
# We can also send the source to a file... test that too
self.assertSuccess(self.cmd('source',1,self.path_script,'--repository=%s'%self.path_repos))
self.assert_(os.path.exists(self.path_script))
fd=open(self.path_script)
self.assertSuccess(self.cmd('source',1,filename,'--repository=%s'%self.path_repos))
self.assert_(os.path.exists(filename))
fd=open(filename)
result=fd.read()
self.assert_(result.strip()==source.strip())
def test_commit_replace(self):
"""Commit can replace a specified version"""
# Commit the default script
self.assertSuccess(self.cmd('commit',self.path_script,self.path_repos))
self.assertEquals(self.cmd_version(self.path_repos),1)
# Read the default script's text
fd=self.execute(self.cmd('source',1,'--repository=%s'%self.path_repos))
script_src_1 = fd.read()
self.assertSuccess(fd)
# Commit a new script
script_text="""
from sqlalchemy import *
from migrate import *
# Our test is just that the source is different; so we don't have to
# do anything useful in here.
def upgrade():
pass
def downgrade():
pass
""".replace('\n ','\n')
fd=open(self.path_script,'w')
fd.write(script_text)
fd.close()
self.assertSuccess(self.cmd('commit',self.path_script,self.path_repos,1))
# We specified a version above - it should replace that, not create new
self.assertEquals(self.cmd_version(self.path_repos),1)
# Source should change
fd=self.execute(self.cmd('source',1,'--repository=%s'%self.path_repos))
script_src_2 = fd.read()
self.assertSuccess(fd)
self.assertNotEquals(script_src_1,script_src_2)
# source should be reasonable
self.assertEquals(script_src_2.strip(),script_text.strip())
self.assert_(script_src_1.count('from migrate import'))
self.assert_(script_src_1.count('from sqlalchemy import'))
class TestShellDatabase(Shell,fixture.DB):
"""Commands associated with a particular database"""
@ -263,8 +219,7 @@ class TestShellDatabase(Shell,fixture.DB):
path_script = self.tmp_py()
version=1
for i in range(version):
self.assertSuccess(self.cmd('script',path_script))
self.assertSuccess(self.cmd('commit',path_script,path_repos))
self.assertSuccess(self.cmd('script', '--repository=%s' % path_repos, 'Desc'))
# Repository version is correct
fd=self.execute(self.cmd('version',path_repos))
self.assertEquals(fd.read().strip(),str(version))
@ -284,7 +239,6 @@ class TestShellDatabase(Shell,fixture.DB):
# Create a repository
repos_name = 'repos_name'
repos_path = self.tmp()
script_path = self.tmp_py()
self.assertSuccess(self.cmd('create',repos_path,repos_name))
self.assertEquals(self.cmd_version(repos_path),0)
# Version the DB
@ -301,8 +255,7 @@ class TestShellDatabase(Shell,fixture.DB):
self.assertFailure(self.cmd('upgrade',self.url,repos_path,-1))
# Add a script to the repository; upgrade the db
self.assertSuccess(self.cmd('script',script_path))
self.assertSuccess(self.cmd('commit',script_path,repos_path))
self.assertSuccess(self.cmd('script', '--repository=%s' % repos_path, 'Desc'))
self.assertEquals(self.cmd_version(repos_path),1)
self.assertEquals(self.cmd_db_version(self.url,repos_path),0)
@ -321,14 +274,6 @@ class TestShellDatabase(Shell,fixture.DB):
self.assertSuccess(self.cmd('drop_version_control',self.url,repos_path))
def _run_test_sqlfile(self,upgrade_script,downgrade_script):
upgrade_path = self.tmp_sql()
downgrade_path = self.tmp_sql()
upgrade = (upgrade_path,upgrade_script)
downgrade = (downgrade_path,downgrade_script)
for file_path,file_text in (upgrade,downgrade):
fd = open(file_path,'w')
fd.write(file_text)
fd.close()
repos_path = self.tmp()
repos_name = 'repos'
@ -338,15 +283,12 @@ class TestShellDatabase(Shell,fixture.DB):
self.assertEquals(self.cmd_version(repos_path),0)
self.assertEquals(self.cmd_db_version(self.url,repos_path),0)
self.assertSuccess(self.cmd('commit',upgrade_path,repos_path,'postgres','upgrade'))
beforeCount = len(os.listdir(os.path.join(repos_path,'versions'))) # hmm, this number changes sometimes based on running from svn
self.assertSuccess(self.cmd('script_sql', '--repository=%s' % repos_path, 'postgres'))
self.assertEquals(self.cmd_version(repos_path),1)
self.assertEquals(len(os.listdir(os.path.join(repos_path,'versions','1'))),2)
# Add, not replace
self.assertSuccess(self.cmd('commit',downgrade_path,repos_path,'postgres','downgrade','--version=1'))
self.assertEquals(len(os.listdir(os.path.join(repos_path,'versions','1'))),3)
self.assertEquals(self.cmd_version(repos_path),1)
self.assertEquals(len(os.listdir(os.path.join(repos_path,'versions'))), beforeCount + 2)
open('%s/versions/001_postgres_upgrade.sql' % repos_path, 'a').write(upgrade_script)
open('%s/versions/001_postgres_downgrade.sql' % repos_path, 'a').write(downgrade_script)
self.assertEquals(self.cmd_db_version(self.url,repos_path),0)
self.assertRaises(Exception,self.engine.text('select * from t_table').execute)
@ -392,7 +334,6 @@ class TestShellDatabase(Shell,fixture.DB):
def test_test(self):
repos_name = 'repos_name'
repos_path = self.tmp()
script_path = self.tmp_py()
self.assertSuccess(self.cmd('create',repos_path,repos_name))
self.exitcode(self.cmd('drop_version_control',self.url,repos_path))
@ -401,9 +342,9 @@ class TestShellDatabase(Shell,fixture.DB):
self.assertEquals(self.cmd_db_version(self.url,repos_path),0)
# Empty script should succeed
self.assertSuccess(self.cmd('script',script_path))
self.assertSuccess(self.cmd('test',script_path,repos_path,self.url))
self.assertEquals(self.cmd_version(repos_path),0)
self.assertSuccess(self.cmd('script', '--repository=%s' % repos_path, 'Desc'))
self.assertSuccess(self.cmd('test',repos_path,self.url))
self.assertEquals(self.cmd_version(repos_path),1)
self.assertEquals(self.cmd_db_version(self.url,repos_path),0)
# Error script should fail
@ -423,8 +364,8 @@ class TestShellDatabase(Shell,fixture.DB):
file=open(script_path,'w')
file.write(script_text)
file.close()
self.assertFailure(self.cmd('test',script_path,repos_path,self.url))
self.assertEquals(self.cmd_version(repos_path),0)
self.assertFailure(self.cmd('test',repos_path,self.url,'blah blah'))
self.assertEquals(self.cmd_version(repos_path),1)
self.assertEquals(self.cmd_db_version(self.url,repos_path),0)
# Nonempty script using migrate_engine should succeed
@ -451,8 +392,8 @@ class TestShellDatabase(Shell,fixture.DB):
file=open(script_path,'w')
file.write(script_text)
file.close()
self.assertSuccess(self.cmd('test',script_path,repos_path,self.url))
self.assertEquals(self.cmd_version(repos_path),0)
self.assertSuccess(self.cmd('test',repos_path,self.url))
self.assertEquals(self.cmd_version(repos_path),1)
self.assertEquals(self.cmd_db_version(self.url,repos_path),0)
@fixture.usedb()
@ -507,7 +448,7 @@ class TestShellDatabase(Shell,fixture.DB):
output, exitcode = self.output_and_exitcode('python %s update_db_from_model' % script_path)
self.assertEquals(output, "")
self.assertEquals(self.cmd_version(repos_path),0)
self.assertEquals(self.cmd_db_version(self.url,repos_path),0) # version did not get bumped yet because new version not yet committed
self.assertEquals(self.cmd_db_version(self.url,repos_path),0) # version did not get bumped yet because new version not yet created
output, exitcode = self.output_and_exitcode('python %s compare_model_to_db' % script_path)
self.assertEquals(output, "No schema diffs")
output, exitcode = self.output_and_exitcode('python %s create_model' % script_path)
@ -545,13 +486,12 @@ class TestShellDatabase(Shell,fixture.DB):
tmp_account_rundiffs.drop()
""")
# Commit the change.
upgrade_script_path = self.tmp_named('upgrade_script.py')
# Save the upgrade script.
self.assertSuccess(self.cmd('script', '--repository=%s' % repos_path, 'Desc'))
upgrade_script_path = '%s/versions/001_Desc.py' % repos_path
open(upgrade_script_path, 'w').write(output)
#output, exitcode = self.output_and_exitcode('python %s test %s' % (script_path, upgrade_script_path)) # no, we already upgraded the db above
#self.assertEquals(output, "")
output, exitcode = self.output_and_exitcode('python %s commit %s' % (script_path, upgrade_script_path))
self.assertEquals(output, "")
output, exitcode = self.output_and_exitcode('python %s update_db_from_model' % script_path) # bump the db_version
self.assertEquals(output, "")
self.assertEquals(self.cmd_version(repos_path),1)

View File

@ -42,3 +42,13 @@ class TestVerNum(fixture.Base):
self.assert_(VerNum(1)>=1)
self.assert_(not VerNum(1)>=2)
self.assert_(VerNum(2)>=1)
class TestDescriptionNaming(fixture.Base):
def test_names(self):
self.assertEquals(strToFilename(''), '')
self.assertEquals(strToFilename('a'), 'a')
self.assertEquals(strToFilename('Abc Def'), 'Abc_Def')
self.assertEquals(strToFilename('Abc "D" Ef'), 'Abc_D_Ef')
self.assertEquals(strToFilename("Abc's Stuff"), 'Abc_s_Stuff')
self.assertEquals(strToFilename("a b"), 'a_b')