def parse_args(argv): # The prog='west' override avoids the absolute path of the main.py script # showing up when West is run via the wrapper west_parser = argparse.ArgumentParser( prog='west', description='The Zephyr RTOS meta-tool.', epilog='Run "west <command> -h" for help on each command.') # Remember to update scripts/west-completion.bash if you add or remove # flags west_parser.add_argument('-z', '--zephyr-base', default=None, help='''Override the Zephyr base directory. The default is the manifest project with path "zephyr".''') west_parser.add_argument('-v', '--verbose', default=0, action='count', help='''Display verbose output. May be given multiple times to increase verbosity.''') west_parser.add_argument('-V', '--version', action='store_true') subparser_gen = west_parser.add_subparsers(title='commands', dest='command') for command in COMMANDS: parser = command.add_parser(subparser_gen) parser.set_defaults(handler=partial(command_handler, command)) args, unknown = west_parser.parse_known_args(args=argv) if args.version: print_version_info() sys.exit(0) # Set up logging verbosity before doing anything else, so # e.g. verbose messages related to argument handling errors # work properly. log.set_verbosity(args.verbose) if IN_MULTIREPO_INSTALL: set_zephyr_base(args) if 'handler' not in args: log.err('west installation found (in {}), but no command given'.format( west_dir()), fatal=True) west_parser.print_help(file=sys.stderr) sys.exit(1) return args, unknown
def parse_args(argv, extensions, topdir): west_parser, subparser_gen = _make_parsers() # Add handlers for the built-in commands. for command in itertools.chain(*BUILTIN_COMMANDS.values()): parser = command.add_parser(subparser_gen) parser.set_defaults(handler=partial(command_handler, command, topdir)) # Add handlers for extension commands, and finalize the list with # our parser. if extensions: for path, specs in extensions.items(): for spec in specs: parser = add_ext_command_parser(subparser_gen, spec) parser.set_defaults( handler=partial(ext_command_handler, spec, topdir, argv)) west_parser.set_extensions(extensions) help_parser = subparser_gen.add_parser('help', help='get help on a west command') help_parser.add_argument('command', nargs='?') help_parser.set_defaults(handler=partial(help_command_handler, west_parser, topdir, help_parser, extensions)) # Parse arguments. args, unknown = west_parser.parse_known_args(args=argv) if args.version: print('West version: v{}'.format(__version__)) sys.exit(0) # Set up logging verbosity before running the command, so # e.g. verbose messages related to argument handling errors work # properly. This works even for extension commands that haven't # been instantiated yet, because --verbose is an option to the top # level parser, and the command run() method doesn't get called # until later. log.set_verbosity(args.verbose) if args.command != 'init': # init --> we haven't got a zephyr repo. set_zephyr_base(args) if 'handler' not in args: west_parser.print_help(file=sys.stderr, top_level=True) sys.exit(1) return args, unknown
def parse_args(argv): # The prog='west' override avoids the absolute path of the main.py script # showing up when West is run via the wrapper west_parser = argparse.ArgumentParser( prog='west', description='The Zephyr RTOS meta-tool.', epilog='Run "west <command> -h" for help on each command.') west_parser.add_argument('-z', '--zephyr-base', default=None, help='''Path to the Zephyr base directory. If not given, ZEPHYR_BASE must be defined in the environment, and will be used instead.''') west_parser.add_argument('-v', '--verbose', default=0, action='count', help='''Display verbose output. May be given multiple times to increase verbosity.''') west_parser.add_argument('-V', '--version', action='store_true') subparser_gen = west_parser.add_subparsers(title='commands', dest='command') for command in COMMANDS: parser = command.add_parser(subparser_gen) parser.set_defaults(handler=partial(command_handler, command)) args, unknown = west_parser.parse_known_args(args=argv) if args.version: print_version_info() sys.exit(0) # Set up logging verbosity before doing anything else, so # e.g. verbose messages related to argument handling errors # work properly. log.set_verbosity(args.verbose) if IN_MULTIREPO_INSTALL: set_zephyr_base(args) if 'handler' not in args: log.err('you must specify a command', fatal=True) west_parser.print_usage(file=sys.stderr) sys.exit(1) return args, unknown
def run_command(self, argv): # Parse command line arguments and run the WestCommand. # If we're running an extension, instantiate it from its # spec and re-parse arguments before running. args, unknown = self.west_parser.parse_known_args(args=argv) # Set up logging verbosity before running the command, so e.g. # verbose messages related to argument handling errors work # properly. self.setup_logging(args) log.set_verbosity(args.verbose) log.dbg('args namespace:', args, level=log.VERBOSE_EXTREME) # If we were run as 'west -h ...' or 'west --help ...', # monkeypatch the args namespace so we end up running Help. The # user might have also provided a command. If so, print help about # that command. if args.help or args.command is None: args.command_name = args.command args.command = 'help' # Finally, run the command. try: if args.command in self.builtins: if self.mle: self.handle_builtin_manifest_load_err(args) cmd = self.builtins.get(args.command, self.builtins['help']) cmd.run(args, unknown, self.topdir, manifest=self.manifest) else: self.run_extension(args.command, argv) except KeyboardInterrupt: sys.exit(0) except BrokenPipeError: sys.exit(0) except CalledProcessError as cpe: log.err( f'command exited with status {cpe.returncode}: ' f'{quote_sh_list(cpe.cmd)}', fatal=True) if args.verbose >= log.VERBOSE_EXTREME: log.banner('Traceback (enabled by -vvv):') traceback.print_exc() sys.exit(cpe.returncode) except ExtensionCommandError as ece: msg = f"extension command \"{args.command}\" couldn't be run" if ece.hint: msg += '\n Hint: ' + ece.hint if args.verbose >= log.VERBOSE_EXTREME: log.err(msg, fatal=True) log.banner('Traceback (enabled by -vvv):') traceback.print_exc() else: tb_file = dump_traceback() msg += f'\n See {tb_file} for a traceback.' log.err(msg, fatal=True) sys.exit(ece.returncode) except CommandError as ce: # No need to dump_traceback() here. The command is responsible # for logging its own errors. sys.exit(ce.returncode)
def main(argv=None): # Silence validation errors from pykwalify, which are logged at # logging.ERROR level. We want to handle those ourselves as # needed. logging.getLogger('pykwalify').setLevel(logging.CRITICAL) # Makes ANSI color escapes work on Windows, and strips them when # stdout/stderr isn't a terminal colorama.init() # See if we're in an installation. try: topdir = west_topdir() except WestNotFound: topdir = None # Read the configuration files before looking for extensions. # We need this to find the manifest path in order to load extensions. config.read_config(topdir=topdir) # Parse the manifest and create extension command thunks. We'll # pass the saved manifest around so it doesn't have to be # re-parsed. mve = None if topdir: try: manifest = Manifest.from_file(topdir=topdir) extensions = get_extension_commands(manifest) except (MalformedManifest, MalformedConfig, FileNotFoundError, ManifestVersionError) as e: manifest = None extensions = None if isinstance(e, ManifestVersionError): mve = e else: manifest = None extensions = {} # Create the initial set of parsers. We'll need to re-create these # if we're running an extension command. Register extensions with # the parser. if argv is None: argv = sys.argv[1:] west_parser, subparser_gen = _make_parsers() west_parser.west_extensions = extensions west_parser.mve = mve # Cache the parser in the global Help instance. Dirty, but it # needs this data as its parser attribute is not the parent # parser, but the return value of a subparser_gen. BUILTIN_COMMANDS['help'].west_parser = west_parser # Add sub-parsers for the built-in commands. for command in BUILTIN_COMMANDS.values(): command.add_parser(subparser_gen) # Add stub parsers for extensions. # # These just reserve the names of each extension. The real parser # for each extension can't be added until we import the # extension's code, which we won't do unless parse_known_args() # says to run that extension. extensions_by_name = {} if extensions: for path, specs in extensions.items(): for spec in specs: subparser_gen.add_parser(spec.name, add_help=False) extensions_by_name[spec.name] = spec # Parse arguments for the first time. We'll need to do this again # if we're running an extension. args, unknown = west_parser.parse_known_args(args=argv) # Set up logging verbosity before running the command, so # e.g. verbose messages related to argument handling errors work # properly. This works even for extension commands that haven't # been instantiated yet, because --verbose is an option to the top # level parser, and the command run() method doesn't get called # until later. log.set_verbosity(args.verbose) log.dbg('args namespace:', args, level=log.VERBOSE_EXTREME) # Try to set ZEPHYR_BASE. It would be nice to get rid of this # someday and just have extensions that need it set this variable. if args.command and args.command not in ['init', 'help'] and not args.help: set_zephyr_base(args) # If we were run as 'west -h ...' or 'west --help ...', # monkeypatch the args namespace so we end up running Help. The # user might have also provided a command. If so, print help about # that command. if args.help or args.command is None: args.command_name = args.command args.command = 'help' # Finally, run the command. try: if args.command in extensions_by_name: # Check a program invariant. We should never get here # unless we were able to parse the manifest. That's where # information about extensions is gained. assert mve is None, \ 'internal error: running extension "{}" ' \ 'but got ManifestVersionError'.format(args.command) # This does not return. get_extension_commands() ensures # that extensions do not shadow built-in command names, so # checking this first is safe. run_extension(extensions_by_name[args.command], topdir, argv, manifest) else: if mve: if args.command == 'help': log.wrn( _mve_msg(mve, suggest_ugprade=False) + '\n Cannot get extension command help, ' + "and most commands won't run." + '\n To silence this warning, upgrade west.') elif args.command in ['config', 'topdir']: # config and topdir are safe to run, but let's # warn the user that most other commands won't be. log.wrn( _mve_msg(mve, suggest_ugprade=False) + "\n This should work, but most commands won't." + '\n To silence this warning, upgrade west.') elif args.command != 'init': log.die(_mve_msg(mve)) cmd = BUILTIN_COMMANDS.get(args.command, BUILTIN_COMMANDS['help']) cmd.run(args, unknown, topdir, manifest=manifest) except KeyboardInterrupt: sys.exit(0) except BrokenPipeError: sys.exit(0) except CalledProcessError as cpe: log.err('command exited with status {}: {}'.format( cpe.returncode, quote_sh_list(cpe.cmd))) if args.verbose: traceback.print_exc() sys.exit(cpe.returncode) except ExtensionCommandError as ece: msg = 'extension command "{}" could not be run{}.'.format( args.command, ': ' + ece.hint if ece.hint else '') if args.verbose: log.err(msg) traceback.print_exc() else: log.err(msg, 'See {} for a traceback.'.format(dump_traceback())) sys.exit(ece.returncode) except CommandContextError as cce: log.err('command', args.command, 'cannot be run in this context:', *cce.args) log.err('see {} for a traceback.'.format(dump_traceback())) sys.exit(cce.returncode) except CommandError as ce: # No need to dump_traceback() here. The command is responsible # for logging its own errors. sys.exit(ce.returncode) except (MalformedManifest, MalformedConfig) as malformed: log.die('\n '.join(["can't load west manifest"] + list(malformed.args)))
def parse_args(argv, externals): # The prog='west' override avoids the absolute path of the main.py script # showing up when West is run via the wrapper west_parser = WestArgumentParser( prog='west', description='The Zephyr RTOS meta-tool.', epilog='Run "west <command> -h" for detailed help on each command.', add_help=False) # Remember to update scripts/west-completion.bash if you add or remove # flags west_parser.add_argument('-h', '--help', action=WestHelpAction, help='show this help message and exit') west_parser.add_argument('-z', '--zephyr-base', default=None, help='''Override the Zephyr base directory. The default is the manifest project with path "zephyr".''') west_parser.add_argument('-v', '--verbose', default=0, action='count', help='''Display verbose output. May be given multiple times to increase verbosity.''') west_parser.add_argument('-V', '--version', action='store_true', help='print the program version and exit') subparser_gen = west_parser.add_subparsers(metavar='<command>', dest='command') # Add handlers for the built-in commands. for command in itertools.chain(*BUILTIN_COMMANDS.values()): parser = command.add_parser(subparser_gen) parser.set_defaults(handler=partial(command_handler, command)) # Add handlers for external commands, and finalize the list with # our parser. if externals: for path, specs in externals.items(): for spec in specs: parser = add_ext_command_parser(subparser_gen, spec) parser.set_defaults(handler=partial(ext_command_handler, subparser_gen, spec, argv)) west_parser.set_externals(externals) # Parse arguments. args, unknown = west_parser.parse_known_args(args=argv) if args.version: print_version_info() sys.exit(0) # Set up logging verbosity before running the command, so # e.g. verbose messages related to argument handling errors work # properly. This works even for external commands that haven't # been instantiated yet, because --verbose is an option to the top # level parser, and the command run() method doesn't get called # until later. log.set_verbosity(args.verbose) set_zephyr_base(args) if 'handler' not in args: west_parser.print_help(file=sys.stderr, top_level=True) sys.exit(1) return args, unknown