Merge pull request #194 from BurtBiel/help/sortGlobals

Help/sort globals
This commit is contained in:
Burt Bielicki 2016-05-04 16:29:03 -07:00
Родитель f94ef2f00d f25ba60f5c
Коммит 73c69eb19e
5 изменённых файлов: 164 добавлений и 126 удалений

Просмотреть файл

@ -126,26 +126,6 @@
<Compile Include="command_modules\azure-cli-storage\setup.py" />
<Compile Include="command_modules\azure-cli-taskhelp\azure\cli\command_modules\taskhelp\__init__.py" />
<Compile Include="command_modules\azure-cli-taskhelp\setup.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\credentials.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\exceptions.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\basic_dependency.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\dependency.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\deployment_extended.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\deployment_parameter_virtual_network_ip_address_prefix.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\deployment_properties_extended.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\deployment_vm.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\parameters_link.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\provider.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\provider_resource_type.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\template_link.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\vm_creation_client_enums.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\operations\vm_operations.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\operations\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\version.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\vm_creation_client.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\tests\command_specs.py">
<SubType>Code</SubType>
</Compile>
@ -161,9 +141,6 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\azure\cli\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\azure\__init__.py" />
<Compile Include="command_modules\azure-cli-vm\setup.py" />
</ItemGroup>
<ItemGroup>
@ -220,11 +197,6 @@
<Folder Include="command_modules\azure-cli-vm\azure\cli\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\models\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\lib\operations\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\tests\" />
<Folder Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\tests\recordings\" />
</ItemGroup>
@ -251,20 +223,6 @@
<Content Include="command_modules\azure-cli-storage\requirements.txt" />
<Content Include="command_modules\azure-cli-taskhelp\requirements.txt" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\tests\aliases.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\azuredeploy.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\ExistingStorageAccount.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\ExistingVNet.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\NewStorageAccount.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\NewVNet.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\nic_ip_existing_dns_none.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\nic_ip_new_dns_new.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\nic_ip_new_dns_none.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\nic_ip_none_dns_none.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\vm_existing_password.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\vm_existing_sshkey.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\vm_none_password.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\nested_templates\vm_none_sshkey.json" />
<Content Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\mgmt\swagger_create_vm.json" />
<Content Include="command_modules\azure-cli-vm\requirements.txt" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -75,10 +75,18 @@ def print_arguments(help_file):
required_tag = L(' [Required]')
max_name_length = max(len(p.name) + (len(required_tag) if p.required else 0)
for p in help_file.parameters)
for p in sorted(help_file.parameters, key=lambda p: str(not p.required) + p.name):
last_group_name = None
for p in sorted(help_file.parameters,
key=lambda p: str(p.group_name or 'A')
+ str(not p.required) + p.name):
indent = 1
required_text = required_tag if p.required else ''
p.short_summary = (p.short_summary if p.short_summary else '') + _get_choices_str(p)
if p.group_name != last_group_name:
if p.group_name:
print('')
print(p.group_name)
last_group_name = p.group_name
_print_indent('{0}{1}{2}{3}'.format(p.name,
_get_column_indent(p.name + required_text,
max_name_length),
@ -92,7 +100,6 @@ def print_arguments(help_file):
_print_indent('{0}'.format(p.long_summary.rstrip()), indent)
if p.value_sources:
_print_indent('')
_print_indent(L("Values from: {0}").format(', '.join(p.value_sources)), indent)
if p.long_summary or p.value_sources:
@ -105,7 +112,7 @@ def _print_header(help_file):
_print_indent(L('Command') if help_file.type == 'command' else L('Group'), indent)
indent += 1
_print_indent('{0}{1}'.format(help_file.command,
_print_indent('{0}{1}'.format('az ' + help_file.command,
': ' + help_file.short_summary
if help_file.short_summary
else ''),
@ -138,6 +145,7 @@ def _get_choices_str(p):
def _print_examples(help_file):
indent = 0
print('')
_print_indent(L('Examples'), indent)
for e in help_file.examples:
@ -218,7 +226,11 @@ class CommandHelpFile(HelpFile): #pylint: disable=too-few-public-methods
action.help,
required=action.required,
choices=action.choices,
default=action.default))
default=action.default,
group_name=action.container.description))
help_param = next(p for p in self.parameters if p.name == '--help -h')
help_param.group_name = 'Global Arguments'
def _load_from_data(self, data):
super(CommandHelpFile, self)._load_from_data(data)
@ -243,7 +255,8 @@ class CommandHelpFile(HelpFile): #pylint: disable=too-few-public-methods
class HelpParameter(object): #pylint: disable=too-few-public-methods, too-many-instance-attributes
def __init__(self, param_name, description, required, choices=None, default=None): #pylint: disable=too-many-arguments
def __init__(self, param_name, description, required, choices=None, #pylint: disable=too-many-arguments
default=None, group_name=None):
self.name = param_name
self.required = required
self.type = 'string'
@ -252,6 +265,7 @@ class HelpParameter(object): #pylint: disable=too-few-public-methods, too-many-i
self.value_sources = []
self.choices = choices
self.default = default
self.group_name = group_name
def update_from_data(self, data):
if self.name != data.get('name'):

Просмотреть файл

@ -50,7 +50,8 @@ class Application(object):
azure.cli.extensions.register_extensions(self)
self.global_parser = AzCliCommandParser(prog='az', add_help=False)
self.raise_event(self.GLOBAL_PARSER_CREATED, self.global_parser)
global_group = self.global_parser.add_argument_group('global', 'Global Arguments')
self.raise_event(self.GLOBAL_PARSER_CREATED, global_group)
self.parser = AzCliCommandParser(prog='az', parents=[self.global_parser])
self.raise_event(self.COMMAND_PARSER_CREATED, self.parser)
@ -134,17 +135,20 @@ class Application(object):
argcomplete.autocomplete(parser)
@staticmethod
def _register_builtin_arguments(parser):
parser.add_argument('--subscription', dest='_subscription_id', help=argparse.SUPPRESS)
parser.add_argument('--output', '-o', dest='_output_format',
choices=['list', 'json', 'tsv'],
default='list',
help='Output format')
def _register_builtin_arguments(global_group):
global_group.add_argument('--subscription', dest='_subscription_id', help=argparse.SUPPRESS)
global_group.add_argument('--output', '-o', dest='_output_format',
choices=['list', 'json', 'tsv'],
default='list',
help='Output format')
# The arguments for verbosity don't get parsed by argparse but we add it here for help.
parser.add_argument('--verbose', dest='_log_verbosity_verbose',
help='Increase logging verbosity. Use --debug for full debug logs.')
parser.add_argument('--debug', dest='_log_verbosity_debug',
help='Increase logging verbosity to show all debug logs.')
global_group.add_argument('--verbose', dest='_log_verbosity_verbose',
help='Increase logging verbosity.'
' Use --debug for full debug logs.',
action='store_true')
global_group.add_argument('--debug', dest='_log_verbosity_debug',
help='Increase logging verbosity to show all debug logs.',
action='store_true')
def _handle_builtin_arguments(self, args):
self.configuration.output_format = args._output_format #pylint: disable=protected-access

Просмотреть файл

@ -1,9 +1,9 @@
import collections
def _register_global_parameter(parser):
def _register_global_parameter(global_group):
# Let the program know that we are adding a parameter --query
parser.add_argument('--query', dest='_jmespath_query', metavar='JMESPATH',
help='JMESPath query string. See http://jmespath.org/ for more information and examples.') # pylint: disable=line-too-long
global_group.add_argument('--query', dest='_jmespath_query', metavar='JMESPATH',
help='JMESPath query string. See http://jmespath.org/ for more information and examples.') # pylint: disable=line-too-long
def register(application):
def handle_query_parameter(args):

Просмотреть файл

@ -106,7 +106,7 @@ class Test_argparse(unittest.TestCase):
with self.assertRaises(SystemExit):
app.execute('n1 -h'.split())
self.assertEqual(True, io.getvalue().startswith('\nCommand\n n1\n long description'))
self.assertEqual(True, io.getvalue().startswith('\nCommand\n az n1\n long description'))
@redirect_io
def test_help_long_description_and_short_description(self):
@ -131,7 +131,7 @@ class Test_argparse(unittest.TestCase):
with self.assertRaises(SystemExit):
app.execute('n1 -h'.split())
self.assertEqual(True, io.getvalue().startswith('\nCommand\n n1: short description\n long description'))
self.assertEqual(True, io.getvalue().startswith('\nCommand\n az n1: short description\n long description'))
@redirect_io
def test_help_docstring_description_overrides_short_description(self):
@ -185,7 +185,7 @@ class Test_argparse(unittest.TestCase):
with self.assertRaises(SystemExit):
app.execute('n1 -h'.split())
self.assertEqual(True, io.getvalue().startswith('\nCommand\n n1\n line1\n line2'))
self.assertEqual(True, io.getvalue().startswith('\nCommand\n az n1\n line1\n line2'))
@redirect_io
@mock.patch('azure.cli.application.Application.register', return_value=None)
@ -228,7 +228,7 @@ class Test_argparse(unittest.TestCase):
app.execute('n1 -h'.split())
s = '''
Command
n1
az n1
Arguments
--foobar2 -fb2 [Required]: one line partial sentence
@ -236,10 +236,11 @@ Arguments
--foobar -fb : one line partial sentence
text, markdown, etc.
Values from: az vm list, default
--foobar3 -fb3 : the foobar3
Global Arguments
--help -h : show this help message and exit
'''
self.assertEqual(s, io.getvalue())
@ -291,7 +292,7 @@ Arguments
app.execute('n1 -h'.split())
s = '''
Command
n1: this module does xyz one-line or so
az n1: this module does xyz one-line or so
this module.... kjsdflkj... klsfkj paragraph1
this module.... kjsdflkj... klsfkj paragraph2
@ -301,10 +302,12 @@ Arguments
--foobar -fb : one line partial sentence
text, markdown, etc.
Values from: az vm list, default
Global Arguments
--help -h : show this help message and exit
Examples
foo example
example details
@ -377,41 +380,42 @@ Examples
'.*Extra help param --foobar -fb.*',
lambda: app.execute('n1 -h'.split()))
# Will uncomment when partial params don't bypass help (help behaviors implementation) task #115631559
# @redirect_io
# def test_help_with_param_specified(self):
# app = Application(Configuration([]))
# def test_handler(args):
# pass
@redirect_io
@mock.patch('azure.cli.application.Application.register', return_value=None)
def test_help_with_param_specified(self, _):
app = Application(Configuration([]))
def test_handler(args):
pass
# cmd_table = {
# test_handler: {
# 'name': 'n1',
# 'arguments': [
# {'name': '--arg -a', 'required': False},
# {'name': '-b', 'required': False}
# ]
# }
# }
# config = Configuration([])
#config.get_command_table = lambda: cmd_table
#app = Application(config)
cmd_table = {
test_handler: {
'name': 'n1',
'arguments': [
{'name': '--arg -a', 'required': False},
{'name': '-b', 'required': False}
]
}
}
config = Configuration([])
config.get_command_table = lambda: cmd_table
app = Application(config)
# with self.assertRaises(SystemExit):
# cmd_result = app.execute('n1 --arg -h'.split())
with self.assertRaises(SystemExit):
cmd_result = app.execute('n1 --arg foo -h'.split())
# s = '''
#Command
# n1
s = '''
Command
az n1
#Arguments
# --arg -a
Arguments
--arg -a
-b
# -b
Global Arguments
--help -h: show this help message and exit
'''
#'''
# self.assertEqual(s, io.getvalue())
self.assertEqual(s, io.getvalue())
@redirect_io
def test_help_group_children(self):
@ -443,39 +447,42 @@ Examples
with self.assertRaises(SystemExit):
app.execute('group1 -h'.split())
s = '\nGroup\n group1\n\nSub-Commands\n group2\n group3\n\n'
s = '\nGroup\n az group1\n\nSub-Commands\n group2\n group3\n\n'
self.assertEqual(s, io.getvalue())
# Will uncomment when all errors are shown at once (help behaviors implementation) task #115631559
#@redirect_io
#def test_help_extra_missing_params(self):
# app = Application(Configuration([]))
# def test_handler(args):
# pass
@redirect_io
def test_help_extra_missing_params(self):
app = Application(Configuration([]))
def test_handler(args):
pass
# cmd_table = {
# test_handler: {
# 'name': 'n1',
# 'arguments': [
# {'name': '--foobar -fb', 'required': False},
# {'name': '--foobar2 -fb2', 'required': True}
# ]
# }
# }
# config = Configuration([])
#config.get_command_table = lambda: cmd_table
#app = Application(config)
cmd_table = {
test_handler: {
'name': 'n1',
'arguments': [
{'name': '--foobar -fb', 'required': False},
{'name': '--foobar2 -fb2', 'required': True}
]
}
}
config = Configuration([])
config.get_command_table = lambda: cmd_table
app = Application(config)
# with self.assertRaises(SystemExit):
# app.execute('n1 -fb a --foobar3 bad'.split())
# there is an argparse bug on <2.7.10 where SystemExit is not thrown on missing required param
if sys.version_info < (2, 7, 10):
app.execute('n1 -fb a --foobar value'.split())
app.execute('n1 -fb a --foobar2 value --foobar3 extra'.split())
else:
with self.assertRaises(SystemExit):
app.execute('n1 -fb a --foobar value'.split())
with self.assertRaises(SystemExit):
app.execute('n1 -fb a --foobar2 value --foobar3 extra'.split())
# with open(r'C:\temp\value.txt', 'w') as f:
# f.write(io.getvalue())
# self.assertTrue('required' in io.getvalue()
# and '--foobar/-fb' not in io.getvalue()
# and '--foobar2/-fb' in io.getvalue()
# and 'unrecognized arguments: --foobar3' in io.getvalue())
self.assertTrue('required' in io.getvalue()
and '--foobar/-fb' not in io.getvalue()
and '--foobar2/-fb2' in io.getvalue()
and 'unrecognized arguments: --foobar3 extra' in io.getvalue())
@redirect_io
def test_help_group_help(self):
@ -520,19 +527,74 @@ Examples
app.execute('test_group1 test_group2 --help'.split())
s = '''
Group
test_group1 test_group2: this module does xyz one-line or so
az test_group1 test_group2: this module does xyz one-line or so
this module.... kjsdflkj... klsfkj paragraph1
this module.... kjsdflkj... klsfkj paragraph2
Sub-Commands
n1: this module does xyz one-line or so
Examples
foo example
example details
'''
self.assertEqual(s, io.getvalue())
@redirect_io
@mock.patch('azure.cli.application.Application.register', return_value=None)
@mock.patch('azure.cli.extensions.register_extensions', return_value=None)
def test_help_global_params(self, mock_register_extensions, _):
def register_globals(global_group):
global_group.add_argument('--query2', dest='_jmespath_query', metavar='JMESPATH',
help='JMESPath query string. See http://jmespath.org/ '
'for more information and examples.')
mock_register_extensions.return_value = None
mock_register_extensions.side_effect = lambda app: \
app._event_handlers[app.GLOBAL_PARSER_CREATED].append(register_globals)
def test_handler(args):
pass
cmd_table = {
test_handler: {
'name': 'n1',
'help_file': '''
long-summary: |
line1
line2
''',
'arguments': [
{'name': '--arg -a', 'required': False},
{'name': '-b', 'required': False}
]
}
}
config = Configuration([])
config.get_command_table = lambda: cmd_table
app = Application(config)
with self.assertRaises(SystemExit):
app.execute('n1 -h'.split())
s = """
Command
az n1
line1
line2
Arguments
--arg -a
-b
Global Arguments
--help -h: show this help message and exit
--query2 : JMESPath query string. See http://jmespath.org/ for more information and examples.
"""
self.assertEqual(s, io.getvalue())
if __name__ == '__main__':
unittest.main()