web/lib/django_extensions/management/commands/runscript.py
changeset 3 526ebd3988b0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/django_extensions/management/commands/runscript.py	Wed Jan 20 12:37:40 2010 +0100
@@ -0,0 +1,134 @@
+from django.core.management.base import BaseCommand
+from django.core.management.color import no_style
+from optparse import make_option
+import sys
+import os
+
+try:
+    set
+except NameError:
+    from sets import Set as set   # Python 2.3 fallback
+
+class Command(BaseCommand):
+    option_list = BaseCommand.option_list + (
+        make_option('--fixtures', action='store_true', dest='infixtures', default=False,
+            help='Only look in app.fixtures subdir'),
+        make_option('--noscripts', action='store_true', dest='noscripts', default=False,
+            help='Look in app.scripts subdir'),
+        make_option('-s', '--silent', action='store_true', dest='silent', default=False,
+            help='Run silently, do not show errors and tracebacks'),
+        make_option('--no-traceback', action='store_true', dest='no_traceback', default=False,
+            help='Do not show tracebacks'),
+    )
+    help = 'Runs a script in django context.'
+    args = "script [script ...]"
+
+    def handle(self, *scripts, **options):
+        from django.db.models import get_apps
+        
+        NOTICE = self.style.SQL_TABLE
+        NOTICE2 = self.style.SQL_FIELD
+        ERROR = self.style.ERROR_OUTPUT
+        ERROR2 = self.style.NOTICE
+
+        subdirs = []
+
+        if not options.get('noscripts'):
+            subdirs.append('scripts')
+        if options.get('infixtures'):
+            subdirs.append('fixtures')
+        verbosity = int(options.get('verbosity', 1))
+        show_traceback = options.get('traceback', True)
+        if show_traceback is None:
+            # XXX: traceback is set to None from Django ?
+            show_traceback = True
+        no_traceback = options.get('no_traceback', False)
+        if no_traceback:
+            show_traceback = False
+        silent = options.get('silent', False)
+        if silent:
+            verbosity = 0
+
+        if len(subdirs) < 1:
+            print NOTICE("No subdirs to run left.")
+            return
+
+        if len(scripts) < 1:
+            print ERROR("Script name required.")
+            return
+
+        def run_script(mod):
+            # TODO: add arguments to run
+            try:
+                mod.run()
+            except Exception, e:
+                if silent:
+                    return
+                if verbosity > 0:
+                    print ERROR("Exception while running run() in '%s'" % mod.__name__)
+                if show_traceback:
+                    raise
+        
+        def my_import(mod):
+            if verbosity > 1:
+                print NOTICE("Check for %s" % mod)
+            try:
+                t = __import__(mod, [], [], [" "])
+                #if verbosity > 1:
+                #    print NOTICE("Found script %s ..." % mod)
+                if hasattr(t, "run"):
+                    if verbosity > 1:
+                        print NOTICE2("Found script '%s' ..." % mod)
+                    #if verbosity > 1:
+                    #    print NOTICE("found run() in %s. executing..." % mod)
+                    return t
+                else:
+                    if verbosity > 1:
+                        print ERROR2("Find script '%s' but no run() function found." % mod)
+            except ImportError:
+                return False
+        
+        def find_modules_for_script(script):
+            """ find script module which contains 'run' attribute """
+            modules = []
+            # first look in apps
+            for app in get_apps():
+                app_name = app.__name__.split(".")[:-1] # + ['fixtures']
+                for subdir in subdirs:
+                    mod = my_import(".".join(app_name + [subdir, script]))
+                    if mod:
+                        modules.append(mod)
+
+            # try app.DIR.script import
+            sa = script.split(".")
+            for subdir in subdirs:
+                nn = ".".join(sa[:-1] + [subdir, sa[-1]])
+                mod = my_import(nn)
+                if mod:
+                    modules.append(mod)
+
+            # try direct import
+            if script.find(".") != -1:
+                mod = my_import(script)
+                if mod:
+                    modules.append(mod)
+            
+            return modules
+        
+        for script in scripts:
+            modules = find_modules_for_script(script)
+            if not modules:
+                if verbosity>0 and not silent:
+                    print ERROR("No module for script '%s' found" % script)
+            for mod in modules:
+                if verbosity>1:
+                    print NOTICE2("Running script '%s' ..." % mod.__name__)
+                run_script(mod)
+
+# Backwards compatibility for Django r9110
+if not [opt for opt in Command.option_list if opt.dest=='verbosity']:
+    Command.option_list += (
+        make_option('--verbosity', '-v', action="store", dest="verbosity",
+                    default='1', type='choice', choices=['0', '1', '2'],
+                    help="Verbosity level; 0=minimal output, 1=normal output, 2=all output"),
+    )