migrate.versioning.repository PEP-8 clean, added to api.rst

This commit is contained in:
jan.dittberner 2009-01-25 21:08:49 +00:00
parent 5289c4df3b
commit 2a8860478c
2 changed files with 102 additions and 76 deletions

View File

@ -111,3 +111,10 @@ Module :mod:`pathed <migrate.versioning.pathed>`
.. automodule:: migrate.versioning.pathed .. automodule:: migrate.versioning.pathed
:members: :members:
:synopsis: File/Directory handling class :synopsis: File/Directory handling class
Module :mod:`repository <migrate.versioning.repository>`
--------------------------------------------------------
.. automodule:: migrate.versioning.repository
:members:
:synopsis: SQLAlchemy migrate repository management

View File

@ -1,20 +1,30 @@
from pkg_resources import resource_string,resource_filename """
import os,shutil SQLAlchemy migrate repository management.
"""
from pkg_resources import resource_string, resource_filename
import os
import shutil
import string import string
from migrate.versioning.base import * from migrate.versioning.base import *
from migrate.versioning.template import template from migrate.versioning.template import template
from migrate.versioning import exceptions,script,version,pathed,cfgparse from migrate.versioning import exceptions, script, version, pathed, cfgparse
class Changeset(dict): class Changeset(dict):
"""A collection of changes to be applied to a database """A collection of changes to be applied to a database.
Changesets are bound to a repository and manage a set of logsql scripts from
that repository. Changesets are bound to a repository and manage a set of logsql
Behaves like a dict, for the most part. Keys are ordered based on start/end. scripts from that repository.
Behaves like a dict, for the most part. Keys are ordered based on
start/end.
""" """
def __init__(self,start,*changes,**k):
"""Give a start version; step must be explicitly stated""" def __init__(self, start, *changes, **k):
self.step = k.pop('step',1) """
Give a start version; step must be explicitly stated.
"""
self.step = k.pop('step', 1)
self.start = version.VerNum(start) self.start = version.VerNum(start)
self.end = self.start self.end = self.start
for change in changes: for change in changes:
@ -22,26 +32,30 @@ class Changeset(dict):
def __iter__(self): def __iter__(self):
return iter(self.items()) return iter(self.items())
def keys(self): def keys(self):
"""In a series of upgrades x -> y, keys are version x. Sorted.""" """
ret = super(Changeset,self).keys() In a series of upgrades x -> y, keys are version x. Sorted.
"""
ret = super(Changeset, self).keys()
# Reverse order if downgrading # Reverse order if downgrading
ret.sort(reverse=(self.step < 1)) ret.sort(reverse=(self.step < 1))
return ret return ret
def values(self): def values(self):
return [self[k] for k in self.keys()] return [self[k] for k in self.keys()]
def items(self):
return zip(self.keys(),self.values())
def add(self,change): def items(self):
return zip(self.keys(), self.values())
def add(self, change):
key = self.end key = self.end
self.end += self.step self.end += self.step
self[key] = change self[key] = change
def run(self,*p,**k): def run(self, *p, **k):
for version,script in self: for version, script in self:
script.run(*p,**k) script.run(*p, **k)
class Repository(pathed.Pathed): class Repository(pathed.Pathed):
@ -51,88 +65,94 @@ class Repository(pathed.Pathed):
# Version information, inside repository # Version information, inside repository
_versions='versions' _versions='versions'
def __init__(self,path): def __init__(self, path):
log.info('Loading repository %s...'%path) log.info('Loading repository %s...' % path)
self.verify(path) self.verify(path)
super(Repository,self).__init__(path) super(Repository, self).__init__(path)
self.config=cfgparse.Config(os.path.join(self.path,self._config)) self.config=cfgparse.Config(os.path.join(self.path, self._config))
self.versions=version.Collection(os.path.join(self.path,self._versions)) self.versions=version.Collection(os.path.join(self.path,
log.info('Repository %s loaded successfully'%path) self._versions))
log.debug('Config: %r'%self.config.to_dict()) log.info('Repository %s loaded successfully' % path)
log.debug('Config: %r' % self.config.to_dict())
@classmethod @classmethod
def verify(cls,path): def verify(cls, path):
"""Ensure the target path is a valid repository """
Throws InvalidRepositoryError if not Ensure the target path is a valid repository.
:raises: :exc:`InvalidRepositoryError` if not valid
""" """
# Ensure the existance of required files # Ensure the existance of required files
try: try:
cls.require_found(path) cls.require_found(path)
cls.require_found(os.path.join(path,cls._config)) cls.require_found(os.path.join(path, cls._config))
cls.require_found(os.path.join(path,cls._versions)) cls.require_found(os.path.join(path, cls._versions))
except exceptions.PathNotFoundError,e: except exceptions.PathNotFoundError, e:
raise exceptions.InvalidRepositoryError(path) raise exceptions.InvalidRepositoryError(path)
@classmethod @classmethod
def prepare_config(cls,pkg,rsrc,name,**opts): def prepare_config(cls, pkg, rsrc, name, **opts):
"""Prepare a project configuration file for a new project""" """
Prepare a project configuration file for a new project.
"""
# Prepare opts # Prepare opts
defaults=dict( defaults=dict(
version_table='migrate_version', version_table='migrate_version',
repository_id=name, repository_id=name,
required_dbs=[], required_dbs=[], )
) for key, val in defaults.iteritems():
for key,val in defaults.iteritems():
if (key not in opts) or (opts[key] is None): if (key not in opts) or (opts[key] is None):
opts[key]=val opts[key]=val
tmpl = resource_string(pkg,rsrc) tmpl = resource_string(pkg, rsrc)
ret = string.Template(tmpl).substitute(opts) ret = string.Template(tmpl).substitute(opts)
return ret return ret
@classmethod @classmethod
def create(cls,path,name,**opts): def create(cls, path, name, **opts):
"""Create a repository at a specified path""" """Create a repository at a specified path"""
cls.require_notfound(path) cls.require_notfound(path)
pkg,rsrc = template.get_repository(as_pkg=True) pkg, rsrc = template.get_repository(as_pkg=True)
tmplpkg = '.'.join((pkg,rsrc)) tmplpkg = '.'.join((pkg, rsrc))
tmplfile = resource_filename(pkg,rsrc) tmplfile = resource_filename(pkg, rsrc)
config_text = cls.prepare_config(tmplpkg,cls._config,name,**opts) config_text = cls.prepare_config(tmplpkg, cls._config, name, **opts)
# Create repository # Create repository
try: try:
shutil.copytree(tmplfile,path) shutil.copytree(tmplfile, path)
# Edit config defaults # Edit config defaults
fd = open(os.path.join(path,cls._config),'w') fd = open(os.path.join(path, cls._config), 'w')
fd.write(config_text) fd.write(config_text)
fd.close() fd.close()
# Create a management script # Create a management script
manager = os.path.join(path,'manage.py') manager = os.path.join(path, 'manage.py')
manage(manager,repository=path) manage(manager, repository=path)
except: except:
log.error("There was an error creating your repository") log.error("There was an error creating your repository")
return cls(path) return cls(path)
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'))
id=property(lambda self: self.config.get('db_settings','repository_id'))
def version(self,*p,**k): def create_script(self, description, **k):
return self.versions.version(*p,**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'))
id=property(lambda self: self.config.get('db_settings', 'repository_id'))
def version(self, *p, **k):
return self.versions.version(*p, **k)
@classmethod @classmethod
def clear(cls): def clear(cls):
super(Repository,cls).clear() super(Repository, cls).clear()
version.Collection.clear() version.Collection.clear()
def changeset(self,database,start,end=None): def changeset(self, database, start, end=None):
"""Create a changeset to migrate this dbms from ver. start to end/latest """
Create a changeset to migrate this dbms from ver. start to end/latest.
""" """
start = version.VerNum(start) start = version.VerNum(start)
if end is None: if end is None:
@ -143,24 +163,23 @@ class Repository(pathed.Pathed):
step = 1 step = 1
range_mod = 1 range_mod = 1
op = 'upgrade' op = 'upgrade'
else: else:
step = -1 step = -1
range_mod = 0 range_mod = 0
op = 'downgrade' op = 'downgrade'
versions = range(start+range_mod,end+range_mod,step) versions = range(start+range_mod, end+range_mod, step)
#changes = [self.version(v).script(database,op).log for v in versions] changes = [self.version(v).script(database, op) for v in versions]
changes = [self.version(v).script(database,op) for v in versions] ret = Changeset(start, step=step, *changes)
ret = Changeset(start,step=step,*changes)
return ret return ret
def manage(file,**opts): def manage(file, **opts):
"""Create a project management script""" """Create a project management script"""
pkg,rsrc = template.manage(as_pkg=True) pkg, rsrc = template.manage(as_pkg=True)
tmpl = resource_string(pkg,rsrc) tmpl = resource_string(pkg, rsrc)
vars = ",".join(["%s='%s'"%vars for vars in opts.iteritems()]) vars = ",".join(["%s='%s'"%vars for vars in opts.iteritems()])
result = tmpl%dict(defaults=vars) result = tmpl%dict(defaults=vars)
fd = open(file,'w') fd = open(file, 'w')
fd.write(result) fd.write(result)
fd.close() fd.close()