[migration] unify process_script command stable
authorJulien Jehannet <julien.jehannet@logilab.fr>
Thu, 29 Jul 2010 15:18:31 +0200
branchstable
changeset 6035 f8c7aa251782
parent 6034 5e8076eb8ec7
child 6036 fe17d4bac785
[migration] unify process_script command - simplify wrapper by putting the logic in the migration module - enable sql script in shell invocation - adjust cmd_process_script docstring in interactive shell
migration.py
server/migractions.py
--- a/migration.py	Tue Jul 27 19:40:57 2010 +0200
+++ b/migration.py	Thu Jul 29 15:18:31 2010 +0200
@@ -24,13 +24,15 @@
 import logging
 import tempfile
 from os.path import exists, join, basename, splitext
+from itertools import chain
 
+from logilab.common import IGNORED_EXTENSIONS
 from logilab.common.decorators import cached
 from logilab.common.configuration import REQUIRED, read_old_config
 from logilab.common.shellutils import ASK
 from logilab.common.changelog import Version
 
-from cubicweb import ConfigurationError
+from cubicweb import ConfigurationError, ExecutionError
 
 
 def filter_scripts(config, directory, fromversion, toversion, quiet=True):
@@ -51,8 +53,7 @@
         return []
     result = []
     for fname in os.listdir(directory):
-        if fname.endswith('.pyc') or fname.endswith('.pyo') \
-               or fname.endswith('~'):
+        if fname.endswith(IGNORED_EXTENSIONS):
             continue
         fpath = join(directory, fname)
         try:
@@ -75,9 +76,6 @@
     return sorted(result)
 
 
-IGNORED_EXTENSIONS = ('.swp', '~')
-
-
 def execscript_confirm(scriptpath):
     """asks for confirmation before executing a script and provides the
     ability to show the script's content
@@ -285,6 +283,16 @@
         Display the migration script path, ask for confirmation and execute it
         if confirmed
 
+        Allowed input file formats for migration scripts:
+        - `python` (.py)
+        - `sql` (.sql)
+        - `doctest` (.txt or .rst)
+
+        .. warning:: sql migration scripts are not available in web-only instance
+
+        You can pass script parameters with using double dash (--) in the
+        command line
+
         Context environment can have these variables defined:
         - __name__ : will be determine by funcname parameter
         - __file__ : is the name of the script if it exists
@@ -295,13 +303,20 @@
         :params args: optional arguments for funcname
         :keyword scriptargs: optional arguments of the script
         """
+        ftypes = {'python':  ('.py',),
+                  'doctest': ('.txt', '.rst'),
+                  'sql':     ('.sql',)}
+        # sql migration scripts are not available in web-only instance
+        if not hasattr(self, "session"):
+            ftypes.pop('sql')
         migrscript = os.path.normpath(migrscript)
-        if migrscript.endswith('.py'):
-            script_mode = 'python'
-        elif migrscript.endswith(('.txt', '.rst')):
-            script_mode = 'doctest'
+        for (script_mode, ftype) in ftypes.items():
+            if migrscript.endswith(ftype):
+                break
         else:
-            raise Exception('This is not a valid cubicweb shell input')
+            ftypes = ', '.join(chain(*ftypes.values()))
+            msg = 'ignoring %s, not a valid script extension (%s)'
+            raise ExecutionError(msg % (migrscript, ftypes))
         if not self.execscript_confirm(migrscript):
             return
         scriptlocals = self._create_context().copy()
@@ -322,6 +337,9 @@
                     self.critical('no %s in script %s', funcname, migrscript)
                     return None
                 return func(*args, **kwargs)
+        elif script_mode == 'sql':
+            from cubicweb.server.sqlutils import sqlexec
+            sqlexec(open(migrscript).read(), self.session.system_sql)
         else: # script_mode == 'doctest'
             import doctest
             doctest.testfile(migrscript, module_relative=False,
--- a/server/migractions.py	Tue Jul 27 19:40:57 2010 +0200
+++ b/server/migractions.py	Thu Jul 29 15:18:31 2010 +0200
@@ -49,7 +49,7 @@
 from yams.constraints import SizeConstraint
 from yams.schema2sql import eschema2sql, rschema2sql
 
-from cubicweb import AuthenticationError
+from cubicweb import AuthenticationError, ExecutionError
 from cubicweb.schema import (ETYPE_NAME_MAP, META_RTYPES, VIRTUAL_RTYPES,
                              PURE_VIRTUAL_RTYPES,
                              CubicWebRelationSchema, order_eschemas)
@@ -117,27 +117,19 @@
             super(ServerMigrationHelper, self).migrate(vcconf, toupgrade, options)
 
     def cmd_process_script(self, migrscript, funcname=None, *args, **kwargs):
-        """execute a migration script
-        in interactive mode,  display the migration script path, ask for
-        confirmation and execute it if confirmed
-        """
         try:
-            if migrscript.endswith('.sql'):
-                if self.execscript_confirm(migrscript):
-                    sqlexec(open(migrscript).read(), self.session.system_sql)
-            elif migrscript.endswith('.py') or migrscript.endswith('.txt'):
-                return super(ServerMigrationHelper, self).cmd_process_script(
-                    migrscript, funcname, *args, **kwargs)
-            else:
-                print >> sys.stderr
-                print >> sys.stderr, ('-> ignoring %s, only .py .sql and .txt scripts are considered' %
-                       migrscript)
-                print >> sys.stderr
+            super(ServerMigrationHelper, self).cmd_process_script(
+                  migrscript, funcname, *args, **kwargs)
             self.commit()
+        except ExecutionError, err:
+            print >> sys.stderr, "-> %s" % err
         except:
             self.rollback()
             raise
 
+    # Adjust docstring
+    cmd_process_script.__doc__ = MigrationHelper.cmd_process_script.__doc__
+
     # server specific migration methods ########################################
 
     def backup_database(self, backupfile=None, askconfirm=True):