|
1 from django.core.management.base import BaseCommand |
|
2 from django.core.management.color import no_style |
|
3 from optparse import make_option |
|
4 import sys |
|
5 import os |
|
6 |
|
7 try: |
|
8 set |
|
9 except NameError: |
|
10 from sets import Set as set # Python 2.3 fallback |
|
11 |
|
12 class Command(BaseCommand): |
|
13 option_list = BaseCommand.option_list + ( |
|
14 make_option('--fixtures', action='store_true', dest='infixtures', default=False, |
|
15 help='Only look in app.fixtures subdir'), |
|
16 make_option('--noscripts', action='store_true', dest='noscripts', default=False, |
|
17 help='Look in app.scripts subdir'), |
|
18 make_option('-s', '--silent', action='store_true', dest='silent', default=False, |
|
19 help='Run silently, do not show errors and tracebacks'), |
|
20 make_option('--no-traceback', action='store_true', dest='no_traceback', default=False, |
|
21 help='Do not show tracebacks'), |
|
22 ) |
|
23 help = 'Runs a script in django context.' |
|
24 args = "script [script ...]" |
|
25 |
|
26 def handle(self, *scripts, **options): |
|
27 from django.db.models import get_apps |
|
28 |
|
29 NOTICE = self.style.SQL_TABLE |
|
30 NOTICE2 = self.style.SQL_FIELD |
|
31 ERROR = self.style.ERROR_OUTPUT |
|
32 ERROR2 = self.style.NOTICE |
|
33 |
|
34 subdirs = [] |
|
35 |
|
36 if not options.get('noscripts'): |
|
37 subdirs.append('scripts') |
|
38 if options.get('infixtures'): |
|
39 subdirs.append('fixtures') |
|
40 verbosity = int(options.get('verbosity', 1)) |
|
41 show_traceback = options.get('traceback', True) |
|
42 if show_traceback is None: |
|
43 # XXX: traceback is set to None from Django ? |
|
44 show_traceback = True |
|
45 no_traceback = options.get('no_traceback', False) |
|
46 if no_traceback: |
|
47 show_traceback = False |
|
48 silent = options.get('silent', False) |
|
49 if silent: |
|
50 verbosity = 0 |
|
51 |
|
52 if len(subdirs) < 1: |
|
53 print NOTICE("No subdirs to run left.") |
|
54 return |
|
55 |
|
56 if len(scripts) < 1: |
|
57 print ERROR("Script name required.") |
|
58 return |
|
59 |
|
60 def run_script(mod): |
|
61 # TODO: add arguments to run |
|
62 try: |
|
63 mod.run() |
|
64 except Exception, e: |
|
65 if silent: |
|
66 return |
|
67 if verbosity > 0: |
|
68 print ERROR("Exception while running run() in '%s'" % mod.__name__) |
|
69 if show_traceback: |
|
70 raise |
|
71 |
|
72 def my_import(mod): |
|
73 if verbosity > 1: |
|
74 print NOTICE("Check for %s" % mod) |
|
75 try: |
|
76 t = __import__(mod, [], [], [" "]) |
|
77 #if verbosity > 1: |
|
78 # print NOTICE("Found script %s ..." % mod) |
|
79 if hasattr(t, "run"): |
|
80 if verbosity > 1: |
|
81 print NOTICE2("Found script '%s' ..." % mod) |
|
82 #if verbosity > 1: |
|
83 # print NOTICE("found run() in %s. executing..." % mod) |
|
84 return t |
|
85 else: |
|
86 if verbosity > 1: |
|
87 print ERROR2("Find script '%s' but no run() function found." % mod) |
|
88 except ImportError: |
|
89 return False |
|
90 |
|
91 def find_modules_for_script(script): |
|
92 """ find script module which contains 'run' attribute """ |
|
93 modules = [] |
|
94 # first look in apps |
|
95 for app in get_apps(): |
|
96 app_name = app.__name__.split(".")[:-1] # + ['fixtures'] |
|
97 for subdir in subdirs: |
|
98 mod = my_import(".".join(app_name + [subdir, script])) |
|
99 if mod: |
|
100 modules.append(mod) |
|
101 |
|
102 # try app.DIR.script import |
|
103 sa = script.split(".") |
|
104 for subdir in subdirs: |
|
105 nn = ".".join(sa[:-1] + [subdir, sa[-1]]) |
|
106 mod = my_import(nn) |
|
107 if mod: |
|
108 modules.append(mod) |
|
109 |
|
110 # try direct import |
|
111 if script.find(".") != -1: |
|
112 mod = my_import(script) |
|
113 if mod: |
|
114 modules.append(mod) |
|
115 |
|
116 return modules |
|
117 |
|
118 for script in scripts: |
|
119 modules = find_modules_for_script(script) |
|
120 if not modules: |
|
121 if verbosity>0 and not silent: |
|
122 print ERROR("No module for script '%s' found" % script) |
|
123 for mod in modules: |
|
124 if verbosity>1: |
|
125 print NOTICE2("Running script '%s' ..." % mod.__name__) |
|
126 run_script(mod) |
|
127 |
|
128 # Backwards compatibility for Django r9110 |
|
129 if not [opt for opt in Command.option_list if opt.dest=='verbosity']: |
|
130 Command.option_list += ( |
|
131 make_option('--verbosity', '-v', action="store", dest="verbosity", |
|
132 default='1', type='choice', choices=['0', '1', '2'], |
|
133 help="Verbosity level; 0=minimal output, 1=normal output, 2=all output"), |
|
134 ) |