[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
--- 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):