nubia/internal/registry_tools.py (87 lines of code) (raw):

#!/usr/bin/env python3 # Copyright (c) Facebook, Inc. and its affiliates. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. # import json import logging from argparse import _SubParsersAction from nubia.internal.typing import Command, FunctionInspection from nubia.internal.typing.argparse import transform_argument_name logger = logging.getLogger(__name__) def _dump_command(cmd): assert isinstance(cmd, Command) return { # We can also add cmd.help if needed in the future "name": cmd.name } def _dump_arguments(arguments): output = {"options": [], "positionals": []} for arg in arguments.values(): if arg.positional: output["positionals"].append( { "name": transform_argument_name(arg.name), "values": list(arg.choices) if arg.choices else None, } ) else: output["options"].append( { "name": transform_argument_name(arg.name), "extra_names": list(map(transform_argument_name, arg.extra_names)), "expects_argument": not ( arg.type == bool or arg.default_value is False ), "default": arg.default_value, "required": not arg.default_value_set, "values": list(arg.choices) if arg.choices else None, } ) return output def _dump_subcommands(subcommands): return [_fn_to_dict(cmd) for _, cmd in subcommands] def _dump_opts_parser_common(opts_parser, plugin): output = [] top_level_actions = [ action for action in opts_parser._actions if not isinstance(action, _SubParsersAction) ] for action in top_level_actions: option = {"extra_names": []} for name in action.option_strings: if name.startswith(opts_parser.prefix_chars * 2): option["name"] = name elif name.startswith(opts_parser.prefix_chars): option["extra_names"].append(name) else: # we don't know what that is! logger.warning( "We found '%s' in option_strings of action %s", name, action ) # we want to skip this particular one since it's hidden if option.get("name", "").startswith("--_"): continue option["expects_argument"] = True if action.type is not None else False option_name = option.get("name") if option_name: ds = plugin.get_completion_datasource_for_global_argument(option_name) if ds: option["values"] = ds.get_all() output.append(option) return output def _fn_to_dict(inspection): cmd = _dump_command(inspection.command) cmd.update(_dump_arguments(inspection.arguments)) if inspection.subcommands: cmd["commands"] = _dump_subcommands(inspection.subcommands) return cmd def export_registry(plugin, args, opts_parser, registry): cmds = registry.get_all_commands() commands = [] for cmd in cmds: if cmd.built_in: continue inspection = cmd.metadata if isinstance(inspection, FunctionInspection): commands.append(_fn_to_dict(inspection)) else: logger.warning("Command %s is not instance of FunctionInspection", cmd) model = { "commands": commands, # This will include the shell top-level options, this will be included # in a future diff "options": _dump_opts_parser_common(opts_parser, plugin), } return json.dumps(model)