Skip to content

Commit

Permalink
{Core} Knack adoption (#12604)
Browse files Browse the repository at this point in the history
* Allow disabling color (#12601)

* Support --only-show-errors (#12544)

* Add experimental tag (#12543)

* Move yaml output to Knack (#12603)
  • Loading branch information
jiasli authored Mar 20, 2020
1 parent 450f751 commit decf463
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 90 deletions.
18 changes: 12 additions & 6 deletions src/azure-cli-core/azure/cli/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from knack.introspection import extract_args_from_signature, extract_full_summary_from_signature
from knack.log import get_logger
from knack.preview import PreviewItem
from knack.experimental import ExperimentalItem
from knack.util import CLIError
from knack.arguments import ArgumentsContext, CaseInsensitiveList # pylint: disable=unused-import

Expand Down Expand Up @@ -85,8 +86,8 @@ def get_cli_version(self):

def show_version(self):
from azure.cli.core.util import get_az_version_string
from azure.cli.core.commands.constants import SURVEY_PROMPT
import colorama
from azure.cli.core.commands.constants import SURVEY_PROMPT, SURVEY_PROMPT_COLOR

ver_string, updates_available = get_az_version_string()
print(ver_string)
if updates_available == -1:
Expand All @@ -98,9 +99,7 @@ def show_version(self):
else:
print('Your CLI is up-to-date.')

colorama.init() # This could be removed when knack fix is released
print('\n' + SURVEY_PROMPT)
colorama.deinit() # This could be removed when knack fix is released
print('\n' + (SURVEY_PROMPT_COLOR if self.enable_color else SURVEY_PROMPT))

def exception_handler(self, ex): # pylint: disable=no-self-use
from azure.cli.core.util import handle_exception
Expand Down Expand Up @@ -162,7 +161,7 @@ def _update_command_table_from_modules(args):
# Changing this error message requires updating CI script that checks for failed
# module loading.
import azure.cli.core.telemetry as telemetry
logger.error("Error loading command module '%s'", mod)
logger.error("Error loading command module '%s': %s", mod, ex)
telemetry.set_exception(exception=ex, fault_type='module-load-error-' + mod,
summary='Error loading module: {}'.format(mod))
logger.debug(traceback.format_exc())
Expand Down Expand Up @@ -450,6 +449,13 @@ def command_group(self, group_name, command_type=None, **kwargs):
kwargs['deprecate_info'].target = group_name
if kwargs.get('is_preview', False):
kwargs['preview_info'] = PreviewItem(
cli_ctx=self.cli_ctx,
target=group_name,
object_type='command group'
)
if kwargs.get('is_experimental', False):
kwargs['experimental_info'] = ExperimentalItem(
cli_ctx=self.cli_ctx,
target=group_name,
object_type='command group'
)
Expand Down
19 changes: 12 additions & 7 deletions src/azure-cli-core/azure/cli/core/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import argparse

from azure.cli.core.commands import ExtensionCommandSource
from azure.cli.core.commands.constants import SURVEY_PROMPT
from azure.cli.core.commands.constants import SURVEY_PROMPT, SURVEY_PROMPT_COLOR

from knack.help import (HelpFile as KnackHelpFile, CommandHelpFile as KnackCommandHelpFile,
GroupHelpFile as KnackGroupHelpFile, ArgumentGroupRegistry as KnackArgumentGroupRegistry,
Expand Down Expand Up @@ -64,6 +64,7 @@ def _print_header(self, cli_name, help_file):
def _print_detailed_help(self, cli_name, help_file):
CLIPrintMixin._print_extensions_msg(help_file)
super(CLIPrintMixin, self)._print_detailed_help(cli_name, help_file)
self._print_az_find_message(help_file.command, self.cli_ctx.enable_color)

@staticmethod
def _get_choices_defaults_sources_str(p):
Expand All @@ -75,7 +76,6 @@ def _get_choices_defaults_sources_str(p):

@staticmethod
def _print_examples(help_file):
from colorama import Style
indent = 0
_print_indent('Examples', indent)
for e in help_file.examples:
Expand All @@ -86,9 +86,15 @@ def _print_examples(help_file):
_print_indent(u'{0}'.format(e.long_summary), indent)
_print_indent(u'{0}'.format(e.command), indent)
print('')

@staticmethod
def _print_az_find_message(command, enable_color):
from colorama import Style
indent = 0
message = 'For more specific examples, use: az find "az {}"'.format(help_file.command)
_print_indent(Style.BRIGHT + message + Style.RESET_ALL + '\n', indent)
message = 'For more specific examples, use: az find "az {}"'.format(command)
if enable_color:
message = Style.BRIGHT + message + Style.RESET_ALL
_print_indent(message + '\n', indent)

@staticmethod
def _process_value_sources(p):
Expand Down Expand Up @@ -153,8 +159,6 @@ def new_normalize_text(s):
def show_help(self, cli_name, nouns, parser, is_group):
self.update_loaders_with_help_file_contents(nouns)

import colorama
colorama.init(autoreset=True)
delimiters = ' '.join(nouns)
help_file = self.command_help_cls(self, delimiters, parser) if not is_group \
else self.group_help_cls(self, delimiters, parser)
Expand All @@ -165,7 +169,7 @@ def show_help(self, cli_name, nouns, parser, is_group):
AzCliHelp.update_examples(help_file)
self._print_detailed_help(cli_name, help_file)

print(SURVEY_PROMPT)
print(SURVEY_PROMPT_COLOR if self.cli_ctx.enable_color else SURVEY_PROMPT)

def _register_help_loaders(self):
import azure.cli.core._help_loaders as help_loaders
Expand Down Expand Up @@ -288,6 +292,7 @@ def __init__(self, help_ctx, delimiters, parser):
'name_source': [action.metavar or action.dest],
'deprecate_info': getattr(action, 'deprecate_info', None),
'preview_info': getattr(action, 'preview_info', None),
'experimental_info': getattr(action, 'experimental_info', None),
'description': action.help,
'choices': action.choices,
'required': False,
Expand Down
28 changes: 0 additions & 28 deletions src/azure-cli-core/azure/cli/core/_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,6 @@


class AzOutputProducer(knack.output.OutputProducer):
def __init__(self, cli_ctx=None):
super(AzOutputProducer, self).__init__(cli_ctx)
additional_formats = {
'yaml': self.format_yaml,
'yamlc': self.format_yaml_color,
'none': self.format_none
}
super(AzOutputProducer, self)._FORMAT_DICT.update(additional_formats)

@staticmethod
def format_yaml(obj):
from yaml import (safe_dump, representer)
import json

try:
return safe_dump(obj.result, default_flow_style=False)
except representer.RepresenterError:
# yaml.safe_dump fails when obj.result is an OrderedDict. knack's --query implementation converts the result to an OrderedDict. https://github.com/microsoft/knack/blob/af674bfea793ff42ae31a381a21478bae4b71d7f/knack/query.py#L46. # pylint: disable=line-too-long
return safe_dump(json.loads(json.dumps(obj.result)), default_flow_style=False)

@staticmethod
def format_yaml_color(obj):
from pygments import highlight, lexers, formatters
return highlight(AzOutputProducer.format_yaml(obj), lexers.YamlLexer(), formatters.TerminalFormatter()) # pylint: disable=no-member

@staticmethod
def format_none(_):
return ""

def check_valid_format_type(self, format_type):
return format_type in self._FORMAT_DICT
Expand Down
82 changes: 48 additions & 34 deletions src/azure-cli-core/azure/cli/core/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@
import azure.cli.core.telemetry as telemetry

from knack.arguments import CLICommandArgument
from knack.commands import CLICommand, CommandGroup
from knack.commands import CLICommand, CommandGroup, PREVIEW_EXPERIMENTAL_CONFLICT_ERROR
from knack.deprecation import ImplicitDeprecated, resolve_deprecate_info
from knack.invocation import CommandInvoker
from knack.preview import ImplicitPreviewItem, PreviewItem, resolve_preview_info
from knack.experimental import ImplicitExperimentalItem, ExperimentalItem, resolve_experimental_info
from knack.log import get_logger
from knack.util import CLIError, CommandResultItem, todict
from knack.events import EVENT_INVOKER_TRANSFORM_RESULT
Expand Down Expand Up @@ -686,8 +687,6 @@ def resolve_warnings(self, cmd, parsed_args):
self._resolve_extension_override_warning(cmd)

def _resolve_preview_and_deprecation_warnings(self, cmd, parsed_args):
import colorama

deprecations = [] + getattr(parsed_args, '_argument_deprecations', [])
if cmd.deprecate_info:
deprecations.append(cmd.deprecate_info)
Expand Down Expand Up @@ -724,12 +723,31 @@ def _resolve_preview_and_deprecation_warnings(self, cmd, parsed_args):
del preview_kwargs['_get_message']
previews.append(ImplicitPreviewItem(**preview_kwargs))

colorama.init()
for d in deprecations:
print(d.message, file=sys.stderr)
for p in previews:
print(p.message, file=sys.stderr)
colorama.deinit()
experimentals = [] + getattr(parsed_args, '_argument_experimentals', [])
if cmd.experimental_info:
experimentals.append(cmd.experimental_info)
else:
# search for implicit command experimental status
path_comps = cmd.name.split()[:-1]
implicit_experimental_info = None
while path_comps and not implicit_experimental_info:
implicit_experimental_info = resolve_experimental_info(self.cli_ctx, ' '.join(path_comps))
del path_comps[-1]

if implicit_experimental_info:
experimental_kwargs = implicit_experimental_info.__dict__.copy()
experimental_kwargs['object_type'] = 'command'
del experimental_kwargs['_get_tag']
del experimental_kwargs['_get_message']
experimentals.append(ImplicitExperimentalItem(**experimental_kwargs))

if not self.cli_ctx.only_show_errors:
for d in deprecations:
print(d.message, file=sys.stderr)
for p in previews:
print(p.message, file=sys.stderr)
for e in experimentals:
print(e.message, file=sys.stderr)

def _resolve_extension_override_warning(self, cmd): # pylint: disable=no-self-use
if isinstance(cmd.command_source, ExtensionCommandSource) and cmd.command_source.overrides_command:
Expand Down Expand Up @@ -864,12 +882,8 @@ def _generate_template_progress(self, correlation_id): # pylint: disable=no-sel
logger.info(result)

def __call__(self, poller):
import colorama
from msrest.exceptions import ClientException

# https://github.com/azure/azure-cli/issues/3555
colorama.init()

correlation_message = ''
self.cli_ctx.get_progress_controller().begin()
correlation_id = None
Expand Down Expand Up @@ -910,7 +924,6 @@ def __call__(self, poller):
handle_long_running_operation_exception(client_exception)

self.cli_ctx.get_progress_controller().end()
colorama.deinit()

return result

Expand Down Expand Up @@ -1162,11 +1175,8 @@ def custom_command(self, name, method_name=None, **kwargs):
def _command(self, name, method_name, custom_command=False, **kwargs):
self._check_stale()
merged_kwargs = self._flatten_kwargs(kwargs, get_command_type_kwarg(custom_command))
# don't inherit deprecation or preview info from command group
merged_kwargs['deprecate_info'] = kwargs.get('deprecate_info', None)
merged_kwargs['preview_info'] = None
if kwargs.get('is_preview', False):
merged_kwargs['preview_info'] = PreviewItem(self.command_loader.cli_ctx, object_type='command')
self._apply_tags(merged_kwargs, kwargs, name)

operations_tmpl = merged_kwargs['operations_tmpl']
command_name = '{} {}'.format(self.group_name, name) if self.group_name else name
self.command_loader._cli_command(command_name, # pylint: disable=protected-access
Expand Down Expand Up @@ -1206,11 +1216,7 @@ def generic_update_command(self, name, getter_name='get', getter_type=None,
self._check_stale()
merged_kwargs = self._flatten_kwargs(kwargs, get_command_type_kwarg())
merged_kwargs_custom = self._flatten_kwargs(kwargs, get_command_type_kwarg(custom_command=True))
# don't inherit deprecation or preview info from command group
merged_kwargs['deprecate_info'] = kwargs.get('deprecate_info', None)
merged_kwargs['preview_info'] = None
if kwargs.get('is_preview', False):
merged_kwargs['preview_info'] = PreviewItem(self.command_loader.cli_ctx, object_type='command')
self._apply_tags(merged_kwargs, kwargs, name)

getter_op = self._resolve_operation(merged_kwargs, getter_name, getter_type)
setter_op = self._resolve_operation(merged_kwargs, setter_name, setter_type)
Expand Down Expand Up @@ -1241,11 +1247,7 @@ def _wait_command(self, name, getter_name='get', getter_type=None, custom_comman
from azure.cli.core.commands.arm import _cli_wait_command
self._check_stale()
merged_kwargs = self._flatten_kwargs(kwargs, get_command_type_kwarg(custom_command))
# don't inherit deprecation or preview info from command group
merged_kwargs['deprecate_info'] = kwargs.get('deprecate_info', None)
merged_kwargs['preview_info'] = None
if kwargs.get('is_preview', False):
merged_kwargs['preview_info'] = PreviewItem(self.command_loader.cli_ctx, object_type='command')
self._apply_tags(merged_kwargs, kwargs, name)

if getter_type:
merged_kwargs = _merge_kwargs(getter_type.settings, merged_kwargs, CLI_COMMAND_KWARGS)
Expand All @@ -1263,18 +1265,30 @@ def _show_command(self, name, getter_name='get', getter_type=None, custom_comman
from azure.cli.core.commands.arm import _cli_show_command
self._check_stale()
merged_kwargs = self._flatten_kwargs(kwargs, get_command_type_kwarg(custom_command))
# don't inherit deprecation or preview info from command group
merged_kwargs['deprecate_info'] = kwargs.get('deprecate_info', None)
merged_kwargs['preview_info'] = None
if kwargs.get('is_preview', False):
merged_kwargs['preview_info'] = PreviewItem(self.command_loader.cli_ctx, object_type='command')
self._apply_tags(merged_kwargs, kwargs, name)

if getter_type:
merged_kwargs = _merge_kwargs(getter_type.settings, merged_kwargs, CLI_COMMAND_KWARGS)
getter_op = self._resolve_operation(merged_kwargs, getter_name, getter_type, custom_command=custom_command)
_cli_show_command(self.command_loader, '{} {}'.format(self.group_name, name), getter_op=getter_op,
custom_command=custom_command, **merged_kwargs)

def _apply_tags(self, merged_kwargs, kwargs, command_name):
# don't inherit deprecation or preview info from command group
merged_kwargs['deprecate_info'] = kwargs.get('deprecate_info', None)

# transform is_preview and is_experimental to StatusTags
merged_kwargs['preview_info'] = None
merged_kwargs['experimental_info'] = None
is_preview = kwargs.get('is_preview', False)
is_experimental = kwargs.get('is_experimental', False)
if is_preview and is_experimental:
raise CLIError(PREVIEW_EXPERIMENTAL_CONFLICT_ERROR.format("command", self.group_name + " " + command_name))
if is_preview:
merged_kwargs['preview_info'] = PreviewItem(self.command_loader.cli_ctx, object_type='command')
if is_experimental:
merged_kwargs['experimental_info'] = ExperimentalItem(self.command_loader.cli_ctx, object_type='command')


def register_cache_arguments(cli_ctx):
from knack import events
Expand Down
1 change: 1 addition & 0 deletions src/azure-cli-core/azure/cli/core/commands/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ def add_ids_arguments(_, **kwargs): # pylint: disable=unused-argument
'dest': 'ids' if id_arg else '_ids',
'deprecate_info': deprecate_info,
'is_preview': id_arg.settings.get('is_preview', None) if id_arg else None,
'is_experimental': id_arg.settings.get('is_experimental', None) if id_arg else None,
'nargs': '+',
'arg_group': group_name
}
Expand Down
8 changes: 5 additions & 3 deletions src/azure-cli-core/azure/cli/core/commands/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@


CLI_COMMON_KWARGS = ['min_api', 'max_api', 'resource_type', 'operation_group',
'custom_command_type', 'command_type', 'is_preview', 'preview_info']
'custom_command_type', 'command_type', 'is_preview', 'preview_info',
'is_experimental', 'experimental_info']

CLI_COMMAND_KWARGS = ['transform', 'table_transformer', 'confirmation', 'exception_handler',
'client_factory', 'operations_tmpl', 'no_wait_param', 'supports_no_wait', 'validator',
Expand All @@ -31,5 +32,6 @@

BLACKLISTED_MODS = ['context', 'shell', 'documentdb', 'component']

SURVEY_PROMPT = Fore.YELLOW + Style.BRIGHT + 'Please let us know how we are doing: ' + Fore.BLUE \
+ 'https://aka.ms/clihats' + Style.RESET_ALL
SURVEY_PROMPT = 'Please let us know how we are doing: https://aka.ms/clihats'
SURVEY_PROMPT_COLOR = Fore.YELLOW + Style.BRIGHT + 'Please let us know how we are doing: ' + Fore.BLUE + \
'https://aka.ms/clihats' + Style.RESET_ALL
7 changes: 1 addition & 6 deletions src/azure-cli-core/azure/cli/core/extension/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ def _validate_whl_extension(ext_file):


def _add_whl_ext(cmd, source, ext_sha256=None, pip_extra_index_urls=None, pip_proxy=None): # pylint: disable=too-many-statements
import colorama
colorama.init() # Required for displaying the spinner correctly on windows issue #9140
cmd.cli_ctx.get_progress_controller().add(message='Analyzing')
if not source.endswith('.whl'):
raise ValueError('Unknown extension type. Only Python wheels are supported.')
Expand Down Expand Up @@ -158,7 +156,7 @@ def _add_whl_ext(cmd, source, ext_sha256=None, pip_extra_index_urls=None, pip_pr
dst = os.path.join(extension_path, whl_filename)
shutil.copyfile(ext_file, dst)
logger.debug('Saved the whl to %s', dst)
colorama.deinit()

return extension_name


Expand Down Expand Up @@ -205,10 +203,7 @@ def add_extension(cmd, source=None, extension_name=None, index_url=None, yes=Non
pip_extra_index_urls=None, pip_proxy=None):
ext_sha256 = None
if extension_name:
import colorama
colorama.init() # Required for displaying the spinner correctly on windows issue #9140
cmd.cli_ctx.get_progress_controller().add(message='Searching')
colorama.deinit()
ext = None
try:
ext = get_extension(extension_name)
Expand Down
1 change: 1 addition & 0 deletions src/azure-cli-core/azure/cli/core/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ def load_command_table(self, command_loader):
param.completer = arg.completer
param.deprecate_info = arg.deprecate_info
param.preview_info = arg.preview_info
param.experimental_info = arg.experimental_info
command_parser.set_defaults(
func=metadata,
command=command_name,
Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli-core/azure/cli/core/tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_yaml_output_with_ordered_dict(self):
}

output_producer = AzOutputProducer(DummyCli())
yaml_output = output_producer.format_yaml(CommandResultItem(result=OrderedDict(account_dict)))
yaml_output = output_producer.get_formatter('yaml')(CommandResultItem(result=OrderedDict(account_dict)))
self.assertEqual(account_dict, yaml.safe_load(yaml_output))


Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli-core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
'colorama>=0.3.9',
'humanfriendly~=4.7',
'jmespath',
'knack~=0.6.2',
'knack==0.7.0rc1',
'msrest>=0.4.4',
'msrestazure>=0.6.2',
'paramiko>=2.0.8,<3.0.0',
Expand Down
Loading

0 comments on commit decf463

Please sign in to comment.