-from alembic import config, command, util
-from optparse import OptionParser
-import inspect
-import os
__version__ = '0.1alpha'
-def main(argv):
-
- # TODO:
- # OK, what's the super option parser library that
- # allows <command> plus command-specfic sub-options,
- # and derives everything from callables ?
- # we're inventing here a bit.
-
- commands = {}
- for fn in [getattr(command, n) for n in dir(command)]:
- if inspect.isfunction(fn) and \
- fn.__name__[0] != '_' and \
- fn.__module__ == 'alembic.command':
-
- spec = inspect.getargspec(fn)
- if spec[3]:
- positional = spec[0][1:-len(spec[3])]
- kwarg = spec[0][-len(spec[3]):]
- else:
- positional = spec[0][1:]
- kwarg = []
-
- commands[fn.__name__] = {
- 'name':fn.__name__,
- 'fn':fn,
- 'positional':positional,
- 'kwargs':kwarg
- }
-
- def format_cmd(cmd):
- return "%s %s" % (
- cmd['name'],
- " ".join(["<%s>" % p for p in cmd['positional']])
- )
-
- def format_opt(cmd, padding=32):
- opt = format_cmd(cmd)
- return " " + opt + \
- ((padding - len(opt)) * " ") + cmd['fn'].__doc__
-
- parser = OptionParser(
- "usage: %prog [options] <command> [command arguments]\n\n"
- "Available Commands:\n" +
- "\n".join(sorted([
- format_opt(cmd)
- for cmd in commands.values()
- ])) +
- "\n\n<revision> is a hex revision id or 'head'"
- )
-
- parser.add_option("-c", "--config",
- type="string",
- default="alembic.ini",
- help="Alternate config file")
- parser.add_option("-t", "--template",
- default='generic',
- type="string",
- help="Setup template for use with 'init'")
- parser.add_option("-m", "--message",
- type="string",
- help="Message string to use with 'revision'")
-
- cmd_line_options, cmd_line_args = parser.parse_args(argv[1:])
-
- if len(cmd_line_args) < 1:
- util.err("no command specified")
-
- cmd = cmd_line_args.pop(0).replace('-', '_')
-
- try:
- cmd_fn = commands[cmd]
- except KeyError:
- util.err("no such command %r" % cmd)
-
- kw = dict(
- (k, getattr(cmd_line_options, k))
- for k in cmd_fn['kwargs']
- )
-
- if len(cmd_line_args) != len(cmd_fn['positional']):
- util.err("Usage: %s %s [options]" % (
- os.path.basename(argv[0]),
- format_cmd(cmd_fn)
- ))
-
- cfg = config.Config(cmd_line_options.config)
- cmd_fn['fn'](cfg, *cmd_line_args, **kw)
-
-
+from alembic import command, util
+from optparse import OptionParser
import ConfigParser
import inspect
import os
import sys
-from alembic import util
class Config(object):
def __init__(self, file_):
else:
return default
-
\ No newline at end of file
+def main(argv):
+
+ # TODO:
+ # OK, what's the super option parser library that
+ # allows <command> plus command-specfic sub-options,
+ # and derives everything from callables ?
+ # we're inventing here a bit.
+
+ commands = {}
+ for fn in [getattr(command, n) for n in dir(command)]:
+ if inspect.isfunction(fn) and \
+ fn.__name__[0] != '_' and \
+ fn.__module__ == 'alembic.command':
+
+ spec = inspect.getargspec(fn)
+ if spec[3]:
+ positional = spec[0][1:-len(spec[3])]
+ kwarg = spec[0][-len(spec[3]):]
+ else:
+ positional = spec[0][1:]
+ kwarg = []
+
+ commands[fn.__name__] = {
+ 'name':fn.__name__,
+ 'fn':fn,
+ 'positional':positional,
+ 'kwargs':kwarg
+ }
+
+ def format_cmd(cmd):
+ return "%s %s" % (
+ cmd['name'],
+ " ".join(["<%s>" % p for p in cmd['positional']])
+ )
+
+ def format_opt(cmd, padding=32):
+ opt = format_cmd(cmd)
+ return " " + opt + \
+ ((padding - len(opt)) * " ") + cmd['fn'].__doc__
+
+ parser = OptionParser(
+ "usage: %prog [options] <command> [command arguments]\n\n"
+ "Available Commands:\n" +
+ "\n".join(sorted([
+ format_opt(cmd)
+ for cmd in commands.values()
+ ])) +
+ "\n\n<revision> is a hex revision id or 'head'"
+ )
+
+ parser.add_option("-c", "--config",
+ type="string",
+ default="alembic.ini",
+ help="Alternate config file")
+ parser.add_option("-t", "--template",
+ default='generic',
+ type="string",
+ help="Setup template for use with 'init'")
+ parser.add_option("-m", "--message",
+ type="string",
+ help="Message string to use with 'revision'")
+
+ cmd_line_options, cmd_line_args = parser.parse_args(argv[1:])
+
+ if len(cmd_line_args) < 1:
+ util.err("no command specified")
+
+ cmd = cmd_line_args.pop(0).replace('-', '_')
+
+ try:
+ cmd_fn = commands[cmd]
+ except KeyError:
+ util.err("no such command %r" % cmd)
+
+ kw = dict(
+ (k, getattr(cmd_line_options, k))
+ for k in cmd_fn['kwargs']
+ )
+
+ if len(cmd_line_args) != len(cmd_fn['positional']):
+ util.err("Usage: %s %s [options]" % (
+ os.path.basename(argv[0]),
+ format_cmd(cmd_fn)
+ ))
+
+ cfg = Config(cmd_line_options.config)
+ try:
+ cmd_fn['fn'](cfg, *cmd_line_args, **kw)
+ except util.CommandError, e:
+ util.err(str(e))
from alembic.ddl import base
from alembic import util
from sqlalchemy import MetaData, Table, Column, String
+import logging
+
+log = logging.getLogger(__name__)
class ContextMeta(type):
def __init__(cls, classname, bases, dict_):
return self.connection.scalar(_version.select())
def _update_current_rev(self, old, new):
+ if old == new:
+ return
+
if new is None:
self.connection.execute(_version.delete())
elif old is None:
self.connection.execute(_version.update(), {'version_num':new})
def run_migrations(self, **kw):
- current_rev = self._current_rev()
- rev = -1
+ current_rev = prev_rev = rev = self._current_rev()
for change, rev in self._migrations_fn(current_rev):
- print "-> %s" % (rev, )
+ log.info("Running %s %s -> %s", change.__name__, prev_rev, rev)
change(**kw)
- if rev != -1:
- self._update_current_rev(current_rev, rev)
+ prev_rev = rev
+
+ self._update_current_rev(current_rev, rev)
def _exec(self, construct):
self.connection.execute(construct)
from sqlalchemy.types import NULLTYPE
from sqlalchemy import schema
-__all__ = ['alter_column', 'create_foreign_key', 'create_unique_constraint', 'execute']
+__all__ = [
+ 'alter_column',
+ 'create_foreign_key',
+ 'create_unique_constraint',
+ 'execute']
def alter_column(table_name, column_name,
nullable=util.NO_VALUE,
self.versions = os.path.join(self.dir, 'versions')
if not os.access(dir, os.F_OK):
- util.err("Path doesn't exist: %r. Please use "
+ raise util.CommandError("Path doesn't exist: %r. Please use "
"the 'init' command to create a new "
"scripts folder." % dir)
def _get_rev(self, id_):
if id_ == 'head':
- return self._current_head()
+ id_ = self._current_head()
elif id_ == 'base':
- return None
- else:
- return id_
+ id_ = None
+ try:
+ return self._revision_map[id_]
+ except KeyError:
+ raise util.CommandError("No such revision %s" % id_)
def _revs(self, upper, lower):
- lower = self._revision_map[self._get_rev(lower)]
- upper = self._revision_map[self._get_rev(upper)]
+ lower = self._get_rev(lower)
+ upper = self._get_rev(upper)
script = upper
while script != lower:
yield script
NO_VALUE = util.symbol("NO_VALUE")
+class CommandError(Exception):
+ pass
+
try:
width = int(os.environ['COLUMNS'])
except (KeyError, ValueError):
#!/usr/bin/env python
-from alembic import main
+from alembic.config import main
import sys
if __name__ == "__main__":