azdev/operations/command_change/custom.py (206 lines of code) (raw):

# ----------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for # license information. # ----------------------------------------------------------------------------- from enum import Enum from knack.log import get_logger from .util import get_command_tree logger = get_logger(__name__) STORED_DEPRECATION_KEY = ["expiration", "target", "redirect", "hide"] class DiffExportFormat(Enum): DICT = "dict" TEXT = "text" TREE = "tree" def process_aaz_argument(az_arguments_schema, argument_settings, para): from azure.cli.core.aaz import has_value # pylint: disable=import-error _fields = az_arguments_schema._fields # pylint: disable=protected-access aaz_type = _fields.get(argument_settings["dest"], None) if aaz_type: para["aaz_type"] = aaz_type.__class__.__name__ if aaz_type._type_in_help and aaz_type._type_in_help.lower() != "undefined": # pylint: disable=protected-access para["type"] = aaz_type._type_in_help # pylint: disable=protected-access if has_value(aaz_type._default): # pylint: disable=protected-access para["aaz_default"] = aaz_type._default # pylint: disable=protected-access if para["aaz_type"] in ["AAZArgEnum"] and aaz_type.get("enum", None) and aaz_type.enum.get("items", None): para["aaz_choices"] = aaz_type.enum["items"] def process_arg_options(argument_settings, para): para["options"] = [] if not argument_settings.get("options_list", None): return raw_options_list = argument_settings["options_list"] option_list = set() for opt in raw_options_list: opt_type = opt.__class__.__name__ if opt_type == "str": option_list.add(opt) elif opt_type == "Deprecated": if hasattr(opt, "hide") and opt.hide: continue if hasattr(opt, "target"): option_list.add(opt.target) else: logger.warning("Unsupported option type: %i", opt_type) para["options"] = sorted(option_list) def process_arg_options_deprecation(argument_settings, para): if not argument_settings.get("options_list", None): return raw_options_list = argument_settings["options_list"] option_deprecation_list = [] for opt in raw_options_list: opt_type = opt.__class__.__name__ if opt_type != "Deprecated": continue opt_deprecation = {} for info_key in STORED_DEPRECATION_KEY: if hasattr(opt, info_key) and getattr(opt, info_key): opt_deprecation[info_key] = getattr(opt, info_key) option_deprecation_list.append(opt_deprecation) if len(option_deprecation_list) != 0: para["options_deprecate_info"] = option_deprecation_list def process_arg_deprecation(argument_settings, para): if argument_settings.get("deprecate_info", None) is None: return for info_key in STORED_DEPRECATION_KEY: if hasattr(argument_settings["deprecate_info"], info_key) and \ getattr(argument_settings["deprecate_info"], info_key): if para.get("deprecate_info", None) is None: para["deprecate_info"] = {} para["deprecate_info"][info_key] = getattr(argument_settings["deprecate_info"], info_key) def process_arg_type(argument_settings, para): if not argument_settings.get("type", None): return configured_type = argument_settings["type"] raw_type = None if hasattr(configured_type, "__name__"): raw_type = configured_type.__name__ elif hasattr(configured_type, "__class__"): raw_type = configured_type.__class__.__name__ else: print("unsupported type", configured_type) return para["type"] = raw_type if raw_type in ["str", "int", "float", "bool", "file_type"] else "custom_type" def normalize_para_types(para): type_string_opts = ["string", "str", "aazstrarg", "aazresourcelocationarg", "aazresourcegroupnamearg", "aazresourceidarg", "aazpaginationtokenarg", "aazfilearg"] type_int_opts = ["int", "aazintarg", "aazpaginationlimitarg"] type_float_opts = ["float", "aazfloatarg"] type_bool_opts = ["boolean", "bool", "aazboolarg", "aazgenericupdateforcestringarg"] def normalize_para_type(type_opts, value): if para.get("type", None) and para["type"].lower() in type_opts: para["type"] = value if para.get("aaz_type", None) and para["aaz_type"].lower() in type_opts: para["aaz_type"] = value normalize_para_type(type_string_opts, "string") normalize_para_type(type_int_opts, "int") normalize_para_type(type_float_opts, "float") normalize_para_type(type_bool_opts, "bool") def get_command_examples(command_info, command_meta): example_items = [] if command_info and command_info.get("help", None) and hasattr(command_info["help"], "examples"): for example_obj in command_info["help"].examples: example_items.append({"name": example_obj.name, "text": example_obj.text}) if example_items: command_meta["examples"] = example_items def gen_command_meta(command_info, with_help=False, with_example=False): stored_property_when_exist = ["confirmation", "supports_no_wait", "is_preview", "deprecate_info"] command_meta = { "name": command_info["name"], "is_aaz": command_info["is_aaz"], } for prop in stored_property_when_exist: if command_info.get(prop, None): command_meta[prop] = command_info[prop] if with_example: get_command_examples(command_info, command_meta) if with_help: if command_info.get("help", None) and hasattr(command_info["help"], "short_summary"): command_meta["desc"] = command_info["help"].short_summary parameters = [] for _, argument in command_info["arguments"].items(): if argument.type is None: continue settings = argument.type.settings if settings.get("action", None): action = settings["action"] if hasattr(action, "__name__") and action.__name__ == "IgnoreAction": # ignore argument like: cmd continue para = { "name": settings["dest"], } process_arg_deprecation(settings, para) process_arg_options(settings, para) process_arg_options_deprecation(settings, para) process_arg_type(settings, para) if settings.get("required", False): para["required"] = True if settings.get("choices", None): para["choices"] = sorted(list(settings["choices"])) if settings.get("id_part", None): para["id_part"] = settings["id_part"] if settings.get("nargs", None): para["nargs"] = settings["nargs"] if settings.get("completer", None): para["has_completer"] = True if settings.get("default", None): if not isinstance(settings["default"], (float, int, str, list, bool)): para["default"] = str(settings["default"]) else: para["default"] = settings["default"] if with_help: para["desc"] = settings.get("help", "") if command_info["is_aaz"] and command_info["az_arguments_schema"]: process_aaz_argument(command_info["az_arguments_schema"], settings, para) normalize_para_types(para) parameters.append(para) command_meta["parameters"] = parameters return command_meta def process_command_group_deprecation(command_group_obj, command_group_info): if not hasattr(command_group_obj, "group_kwargs"): return group_kwargs = getattr(command_group_obj, "group_kwargs") if group_kwargs.get("deprecate_info", None) is None: return for info_key in STORED_DEPRECATION_KEY: if hasattr(group_kwargs["deprecate_info"], info_key) and getattr(group_kwargs["deprecate_info"], info_key): if command_group_info.get("deprecate_info", None) is None: command_group_info["deprecate_info"] = {} command_group_info["deprecate_info"][info_key] = getattr(group_kwargs["deprecate_info"], info_key) def get_commands_meta(command_group_table, commands_info, with_help, with_example): commands_meta = {} for command_info in commands_info: # pylint: disable=too-many-nested-blocks module_name = command_info["source"]["module"] command_name = command_info["name"] if module_name not in commands_meta: commands_meta[module_name] = { "module_name": module_name, "name": "az", "commands": {}, "sub_groups": {} } command_group_info = commands_meta[module_name] command_tree = get_command_tree(command_name) while True: if "is_group" not in command_tree: break if command_tree["is_group"]: group_name = command_tree["group_name"] if group_name not in command_group_info["sub_groups"]: group_info = command_group_table.get(group_name, None) command_group_info["sub_groups"][group_name] = { "name": group_name, "commands": {}, "sub_groups": {} } process_command_group_deprecation(group_info, command_group_info["sub_groups"][group_name]) if with_help: try: command_group_info["sub_groups"][group_name]["desc"] = group_info.help["short-summary"] except AttributeError: pass command_tree = command_tree["sub_info"] command_group_info = command_group_info["sub_groups"][group_name] else: if command_name in command_group_info["commands"]: logger.warning("repeated command: %i", command_name) break command_meta = gen_command_meta(command_info, with_help, with_example) command_group_info["commands"][command_name] = command_meta break return commands_meta