def validate_unknown_args(unknown: List[str]) -> Dict[str, Any]: """Convert a list of strings into a dict of valid kwargs for add_* methods. Will exit program if any of the arguments are unrecognized, or are malformed. Converts string to python type using literal_eval. Parameters ---------- unknown : List[str] a list of strings gathered as "unknown" arguments in argparse. Returns ------- kwargs : Dict[str, Any] {key: val} dict suitable for the viewer.add_* methods where ``val`` is a ``literal_eval`` result, or string. """ from napari.components.viewer_model import valid_add_kwargs out: Dict[str, Any] = dict() valid = set.union(*valid_add_kwargs().values()) for i, arg in enumerate(unknown): if not arg.startswith("--"): continue if "=" in arg: key, value = arg.split("=", maxsplit=1) else: key = arg key = key.lstrip('-').replace("-", "_") if key not in valid: sys.exit(f"error: unrecognized arguments: {arg}") if "=" not in arg: try: value = unknown[i + 1] if value.startswith("--"): raise IndexError() except IndexError: sys.exit(f"error: argument {arg} expected one argument") try: value = literal_eval(value) except Exception: value = value out[key] = value return out
def parse_sys_argv(): """Parse command line arguments.""" kwarg_options = [] for layer_type, keys in valid_add_kwargs().items(): kwarg_options.append(f" {layer_type.title()}:") keys = {k.replace('_', '-') for k in keys} lines = wrap(", ".join(sorted(keys)), break_on_hyphens=False) kwarg_options.extend([f" {line}" for line in lines]) parser = argparse.ArgumentParser( usage=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, epilog="optional layer-type-specific arguments (precede with '--'):\n" + "\n".join(kwarg_options), ) parser.add_argument('paths', nargs='*', help='path(s) to view.') parser.add_argument( '-v', '--verbose', action='count', default=0, help="increase output verbosity", ) parser.add_argument( '-w', '--with', dest='with_', nargs='+', metavar=('PLUGIN_NAME', 'WIDGET_NAME'), help=( "open napari with dock widget from specified plugin name." "(If plugin provides multiple dock widgets, widget name must also " "be provided)" ), ) parser.add_argument( '--version', action='version', version=f'napari version {__version__}', ) parser.add_argument( '--info', action=InfoAction, nargs=0, help='show system information and exit', ) parser.add_argument( '--plugin-info', action=PluginInfoAction, nargs=0, help='show information about plugins and exit', ) parser.add_argument( '--citation', action=CitationAction, nargs=0, help='show citation information and exit', ) parser.add_argument( '--stack', action='store_true', help='concatenate multiple input files into a single stack.', ) parser.add_argument( '--plugin', help='specify plugin name when opening a file', ) parser.add_argument( '--layer-type', metavar="TYPE", choices=set(layers.NAMES), help=( 'force file to be interpreted as a specific layer type. ' f'one of {set(layers.NAMES)}' ), ) parser.add_argument( '--reset', action='store_true', help='reset settings to default values.', ) args, unknown = parser.parse_known_args() # this is a hack to allow using "=" as a key=value separator while also # allowing nargs='*' on the "paths" argument... for idx, item in enumerate(reversed(args.paths)): if item.startswith("--"): unknown.append(args.paths.pop(len(args.paths) - idx - 1)) kwargs = validate_unknown_args(unknown) if unknown else {} return args, kwargs