comparison piecrust/main.py @ 583:1eda551ee681

cli: More proper argument parsing for the main/root arguments.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 30 Dec 2015 20:42:45 -0800
parents 42a5e78e782a
children 2edaefcb82cd
comparison
equal deleted inserted replaced
582:d8d9e0424a72 583:1eda551ee681
72 log_friendly_exception(logger, ex) 72 log_friendly_exception(logger, ex)
73 exit_code = 1 73 exit_code = 1
74 sys.exit(exit_code) 74 sys.exit(exit_code)
75 75
76 76
77 class PreParsedChefArgs(object): 77 def _setup_main_parser_arguments(parser):
78 def __init__(self, root=None, cache=True, debug=False, quiet=False, 78 parser.add_argument(
79 log_file=None, log_debug=False, config_variant=None): 79 '--version',
80 self.root = root 80 action='version',
81 self.cache = cache 81 version=('%(prog)s ' + APP_VERSION))
82 self.debug = debug 82 parser.add_argument(
83 self.quiet = quiet 83 '--root',
84 self.log_file = log_file 84 help="The root directory of the website.")
85 self.log_debug = log_debug 85 parser.add_argument(
86 self.config_variant = config_variant 86 '--config',
87 self.config_values = [] 87 dest='config_variant',
88 self.debug_only = [] 88 help="The configuration variant to use for this command.")
89 self.no_color = False 89 parser.add_argument(
90 90 '--config-set',
91 91 nargs='*',
92 def _parse_config_value(arg): 92 dest='config_values',
93 try: 93 help="Sets a specific site configuration setting.")
94 name, value = arg.split('=') 94 parser.add_argument(
95 except Exception: 95 '--debug',
96 raise Exception("Invalid configuration name and value: %s" % arg) 96 help="Show debug information.", action='store_true')
97 return (name, value) 97 parser.add_argument(
98 '--debug-only',
99 nargs='*',
100 help="Only show debug information for the given categories.")
101 parser.add_argument(
102 '--no-cache',
103 help="When applicable, disable caching.",
104 action='store_true')
105 parser.add_argument(
106 '--quiet',
107 help="Print only important information.",
108 action='store_true')
109 parser.add_argument(
110 '--log',
111 dest='log_file',
112 help="Send log messages to the specified file.")
113 parser.add_argument(
114 '--log-debug',
115 help="Log debug messages to the log file.",
116 action='store_true')
117 parser.add_argument(
118 '--no-color',
119 help="Don't use colorized output.",
120 action='store_true')
98 121
99 122
100 def _pre_parse_chef_args(argv): 123 def _pre_parse_chef_args(argv):
101 # We need to parse some arguments before we can build the actual argument 124 # We need to parse some arguments before we can build the actual argument
102 # parser, because it can affect which plugins will be loaded. Also, log- 125 # parser, because it can affect which plugins will be loaded. Also, log-
103 # related arguments must be parsed first because we want to log everything 126 # related arguments must be parsed first because we want to log everything
104 # from the beginning. 127 # from the beginning.
105 res = PreParsedChefArgs() 128 parser = argparse.ArgumentParser()
106 i = 0 129 _setup_main_parser_arguments(parser)
107 while i < len(argv): 130 parser.add_argument('args', nargs=argparse.REMAINDER)
108 arg = argv[i] 131 res, _ = parser.parse_known_args(argv)
109 if arg.startswith('--root='):
110 res.root = os.path.expanduser(arg[len('--root='):])
111 elif arg == '--root':
112 res.root = os.path.expanduser(argv[i + 1])
113 i += 1
114 elif arg.startswith('--config='):
115 res.config_variant = arg[len('--config='):]
116 elif arg == '--config':
117 res.config_variant = argv[i + 1]
118 i += 1
119 elif arg.startswith('--config-set='):
120 res.config_values.append(
121 _parse_config_value(arg[len('--config-set='):]))
122 elif arg == '--config-set':
123 res.config_values.append(_parse_config_value(argv[i + 1]))
124 i += 1
125 elif arg == '--log':
126 res.log_file = argv[i + 1]
127 i += 1
128 elif arg == '--log-debug':
129 res.log_debug = True
130 elif arg == '--debug-only':
131 res.debug_only.append(argv[i + 1])
132 i += 1
133 elif arg == '--no-cache':
134 res.cache = False
135 elif arg == '--debug':
136 res.debug = True
137 elif arg == '--quiet':
138 res.quiet = True
139 elif arg == '--no-color':
140 res.no_color = True
141 else:
142 break
143
144 i = i + 1
145 132
146 # Setup the logger. 133 # Setup the logger.
147 if res.debug and res.quiet: 134 if res.debug and res.quiet:
148 raise Exception("You can't specify both --debug and --quiet.") 135 raise Exception("You can't specify both --debug and --quiet.")
149 136
155 root_logger = logging.getLogger() 142 root_logger = logging.getLogger()
156 root_logger.setLevel(logging.INFO) 143 root_logger.setLevel(logging.INFO)
157 if res.debug or res.log_debug: 144 if res.debug or res.log_debug:
158 root_logger.setLevel(logging.DEBUG) 145 root_logger.setLevel(logging.DEBUG)
159 146
160 for n in res.debug_only: 147 if res.debug_only:
161 logging.getLogger(n).setLevel(logging.DEBUG) 148 for n in res.debug_only:
149 logging.getLogger(n).setLevel(logging.DEBUG)
162 150
163 log_handler = logging.StreamHandler(sys.stdout) 151 log_handler = logging.StreamHandler(sys.stdout)
164 if res.debug or res.debug_only: 152 if res.debug or res.debug_only:
165 log_handler.setLevel(logging.DEBUG) 153 log_handler.setLevel(logging.DEBUG)
166 log_handler.setFormatter(ColoredFormatter("[%(name)s] %(message)s")) 154 log_handler.setFormatter(ColoredFormatter("[%(name)s] %(message)s"))
182 170
183 171
184 def _run_chef(pre_args, argv): 172 def _run_chef(pre_args, argv):
185 # Setup the app. 173 # Setup the app.
186 start_time = time.perf_counter() 174 start_time = time.perf_counter()
187 root = pre_args.root 175 root = None
188 if root is None: 176 if pre_args.root:
177 root = os.path.expanduser(pre_args.root)
178 else:
189 try: 179 try:
190 root = find_app_root() 180 root = find_app_root()
191 except SiteNotFoundError: 181 except SiteNotFoundError:
192 root = None 182 root = None
193 183
194 if not root: 184 if not root:
195 app = NullPieCrust() 185 app = NullPieCrust()
196 else: 186 else:
197 app = PieCrust(root, cache=pre_args.cache, debug=pre_args.debug) 187 app = PieCrust(root, cache=(not pre_args.no_cache),
188 debug=pre_args.debug)
198 189
199 # Build a hash for a custom cache directory. 190 # Build a hash for a custom cache directory.
200 cache_key = 'default' 191 cache_key = 'default'
201 192
202 # Handle custom configurations. 193 # Handle custom configurations.
206 pre_args.config_values) 197 pre_args.config_values)
207 198
208 # Adjust the cache key. 199 # Adjust the cache key.
209 if pre_args.config_variant is not None: 200 if pre_args.config_variant is not None:
210 cache_key += ',variant=%s' % pre_args.config_variant 201 cache_key += ',variant=%s' % pre_args.config_variant
211 for name, value in pre_args.config_values: 202 if pre_args.config_values:
212 cache_key += ',%s=%s' % (name, value) 203 for name, value in pre_args.config_values:
204 cache_key += ',%s=%s' % (name, value)
213 205
214 # Setup the arg parser. 206 # Setup the arg parser.
215 parser = argparse.ArgumentParser( 207 parser = argparse.ArgumentParser(
216 prog='chef', 208 prog='chef',
217 description="The PieCrust chef manages your website.", 209 description="The PieCrust chef manages your website.",
218 formatter_class=argparse.RawDescriptionHelpFormatter) 210 formatter_class=argparse.RawDescriptionHelpFormatter)
219 parser.add_argument( 211 _setup_main_parser_arguments(parser)
220 '--version',
221 action='version',
222 version=('%(prog)s ' + APP_VERSION))
223 parser.add_argument(
224 '--root',
225 help="The root directory of the website.")
226 parser.add_argument(
227 '--config',
228 help="The configuration variant to use for this command.")
229 parser.add_argument(
230 '--config-set',
231 help="Sets a specific site configuration setting.")
232 parser.add_argument(
233 '--debug',
234 help="Show debug information.", action='store_true')
235 parser.add_argument(
236 '--debug-only',
237 help="Only show debug information for the given categories.")
238 parser.add_argument(
239 '--no-cache',
240 help="When applicable, disable caching.",
241 action='store_true')
242 parser.add_argument(
243 '--quiet',
244 help="Print only important information.",
245 action='store_true')
246 parser.add_argument(
247 '--log',
248 help="Send log messages to the specified file.")
249 parser.add_argument(
250 '--log-debug',
251 help="Log debug messages to the log file.",
252 action='store_true')
253 parser.add_argument(
254 '--no-color',
255 help="Don't use colorized output.",
256 action='store_true')
257 212
258 commands = sorted(app.plugin_loader.getCommands(), 213 commands = sorted(app.plugin_loader.getCommands(),
259 key=lambda c: c.name) 214 key=lambda c: c.name)
260 subparsers = parser.add_subparsers(title='list of commands') 215 subparsers = parser.add_subparsers(title='list of commands')
261 for c in commands: 216 for c in commands: