1# -------------------------------------------------------------------------------------------- 2# Copyright (c) Microsoft Corporation. All rights reserved. 3# Licensed under the MIT License. See License.txt in the project root for license information. 4# -------------------------------------------------------------------------------------------- 5 6from azure.cli.core._help import CliCommandHelpFile, CliGroupHelpFile 7 8from knack.log import get_logger 9from knack.util import CLIError 10 11logger = get_logger(__name__) 12 13 14def get_all_help(cli_ctx, skip=True): 15 invoker = cli_ctx.invocation 16 help_ctx = cli_ctx.help_cls(cli_ctx) 17 if not invoker: 18 raise CLIError('CLI context does not contain invocation.') 19 20 parser_keys = [] 21 parser_values = [] 22 sub_parser_keys = [] 23 sub_parser_values = [] 24 _store_parsers(invoker.parser, parser_keys, parser_values, sub_parser_keys, sub_parser_values) 25 for cmd, parser in zip(parser_keys, parser_values): 26 if cmd not in sub_parser_keys: 27 sub_parser_keys.append(cmd) 28 sub_parser_values.append(parser) 29 help_files = [] 30 help_errors = {} 31 for cmd, parser in zip(sub_parser_keys, sub_parser_values): 32 try: 33 help_ctx.update_loaders_with_help_file_contents(cmd.split()) 34 help_file = CliGroupHelpFile(help_ctx, cmd, parser) if _is_group(parser) \ 35 else CliCommandHelpFile(help_ctx, cmd, parser) 36 help_file.load(parser) 37 help_files.append(help_file) 38 except Exception as ex: # pylint: disable=broad-except 39 if skip: 40 logger.warning("Skipping '%s': %s", cmd, ex) 41 else: 42 help_errors[cmd] = "Error '{}': {}".format(cmd, ex) 43 if help_errors: 44 raise CLIError(help_errors) 45 help_files = sorted(help_files, key=lambda x: x.command) 46 return help_files 47 48 49def create_invoker_and_load_cmds_and_args(cli_ctx): 50 from knack.events import ( 51 EVENT_INVOKER_PRE_CMD_TBL_CREATE, EVENT_INVOKER_POST_CMD_TBL_CREATE) 52 from azure.cli.core.commands import register_cache_arguments 53 from azure.cli.core.commands.arm import register_global_subscription_argument, register_ids_argument 54 from azure.cli.core.commands.events import ( 55 EVENT_INVOKER_PRE_LOAD_ARGUMENTS, EVENT_INVOKER_POST_LOAD_ARGUMENTS) 56 import time 57 58 start_time = time.time() 59 60 register_global_subscription_argument(cli_ctx) 61 register_ids_argument(cli_ctx) 62 register_cache_arguments(cli_ctx) 63 64 invoker = cli_ctx.invocation_cls(cli_ctx=cli_ctx, commands_loader_cls=cli_ctx.commands_loader_cls, 65 parser_cls=cli_ctx.parser_cls, help_cls=cli_ctx.help_cls) 66 cli_ctx.invocation = invoker 67 invoker.commands_loader.skip_applicability = True 68 69 cli_ctx.raise_event(EVENT_INVOKER_PRE_CMD_TBL_CREATE, args=[]) 70 invoker.commands_loader.load_command_table(None) 71 invoker.commands_loader.command_name = '' 72 73 cli_ctx.raise_event(EVENT_INVOKER_PRE_LOAD_ARGUMENTS, commands_loader=invoker.commands_loader) 74 invoker.commands_loader.load_arguments() 75 76 cli_ctx.raise_event(EVENT_INVOKER_POST_LOAD_ARGUMENTS, commands_loader=invoker.commands_loader) 77 cli_ctx.raise_event(EVENT_INVOKER_POST_CMD_TBL_CREATE, commands_loader=invoker.commands_loader) 78 invoker.parser.cli_ctx = cli_ctx 79 invoker.parser.load_command_table(invoker.commands_loader) 80 81 end_time = time.time() 82 logger.info('Time to load entire command table: %.3f sec', end_time - start_time) 83 84 85def _store_parsers(parser, parser_keys, parser_values, sub_parser_keys, sub_parser_values): 86 for s in parser.subparsers.values(): 87 parser_keys.append(_get_parser_name(s)) 88 parser_values.append(s) 89 if _is_group(s): 90 for c in s.choices.values(): 91 sub_parser_keys.append(_get_parser_name(c)) 92 sub_parser_values.append(c) 93 _store_parsers(c, parser_keys, parser_values, sub_parser_keys, sub_parser_values) 94 95 96def _get_parser_name(s): 97 return (s._prog_prefix if hasattr(s, '_prog_prefix') else s.prog)[3:] # pylint: disable=protected-access 98 99 100def _is_group(parser): 101 return getattr(parser, '_subparsers', None) is not None \ 102 or getattr(parser, 'choices', None) is not None 103