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


def vararg_callback(option, opt_str, opt_value, parser):
    parser.rargs.insert(0, opt_value)
    value = []
    for arg in parser.rargs:
        # stop on --foo like options
        if arg[:2] == "--" and len(arg) > 2:
            break
        # stop on -a like options
        if arg[:1] == "-":
            break
        value.append(arg)

    del parser.rargs[:len(value)]
    setattr(parser.values, option.dest, value)


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'),
        make_option('--script-args', action='callback', callback=vararg_callback, type='string',
            help='Space-separated argument list to be passed to the scripts. Note that the '
                 'same arguments will be passed to all named scripts.'),
    )
    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
        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, *script_args):
            try:
                mod.run(*script_args)
            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

        if options.get('script_args'):
            script_args = options['script_args']
        else:
            script_args = []
        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, *script_args)


# 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"),
    )

@@ -148,16 +148,27 @@
 mport os
+%0Aimport imp
 %0A%0Atry:%0A 
@@ -3223,33 +3223,486 @@
             
-try:%0A    
+# check if module exists before importing%0A            try:%0A                path = None%0A                full_path = mod.split('.')%0A                for package in mod.split('.')%5B:-1%5D:%0A                    module_tuple = imp.find_module(package, path)%0A                    path = imp.load_module(package, *module_tuple).__path__%0A                imp.find_module(mod.split('.')%5B-1%5D, path)%0A            except (ImportError, AttributeError):%0A                return False%0A%0A
             
@@ -3740,36 +3740,32 @@
 %22%5D)%0A            
- 
-   
 #if verbosity %3E 
@@ -3759,36 +3759,32 @@
  verbosity %3E 1:%0A
-    
             #   
@@ -3838,20 +3838,16 @@
         
-  
-  
 if hasat
@@ -3868,36 +3868,32 @@
                 
-    
 if verbosity %3E 1
@@ -3906,36 +3906,32 @@
                 
-   
- 
 print NOTICE2(%22F
@@ -3967,36 +3967,32 @@
                 
-    
 #if verbosity %3E 
@@ -3986,36 +3986,32 @@
  verbosity %3E 1:%0A
-    
                 
@@ -4081,28 +4081,24 @@
             
-    
 return t%0A   
@@ -4094,20 +4094,16 @@
 eturn t%0A
-    
         
@@ -4120,36 +4120,32 @@
                 
-    
 if verbosity %3E 1
@@ -4138,36 +4138,32 @@
  verbosity %3E 1:%0A
-    
                 
@@ -4237,69 +4237,8 @@
 mod)
-%0A            except ImportError:%0A                return False
 %0A%0A  

check if module exists before importing