From: Mike Bayer Date: Tue, 27 Apr 2010 23:13:55 +0000 (-0400) Subject: we're making revision files.... X-Git-Tag: rel_0_1_0~106 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cf6b911834e32e1fb7e68f78832119bbe6e96fc4;p=thirdparty%2Fsqlalchemy%2Falembic.git we're making revision files.... --- diff --git a/alembic/command.py b/alembic/command.py index 8278d6e3..de3f27e2 100644 --- a/alembic/command.py +++ b/alembic/command.py @@ -28,6 +28,10 @@ def init(opts): util.status("Creating directory %s" % os.path.abspath(dir_), os.makedirs, dir_) + + versions = os.path.join(dir_, 'versions') + util.status("Creating directory %s" % os.path.abspath(versions), + os.makedirs, versions) script = ScriptDirectory(dir_, opts) @@ -61,7 +65,7 @@ def revision(opts): """Create a new revision file.""" script = ScriptDirectory.from_options(opts) - script.generate_rev(uuid.uuid4()) + script.generate_rev(uuid.uuid4(), opts.cmd_line_options.message) def upgrade(opts): """Upgrade to the latest version.""" diff --git a/alembic/op.py b/alembic/op.py index 16fc1ab7..ebd4b56f 100644 --- a/alembic/op.py +++ b/alembic/op.py @@ -2,7 +2,7 @@ from alembic import util from sqlalchemy.types import NULLTYPE from sqlalchemy import schema -__all__ = ['alter_column', 'add_foreign_key'] +__all__ = ['alter_column', 'create_foreign_key', 'create_unique_constraint'] def alter_column(table_name, column_name, nullable=util.NO_VALUE, diff --git a/alembic/script.py b/alembic/script.py index 8cac6917..ddd8ea5f 100644 --- a/alembic/script.py +++ b/alembic/script.py @@ -4,13 +4,19 @@ import shutil import re import inspect -_uuid_re = re.compile(r'[a-z0-9]{16}') -_mod_def_re = re.compile(r'(upgrade|downgrade)_([a-z0-9]{16})') +_uuid_re = re.compile(r'[a-z0-9]{32}\.py$') +_mod_def_re = re.compile(r'(upgrade|downgrade)_([a-z0-9]{32})') class ScriptDirectory(object): def __init__(self, dir, options): self.dir = dir - self.options = otions + self.versions = os.path.join(self.dir, 'versions') + + if not os.access(dir, os.F_OK): + options.err("Path doesn't exist: %r. Please use " + "the 'init' command to create a new " + "scripts folder." % dir) + self.options = options @classmethod def from_options(cls, options): @@ -20,22 +26,32 @@ class ScriptDirectory(object): @util.memoized_property def _revision_map(self): - for file_ in os.listdir(self.dir): - script = Script.from_file(self.dir, file_) + map_ = {} + for file_ in os.listdir(self.versions): + script = Script.from_path(self.versions, file_) if script is None: continue + if script.upgrade in map_: + util.warn("Revision %s is present more than once" % script.upgrade) map_[script.upgrade] = script + for rev in map_.values(): + if rev.downgrade is None: + continue + if rev.downgrade not in map_: + util.warn("Revision %s referenced from %s is not present" + % (rev.downgrade, rev)) + rev.downgrade = None + else: + map_[rev.downgrade].nextrev = rev.upgrade return map_ - def _get_head(self): + def _get_heads(self): # TODO: keep map sorted chronologically - + heads = [] for script in self._revision_map.values(): - if script.upgrade is None \ - and script.downgrade in self._revision_map: - return script - else: - return None + if script.nextrev is None: + heads.append(script) + return heads def _get_origin(self): # TODO: keep map sorted chronologically @@ -48,7 +64,7 @@ class ScriptDirectory(object): return None def generate_template(self, src, dest, **kw): - util.status("Generating %s" % os.path.abspath(src), + util.status("Generating %s" % os.path.abspath(dest), util.template_to_file, src, dest, @@ -59,18 +75,26 @@ class ScriptDirectory(object): util.status("Generating %s" % os.path.abspath(dest), shutil.copy, src, dest) - - def generate_rev(self, revid): - current_head = self._get_head() + def generate_rev(self, revid, message): + current_heads = self._get_heads() + if len(current_heads) > 1: + raise Exception("Only a single head supported so far...") + if current_heads: + current_head = current_heads[0] + else: + current_head = None self.generate_template( - os.path.join(self.dir, "script.py.mako", - up_revision=revid, - down_revision=current_head.upgrade if current_head else None - ) + os.path.join(self.dir, "script.py.mako"), + os.path.join(self.versions, "%s.py" % revid.hex), + up_revision=str(revid.hex), + down_revision=current_head.upgrade if current_head else None, + message=message if message is not None else ("Alembic revision %s" % revid.hex) ) class Script(object): + nextrev = None + def __init__(self, module): self.module = module self.upgrade = self.downgrade = None @@ -87,12 +111,16 @@ class Script(object): self.downgrade = m.group(2) if not self.downgrade and not self.upgrade: raise Exception("Script %s has no upgrade or downgrade path" % module) - + + def __str__(self): + return "revision %s" % self.upgrade + @classmethod def from_path(cls, dir_, filename): if not _uuid_re.match(filename): return None - + + print "LOAD PYTHON FILE", filename module = util.load_python_file(dir_, filename) return Script(module) \ No newline at end of file diff --git a/alembic/util.py b/alembic/util.py index df5bfd89..b065ef92 100644 --- a/alembic/util.py +++ b/alembic/util.py @@ -4,6 +4,8 @@ import os import textwrap from sqlalchemy import util import imp +import warnings +import re NO_VALUE = util.symbol("NO_VALUE") @@ -24,8 +26,8 @@ def format_opt(opt, hlp, padding=22): return " " + opt + \ ((padding - len(opt)) * " ") + hlp -def status(message, fn, *arg, **kw): - msg(message + "...", False) +def status(_statmsg, fn, *arg, **kw): + msg(_statmsg + "...", False) try: ret = fn(*arg, **kw) sys.stdout.write("done\n") @@ -34,7 +36,9 @@ def status(message, fn, *arg, **kw): sys.stdout.write("FAILED\n") raise - +def warn(msg): + warnings.warn(msg) + def msg(msg, newline=True): lines = textwrap.wrap(msg, width) if len(lines) > 1: diff --git a/templates/generic/script.py.mako b/templates/generic/script.py.mako index 596027f3..50919464 100644 --- a/templates/generic/script.py.mako +++ b/templates/generic/script.py.mako @@ -1,3 +1,5 @@ +"""${message}""" + from alembic.op import * def upgrade_${up_revision}(): diff --git a/templates/multidb/script.py.mako b/templates/multidb/script.py.mako index 112b0269..2aebeb60 100644 --- a/templates/multidb/script.py.mako +++ b/templates/multidb/script.py.mako @@ -1,3 +1,5 @@ +"""${message}""" + from alembic.op import * def upgrade_${up_revision}(engine): diff --git a/templates/pylons/script.py.mako b/templates/pylons/script.py.mako index 596027f3..50919464 100644 --- a/templates/pylons/script.py.mako +++ b/templates/pylons/script.py.mako @@ -1,3 +1,5 @@ +"""${message}""" + from alembic.op import * def upgrade_${up_revision}():