| import argparse | 
 | import os | 
 | import json | 
 | import sys | 
 |  | 
 | from tools import localpaths | 
 |  | 
 | from six import iteritems | 
 | from . import virtualenv | 
 |  | 
 |  | 
 | here = os.path.dirname(__file__) | 
 | wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir)) | 
 |  | 
 |  | 
 | def load_commands(): | 
 |     rv = {} | 
 |     with open(os.path.join(here, "paths"), "r") as f: | 
 |         paths = [item.strip().replace("/", os.path.sep) for item in f if item.strip()] | 
 |     for path in paths: | 
 |         abs_path = os.path.join(wpt_root, path, "commands.json") | 
 |         base_dir = os.path.dirname(abs_path) | 
 |         with open(abs_path, "r") as f: | 
 |             data = json.load(f) | 
 |             for command, props in iteritems(data): | 
 |                 assert "path" in props | 
 |                 assert "script" in props | 
 |                 rv[command] = { | 
 |                     "path": os.path.join(base_dir, props["path"]), | 
 |                     "script": props["script"], | 
 |                     "parser": props.get("parser"), | 
 |                     "parse_known": props.get("parse_known", False), | 
 |                     "help": props.get("help"), | 
 |                     "virtualenv": props.get("virtualenv", True), | 
 |                     "install": props.get("install", []), | 
 |                     "requirements": [os.path.join(base_dir, item) | 
 |                                      for item in props.get("requirements", [])] | 
 |                 } | 
 |     return rv | 
 |  | 
 |  | 
 | def parse_args(argv, commands): | 
 |     parser = argparse.ArgumentParser() | 
 |     parser.add_argument("--venv", action="store", help="Path to an existing virtualenv to use") | 
 |     parser.add_argument("--debug", action="store_true", help="Run the debugger in case of an exception") | 
 |     subparsers = parser.add_subparsers(dest="command") | 
 |     for command, props in iteritems(commands): | 
 |         sub_parser = subparsers.add_parser(command, help=props["help"], add_help=False) | 
 |  | 
 |     args, extra = parser.parse_known_args(argv) | 
 |  | 
 |     return args, extra | 
 |  | 
 |  | 
 | def import_command(prog, command, props): | 
 |     # This currently requires the path to be a module, | 
 |     # which probably isn't ideal but it means that relative | 
 |     # imports inside the script work | 
 |     rel_path = os.path.relpath(props["path"], wpt_root) | 
 |  | 
 |     parts = os.path.splitext(rel_path)[0].split(os.path.sep) | 
 |  | 
 |     mod_name = ".".join(parts) | 
 |  | 
 |     mod = __import__(mod_name) | 
 |     for part in parts[1:]: | 
 |         mod = getattr(mod, part) | 
 |  | 
 |     script = getattr(mod, props["script"]) | 
 |     if props["parser"] is not None: | 
 |         parser = getattr(mod, props["parser"])() | 
 |         parser.prog = "%s %s" % (os.path.basename(prog), command) | 
 |     else: | 
 |         parser = None | 
 |  | 
 |     return script, parser | 
 |  | 
 |  | 
 | def setup_virtualenv(path, props): | 
 |     if path is None: | 
 |         path = os.path.join(wpt_root, "_venv") | 
 |     venv = virtualenv.Virtualenv(path) | 
 |     venv.start() | 
 |     for name in props["install"]: | 
 |         venv.install(name) | 
 |     for path in props["requirements"]: | 
 |         venv.install_requirements(path) | 
 |     return venv | 
 |  | 
 |  | 
 | def main(prog=None, argv=None): | 
 |     if prog is None: | 
 |         prog = sys.argv[0] | 
 |     if argv is None: | 
 |         argv = sys.argv[1:] | 
 |  | 
 |     commands = load_commands() | 
 |  | 
 |     main_args, command_args = parse_args(argv, commands) | 
 |  | 
 |     if not(len(argv) and argv[0] in commands): | 
 |         sys.exit(1) | 
 |  | 
 |     command = main_args.command | 
 |     props = commands[command] | 
 |     venv = None | 
 |     if props["virtualenv"]: | 
 |         venv = setup_virtualenv(main_args.venv, props) | 
 |     script, parser = import_command(prog, command, props) | 
 |     if parser: | 
 |         if props["parse_known"]: | 
 |             kwargs, extras = parser.parse_known_args(command_args) | 
 |             extras = (extras,) | 
 |             kwargs = vars(kwargs) | 
 |         else: | 
 |             extras = () | 
 |             kwargs = vars(parser.parse_args(command_args)) | 
 |     else: | 
 |         extras = () | 
 |         kwargs = {} | 
 |  | 
 |     if venv is not None: | 
 |         args = (venv,) + extras | 
 |     else: | 
 |         args = extras | 
 |  | 
 |     if script: | 
 |         try: | 
 |             rv = script(*args, **kwargs) | 
 |             if rv is not None: | 
 |                 sys.exit(int(rv)) | 
 |         except Exception: | 
 |             if main_args.debug: | 
 |                 import pdb | 
 |                 pdb.post_mortem() | 
 |             else: | 
 |                 raise | 
 |     sys.exit(0) | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     main() |