Mercurial > kallithea
comparison rhodecode/lib/dbmigrate/migrate/versioning/shell.py @ 833:9753e0907827 beta
added dbmigrate package, added model changes
moved out upgrade db command to that package
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sat, 11 Dec 2010 01:54:12 +0100 |
parents | |
children | 08d2dcd71666 |
comparison
equal
deleted
inserted
replaced
832:634596f81cfd | 833:9753e0907827 |
---|---|
1 #!/usr/bin/env python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 """The migrate command-line tool.""" | |
5 | |
6 import sys | |
7 import inspect | |
8 import logging | |
9 from optparse import OptionParser, BadOptionError | |
10 | |
11 from migrate import exceptions | |
12 from migrate.versioning import api | |
13 from migrate.versioning.config import * | |
14 from migrate.versioning.util import asbool | |
15 | |
16 | |
17 alias = dict( | |
18 s=api.script, | |
19 vc=api.version_control, | |
20 dbv=api.db_version, | |
21 v=api.version, | |
22 ) | |
23 | |
24 def alias_setup(): | |
25 global alias | |
26 for key, val in alias.iteritems(): | |
27 setattr(api, key, val) | |
28 alias_setup() | |
29 | |
30 | |
31 class PassiveOptionParser(OptionParser): | |
32 | |
33 def _process_args(self, largs, rargs, values): | |
34 """little hack to support all --some_option=value parameters""" | |
35 | |
36 while rargs: | |
37 arg = rargs[0] | |
38 if arg == "--": | |
39 del rargs[0] | |
40 return | |
41 elif arg[0:2] == "--": | |
42 # if parser does not know about the option | |
43 # pass it along (make it anonymous) | |
44 try: | |
45 opt = arg.split('=', 1)[0] | |
46 self._match_long_opt(opt) | |
47 except BadOptionError: | |
48 largs.append(arg) | |
49 del rargs[0] | |
50 else: | |
51 self._process_long_opt(rargs, values) | |
52 elif arg[:1] == "-" and len(arg) > 1: | |
53 self._process_short_opts(rargs, values) | |
54 elif self.allow_interspersed_args: | |
55 largs.append(arg) | |
56 del rargs[0] | |
57 | |
58 def main(argv=None, **kwargs): | |
59 """Shell interface to :mod:`migrate.versioning.api`. | |
60 | |
61 kwargs are default options that can be overriden with passing | |
62 --some_option as command line option | |
63 | |
64 :param disable_logging: Let migrate configure logging | |
65 :type disable_logging: bool | |
66 """ | |
67 if argv is not None: | |
68 argv = argv | |
69 else: | |
70 argv = list(sys.argv[1:]) | |
71 commands = list(api.__all__) | |
72 commands.sort() | |
73 | |
74 usage = """%%prog COMMAND ... | |
75 | |
76 Available commands: | |
77 %s | |
78 | |
79 Enter "%%prog help COMMAND" for information on a particular command. | |
80 """ % '\n\t'.join(["%s - %s" % (command.ljust(28), | |
81 api.command_desc.get(command)) for command in commands]) | |
82 | |
83 parser = PassiveOptionParser(usage=usage) | |
84 parser.add_option("-d", "--debug", | |
85 action="store_true", | |
86 dest="debug", | |
87 default=False, | |
88 help="Shortcut to turn on DEBUG mode for logging") | |
89 parser.add_option("-q", "--disable_logging", | |
90 action="store_true", | |
91 dest="disable_logging", | |
92 default=False, | |
93 help="Use this option to disable logging configuration") | |
94 help_commands = ['help', '-h', '--help'] | |
95 HELP = False | |
96 | |
97 try: | |
98 command = argv.pop(0) | |
99 if command in help_commands: | |
100 HELP = True | |
101 command = argv.pop(0) | |
102 except IndexError: | |
103 parser.print_help() | |
104 return | |
105 | |
106 command_func = getattr(api, command, None) | |
107 if command_func is None or command.startswith('_'): | |
108 parser.error("Invalid command %s" % command) | |
109 | |
110 parser.set_usage(inspect.getdoc(command_func)) | |
111 f_args, f_varargs, f_kwargs, f_defaults = inspect.getargspec(command_func) | |
112 for arg in f_args: | |
113 parser.add_option( | |
114 "--%s" % arg, | |
115 dest=arg, | |
116 action='store', | |
117 type="string") | |
118 | |
119 # display help of the current command | |
120 if HELP: | |
121 parser.print_help() | |
122 return | |
123 | |
124 options, args = parser.parse_args(argv) | |
125 | |
126 # override kwargs with anonymous parameters | |
127 override_kwargs = dict() | |
128 for arg in list(args): | |
129 if arg.startswith('--'): | |
130 args.remove(arg) | |
131 if '=' in arg: | |
132 opt, value = arg[2:].split('=', 1) | |
133 else: | |
134 opt = arg[2:] | |
135 value = True | |
136 override_kwargs[opt] = value | |
137 | |
138 # override kwargs with options if user is overwriting | |
139 for key, value in options.__dict__.iteritems(): | |
140 if value is not None: | |
141 override_kwargs[key] = value | |
142 | |
143 # arguments that function accepts without passed kwargs | |
144 f_required = list(f_args) | |
145 candidates = dict(kwargs) | |
146 candidates.update(override_kwargs) | |
147 for key, value in candidates.iteritems(): | |
148 if key in f_args: | |
149 f_required.remove(key) | |
150 | |
151 # map function arguments to parsed arguments | |
152 for arg in args: | |
153 try: | |
154 kw = f_required.pop(0) | |
155 except IndexError: | |
156 parser.error("Too many arguments for command %s: %s" % (command, | |
157 arg)) | |
158 kwargs[kw] = arg | |
159 | |
160 # apply overrides | |
161 kwargs.update(override_kwargs) | |
162 | |
163 # configure options | |
164 for key, value in options.__dict__.iteritems(): | |
165 kwargs.setdefault(key, value) | |
166 | |
167 # configure logging | |
168 if not asbool(kwargs.pop('disable_logging', False)): | |
169 # filter to log =< INFO into stdout and rest to stderr | |
170 class SingleLevelFilter(logging.Filter): | |
171 def __init__(self, min=None, max=None): | |
172 self.min = min or 0 | |
173 self.max = max or 100 | |
174 | |
175 def filter(self, record): | |
176 return self.min <= record.levelno <= self.max | |
177 | |
178 logger = logging.getLogger() | |
179 h1 = logging.StreamHandler(sys.stdout) | |
180 f1 = SingleLevelFilter(max=logging.INFO) | |
181 h1.addFilter(f1) | |
182 h2 = logging.StreamHandler(sys.stderr) | |
183 f2 = SingleLevelFilter(min=logging.WARN) | |
184 h2.addFilter(f2) | |
185 logger.addHandler(h1) | |
186 logger.addHandler(h2) | |
187 | |
188 if options.debug: | |
189 logger.setLevel(logging.DEBUG) | |
190 else: | |
191 logger.setLevel(logging.INFO) | |
192 | |
193 log = logging.getLogger(__name__) | |
194 | |
195 # check if all args are given | |
196 try: | |
197 num_defaults = len(f_defaults) | |
198 except TypeError: | |
199 num_defaults = 0 | |
200 f_args_default = f_args[len(f_args) - num_defaults:] | |
201 required = list(set(f_required) - set(f_args_default)) | |
202 if required: | |
203 parser.error("Not enough arguments for command %s: %s not specified" \ | |
204 % (command, ', '.join(required))) | |
205 | |
206 # handle command | |
207 try: | |
208 ret = command_func(**kwargs) | |
209 if ret is not None: | |
210 log.info(ret) | |
211 except (exceptions.UsageError, exceptions.KnownError), e: | |
212 parser.error(e.args[0]) | |
213 | |
214 if __name__ == "__main__": | |
215 main() |