]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
some ui improvements
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 29 Apr 2010 22:17:58 +0000 (18:17 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 29 Apr 2010 22:17:58 +0000 (18:17 -0400)
alembic/__init__.py
alembic/config.py
alembic/context.py
alembic/op.py
alembic/script.py
alembic/util.py
scripts/alembic

index c8c90904c54f425d45ae9273784d1e4576772882..f18873da977065b24686858677445f031eab543e 100644 (file)
@@ -1,97 +1,4 @@
-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)
-
-
 
index b56fc9d4bb2f9b6a44c07ce694a2687c779989a4..d244193a44b4f73b6c89f5216dff64ec88f43d39 100644 (file)
@@ -1,8 +1,9 @@
+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_):
@@ -31,4 +32,93 @@ class Config(object):
         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))
index c0380350ce1597ba86d59faf99d088dbd6f2b9b6..7ec872e6879be3cc27ff5735fbb2daa2a1f2d581 100644 (file)
@@ -1,6 +1,9 @@
 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_):
@@ -29,6 +32,9 @@ class DefaultContext(object):
         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:
@@ -37,13 +43,13 @@ class DefaultContext(object):
             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)
index 2e1abd17519e7f512679bbe640e0d77b212c75db..dbd0de4ead7830629e2bac28aa8fba2e26e1cd15 100644 (file)
@@ -3,7 +3,11 @@ from alembic.context import get_context
 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,
index e6a62213c41a3b67e76eefe04c99222313244b5b..f9a4f6b4d80e4a14b10b04dbd151ce17f2e9fc57 100644 (file)
@@ -13,7 +13,7 @@ class ScriptDirectory(object):
         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)
         
@@ -24,15 +24,17 @@ class ScriptDirectory(object):
     
     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
index 5751e204d4b016f534b99839d37378bcf3310499..e25836792a00afbbfc7854e1340e4a7b1fd907a9 100644 (file)
@@ -12,6 +12,9 @@ import uuid
 
 NO_VALUE = util.symbol("NO_VALUE")
 
+class CommandError(Exception):
+    pass
+    
 try:
     width = int(os.environ['COLUMNS'])
 except (KeyError, ValueError):
index 191cc29d92fe97f3280bb53fec048ec086ccfe2a..5a76304cedd88a41a9adcac65be873ed09bb66b5 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-from alembic import main
+from alembic.config import main
 import sys
 
 if __name__ == "__main__":