def test_help_group_children(self): app = Application(Configuration([])) def test_handler(): pass def test_handler2(): pass command = CliCommand('group1 group3 n1', test_handler) command.add_argument('foobar', '--foobar', '-fb', required=False) command.add_argument('foobar2', '--foobar2', '-fb2', required=True) command2 = CliCommand('group1 group2 n1', test_handler2) command2.add_argument('foobar', '--foobar', '-fb', required=False) command2.add_argument('foobar2', '--foobar2', '-fb2', required=True) cmd_table = {'group1 group3 n1': command, 'group1 group2 n1': command2} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('group1 -h'.split()) s = '\nGroup\n az group1\n\nSubgroups:\n group2\n group3\n\n' self.assertEqual(s, io.getvalue())
def test_help_full_documentations(self, _): app = Application(Configuration()) def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('foobar', '--foobar', '-fb', required=False) command.add_argument('foobar2', '--foobar2', '-fb2', required=True) command.help = """ short-summary: this module does xyz one-line or so long-summary: | this module.... kjsdflkj... klsfkj paragraph1 this module.... kjsdflkj... klsfkj paragraph2 parameters: - name: --foobar -fb type: string required: false short-summary: one line partial sentence long-summary: text, markdown, etc. populator-commands: - az vm list - default - name: --foobar2 -fb2 type: string required: true short-summary: one line partial sentence long-summary: paragraph(s) examples: - name: foo example text: example details """ cmd_table = {'n1': command} config = Configuration() config.get_command_table = lambda args: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split()) s = """ Command az n1: This module does xyz one-line or so. This module.... kjsdflkj... klsfkj paragraph1 this module.... kjsdflkj... klsfkj paragraph2. Arguments --foobar2 -fb2 [Required]: One line partial sentence. Paragraph(s). --foobar -fb : One line partial sentence. Values from: az vm list, default. Text, markdown, etc. Global Arguments --help -h : Show this help message and exit. Examples foo example example details """ self.assertEqual(s, io.getvalue())
def test_help_long_description_from_docstring(self): """ Verifies that the first sentence of a docstring is extracted as the short description. Verifies that line breaks in the long summary are removed and leaves the text wrapping to the help system. """ def test_handler(): """Short Description. Long description with\nline break.""" pass setattr(sys.modules[__name__], test_handler.__name__, test_handler) cli_command(None, "test", "{}#{}".format(__name__, test_handler.__name__)) _update_command_definitions(command_table) config = Configuration([]) app = Application(config) with self.assertRaises(SystemExit): app.execute("test -h".split()) self.assertEqual( True, io.getvalue().startswith( "\nCommand\n az test: Short Description.\n Long description with line break." ), ) # pylint: disable=line-too-long
def test_list_value_parameter(self): hellos = [] def handler(args): hellos.append(args) command = CliCommand('test command', handler) command.add_argument('hello', '--hello', nargs='+', action=IterateAction) command.add_argument('something', '--something') cmd_table = {'test command': command} argv = 'az test command --hello world sir --something else'.split() config = Configuration() config.get_command_table = lambda argv: cmd_table application = Application(config) application.execute(argv[1:]) self.assertEqual(2, len(hellos)) self.assertEqual(hellos[0]['hello'], 'world') self.assertEqual(hellos[0]['something'], 'else') self.assertEqual(hellos[1]['hello'], 'sir') self.assertEqual(hellos[1]['something'], 'else')
def test_help_with_param_specified(self, _): app = Application(Configuration([])) def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) cmd_table = {'n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('n1 --arg foo -h'.split()) s = """ Command az n1 Arguments --arg -a -b Global Arguments --help -h: Show this help message and exit. """ self.assertEqual(s, io.getvalue())
class TestCommandWithConfiguredDefaults(unittest.TestCase): def __init__(self, *args, **kwargs): self.argv = None self.application = None super(TestCommandWithConfiguredDefaults, self).__init__(*args, **kwargs) @classmethod def setUpClass(cls): # Ensure initialization has occurred correctly import azure.cli.main logging.basicConfig(level=logging.DEBUG) @classmethod def tearDownClass(cls): logging.shutdown() @staticmethod def sample_vm_list(resource_group_name): return resource_group_name def set_up_command_table(self, required_arg=False): command_table.clear() module_name = __name__ + '.' + self._testMethodName cli_command(module_name, 'test sample-vm-list', '{}#TestCommandWithConfiguredDefaults.sample_vm_list'.format(__name__)) register_cli_argument('test sample-vm-list', 'resource_group_name', CliArgumentType(options_list=('--resource-group-name', '-g'), configured_default='group', required=required_arg)) command_table['test sample-vm-list'].load_arguments() _update_command_definitions(command_table) self.argv = 'az test sample-vm-list'.split() config = Configuration() config.get_command_table = lambda argv: command_table self.application = Application(config) @mock.patch.dict(os.environ, {AzConfig.env_var_name('defaults', 'group'): 'myRG'}) def test_apply_configured_defaults_on_required_arg(self): self.set_up_command_table(required_arg=True) # action res = self.application.execute(self.argv[1:]) # assert self.assertEqual(res.result, 'myRG') @mock.patch.dict(os.environ, {AzConfig.env_var_name('defaults', 'group'): 'myRG'}) def test_apply_configured_defaults_on_optional_arg(self): self.set_up_command_table(required_arg=False) # action res = self.application.execute(self.argv[1:]) # assert self.assertEqual(res.result, 'myRG')
class TestCommandWithConfiguredDefaults(unittest.TestCase): def __init__(self, *args, **kwargs): self.argv = None self.application = None super(TestCommandWithConfiguredDefaults, self).__init__(*args, **kwargs) @classmethod def setUpClass(cls): # Ensure initialization has occurred correctly import azure.cli.main logging.basicConfig(level=logging.DEBUG) @classmethod def tearDownClass(cls): logging.shutdown() @staticmethod def sample_vm_list(resource_group_name): return resource_group_name def set_up_command_table(self, required_arg=False): command_table.clear() module_name = __name__ + '.' + self._testMethodName cli_command(module_name, 'test sample-vm-list', '{}#TestCommandWithConfiguredDefaults.sample_vm_list'.format(__name__)) register_cli_argument('test sample-vm-list', 'resource_group_name', CliArgumentType(options_list=('--resource-group-name', '-g'), configured_default='group', required=required_arg)) command_table['test sample-vm-list'].load_arguments() _update_command_definitions(command_table) self.argv = 'az test sample-vm-list'.split() config = Configuration(self.argv) config.get_command_table = lambda: command_table self.application = Application(config) @mock.patch.dict(os.environ, {AzConfig.env_var_name('defaults', 'group'): 'myRG'}) def test_apply_configured_defaults_on_required_arg(self): self.set_up_command_table(required_arg=True) # action res = self.application.execute(self.argv[1:]) # assert self.assertEqual(res.result, 'myRG') @mock.patch.dict(os.environ, {AzConfig.env_var_name('defaults', 'group'): 'myRG'}) def test_apply_configured_defaults_on_optional_arg(self): self.set_up_command_table(required_arg=False) # action res = self.application.execute(self.argv[1:]) # assert self.assertEqual(res.result, 'myRG')
def test_client_request_id_is_refreshed_correctly(self): app = Application() app.refresh_request_id() self.assertIn('x-ms-client-request-id', app.session['headers']) old_id = app.session['headers']['x-ms-client-request-id'] app.refresh_request_id() self.assertIn('x-ms-client-request-id', app.session['headers']) self.assertNotEquals(old_id, app.session['headers']['x-ms-client-request-id'])
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 def _register_global_parser(appl): # noqa pylint: disable=protected-access appl._event_handlers[appl.GLOBAL_PARSER_CREATED].append( register_globals) mock_register_extensions.side_effect = _register_global_parser def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) command.help = """ long-summary: | line1 line2 """ cmd_table = {'n1': command} 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())
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 def _register_global_parser(appl): # noqa pylint: disable=protected-access appl._event_handlers[appl.GLOBAL_PARSER_CREATED].append(register_globals) mock_register_extensions.side_effect = _register_global_parser def test_handler(): pass command = CliCommand("n1", test_handler) command.add_argument("arg", "--arg", "-a", required=False) command.add_argument("b", "-b", required=False) command.help = """ long-summary: | line1 line2 """ cmd_table = {"n1": command} 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())
def test_generic_update_empty_nodes(self): my_obj = { 'prop': None, 'list': [], 'dict': { 'dict2': None }, 'dict3': {} } def my_get(): return my_obj def my_set(**kwargs): #pylint:disable=unused-argument return my_obj config = Configuration([]) app = Application(config) setattr(sys.modules[__name__], my_get.__name__, my_get) setattr(sys.modules[__name__], my_set.__name__, my_set) cli_generic_update_command(None, 'gencommand', '{}#{}'.format(__name__, my_get.__name__), '{}#{}'.format(__name__, my_set.__name__)) # add to prop app.execute('gencommand --add prop a=b'.split()) self.assertEqual(my_obj['prop'][0]['a'], 'b', 'verify object added to null list') self.assertEqual(len(my_obj['prop'][0]), 1, 'verify only one object added to null list') #add to list app.execute('gencommand --add list c=d'.split()) self.assertEqual(my_obj['list'][0]['c'], 'd', 'verify object added to empty list') self.assertEqual(len(my_obj['list']), 1, 'verify only one object added to empty list') # set dict2 app.execute('gencommand --set dict.dict2.e=f'.split()) self.assertEqual(my_obj['dict']['dict2']['e'], 'f', 'verify object added to null dict') self.assertEqual(len(my_obj['dict']['dict2']), 1, 'verify only one object added to null dict') #set dict3 app.execute('gencommand --set dict3.g=h'.split()) self.assertEqual(my_obj['dict3']['g'], 'h', 'verify object added to empty dict') self.assertEqual(len(my_obj['dict3']), 1, 'verify only one object added to empty dict')
def test_help_loads(self): app = Application() app.initialize(Configuration()) with mock.patch('azure.cli.core.commands.arm.APPLICATION', app): from azure.cli.core.commands.arm import add_id_parameters parser_dict = {} cmd_tbl = app.configuration.get_command_table() app.parser.load_command_table(cmd_tbl) for cmd in cmd_tbl: try: app.configuration.load_params(cmd) except KeyError: pass app.register(app.COMMAND_TABLE_PARAMS_LOADED, add_id_parameters) app.raise_event(app.COMMAND_TABLE_PARAMS_LOADED, command_table=cmd_tbl) app.parser.load_command_table(cmd_tbl) _store_parsers(app.parser, parser_dict) for name, parser in parser_dict.items(): try: help_file = _help.GroupHelpFile(name, parser) \ if _is_group(parser) \ else _help.CommandHelpFile(name, parser) help_file.load(parser) except Exception as ex: raise _help.HelpAuthoringException('{}, {}'.format( name, ex))
def test_help_params_documentations(self, _): app = Application(Configuration()) def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('foobar', '--foobar', '-fb', required=False) command.add_argument('foobar2', '--foobar2', '-fb2', required=True) command.add_argument('foobar3', '--foobar3', '-fb3', required=False, help='the foobar3') command.help = """ parameters: - name: --foobar -fb type: string required: false short-summary: one line partial sentence long-summary: text, markdown, etc. populator-commands: - az vm list - default - name: --foobar2 -fb2 type: string required: true short-summary: one line partial sentence long-summary: paragraph(s) """ cmd_table = {'n1': command} config = Configuration() config.get_command_table = lambda argv: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split()) s = """ Command az n1 Arguments --foobar2 -fb2 [Required]: One line partial sentence. Paragraph(s). --foobar -fb : One line partial sentence. Values from: az vm list, default. Text, markdown, etc. --foobar3 -fb3 : The foobar3. Global Arguments --help -h : Show this help message and exit. """ self.assertEqual(s, io.getvalue())
def test_client_request_id_is_refreshed_after_execution(self): def _handler(args): return True config = Configuration() config.get_command_table = lambda *_: {'test': CliCommand('test', _handler)} app = Application(config) app.execute(['test']) self.assertIn('x-ms-client-request-id', app.session['headers']) old_id = app.session['headers']['x-ms-client-request-id'] app.execute(['test']) self.assertIn('x-ms-client-request-id', app.session['headers']) self.assertNotEquals(old_id, app.session['headers']['x-ms-client-request-id'])
def test_choice_list_with_ints(self): def test_handler(): pass command = CliCommand("n1", test_handler) command.add_argument("arg", "--arg", "-a", required=False, choices=[1, 2, 3]) command.add_argument("b", "-b", required=False, choices=["a", "b", "c"]) cmd_table = {"n1": command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application() app.initialize(config) with self.assertRaises(SystemExit): app.execute("n1 -h".split())
def test_choice_list_with_ints(self): def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('arg', '--arg', '-a', required=False, choices=[1, 2, 3]) command.add_argument('b', '-b', required=False, choices=['a', 'b', 'c']) cmd_table = {'n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application() app.initialize(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split())
def test_help_plain_short_description(self): def test_handler(): pass command = CliCommand("n1", test_handler, description="the description") command.add_argument("arg", "--arg", "-a", required=False) command.add_argument("b", "-b", required=False) cmd_table = {"n1": command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute("n1 -h".split()) self.assertEqual(True, "n1: The description." in io.getvalue())
def test_expand_file_prefixed_files(self): f = tempfile.NamedTemporaryFile(delete=False) f.close() with open(f.name, 'w+') as stream: stream.write('foo') cases = [ [['--bar=baz'], ['--bar=baz']], [['--bar', 'baz'], ['--bar', 'baz']], [['--bar=@{}'.format(f.name)], ['--bar=foo']], [['--bar', '@{}'.format(f.name)], ['--bar', 'foo']], [['--bar', f.name], ['--bar', f.name]], [['--bar="@{}"'.format(f.name)], ['--bar=foo']], [['[email protected]'], ['[email protected]']], [['--bar', '*****@*****.**'], ['--bar', '*****@*****.**']], ] for test_case in cases: try: args = Application._expand_file_prefixed_files(test_case[0]) #pylint: disable=protected-access self.assertEqual(args, test_case[1], 'Failed for: {}'.format(test_case[0])) except CLIError as ex: self.fail('Unexpected error for {} ({}): {}'.format( test_case[0], args, ex)) os.remove(f.name)
def test_expand_file_prefixed_files(self): f = tempfile.NamedTemporaryFile(delete=False) f.close() f_with_bom = tempfile.NamedTemporaryFile(delete=False) f_with_bom.close() with open(f.name, 'w+') as stream: stream.write('foo') from codecs import open as codecs_open with codecs_open(f_with_bom.name, encoding='utf-8-sig', mode='w+') as stream: stream.write('foo') cases = [[['bar=baz'], ['bar=baz']], [['bar', 'baz'], ['bar', 'baz']], [['bar=@{}'.format(f.name)], ['bar=foo']], [['bar=@{}'.format(f_with_bom.name)], ['bar=foo']], [['bar', '@{}'.format(f.name)], ['bar', 'foo']], [['bar', f.name], ['bar', f.name]], [['[email protected]'], ['[email protected]']], [['bar', '*****@*****.**'], ['bar', '*****@*****.**']], [['bar=mymongo=@connectionstring'], ['bar=mymongo=@connectionstring']]] for test_case in cases: try: args = Application._expand_file_prefixed_files(test_case[0]) # pylint: disable=protected-access self.assertEqual(args, test_case[1], 'Failed for: {}'.format(test_case[0])) except CLIError as ex: self.fail('Unexpected error for {} ({}): {}'.format( test_case[0], args, ex)) os.remove(f.name)
def test_expand_file_prefixed_files(self): f = tempfile.NamedTemporaryFile(delete=False) f.close() f_with_bom = tempfile.NamedTemporaryFile(delete=False) f_with_bom.close() with open(f.name, 'w+') as stream: stream.write('foo') from codecs import open as codecs_open with codecs_open(f_with_bom.name, encoding='utf-8-sig', mode='w+') as stream: stream.write('foo') cases = [ [['bar=baz'], ['bar=baz']], [['bar', 'baz'], ['bar', 'baz']], [['bar=@{}'.format(f.name)], ['bar=foo']], [['bar=@{}'.format(f_with_bom.name)], ['bar=foo']], [['bar', '@{}'.format(f.name)], ['bar', 'foo']], [['bar', f.name], ['bar', f.name]], [['[email protected]'], ['[email protected]']], [['bar', '*****@*****.**'], ['bar', '*****@*****.**']], [['bar=mymongo=@connectionstring'], ['bar=mymongo=@connectionstring']] ] for test_case in cases: try: args = Application._expand_file_prefixed_files(test_case[0]) # pylint: disable=protected-access self.assertEqual(args, test_case[1], 'Failed for: {}'.format(test_case[0])) except CLIError as ex: self.fail('Unexpected error for {} ({}): {}'.format(test_case[0], args, ex)) os.remove(f.name)
def test_help_plain_short_description(self): def test_handler(): pass command = CliCommand('n1', test_handler, description='the description') command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) cmd_table = {'n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split()) self.assertEqual(True, 'n1: The description.' in io.getvalue())
def test_help_long_description_and_short_description(self): def test_handler(): pass command = CliCommand('n1', test_handler, description='short description') command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) command.help = 'long description' cmd_table = {'n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split()) self.assertEqual(True, io.getvalue().startswith('\nCommand\n az n1: Short description.\n Long description.')) # pylint: disable=line-too-long
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) # pylint: disable=protected-access def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) command.help = """ long-summary: | line1 line2 """ cmd_table = {'n1': command} 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())
def test_help_docstring_description_overrides_short_description(self): def test_handler(): pass command = CliCommand('n1', test_handler, description='short description') command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) command.help = 'short-summary: docstring summary' cmd_table = {'n1': command} config = Configuration() config.get_command_table = lambda args: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split()) self.assertEqual(True, 'n1: Docstring summary.' in io.getvalue())
def test_help_loads(self): app = Application() app.initialize(Configuration()) with mock.patch('azure.cli.core.commands.arm.APPLICATION', app): from azure.cli.core.commands.arm import add_id_parameters parser_dict = {} cmd_tbl = app.configuration.get_command_table() app.parser.load_command_table(cmd_tbl) for cmd in cmd_tbl: try: app.configuration.load_params(cmd) except KeyError: pass app.register(app.COMMAND_TABLE_PARAMS_LOADED, add_id_parameters) app.raise_event(app.COMMAND_TABLE_PARAMS_LOADED, command_table=cmd_tbl) app.parser.load_command_table(cmd_tbl) _store_parsers(app.parser, parser_dict) for name, parser in parser_dict.items(): try: help_file = _help.GroupHelpFile(name, parser) \ if _is_group(parser) \ else _help.CommandHelpFile(name, parser) help_file.load(parser) except Exception as ex: raise _help.HelpAuthoringException('{}, {}'.format(name, ex))
def test_help_long_description_from_docstring(self): """ Verifies that the first sentence of a docstring is extracted as the short description. Verifies that line breaks in the long summary are removed and leaves the text wrapping to the help system. """ def test_handler(): """Short Description. Long description with\nline break.""" pass cli_command('test', test_handler) _update_command_definitions(command_table) config = Configuration([]) app = Application(config) with self.assertRaises(SystemExit): app.execute('test -h'.split()) self.assertEqual(True, io.getvalue().startswith('\nCommand\n az test: Short Description.\n Long description with line break.')) # pylint: disable=line-too-long
def set_up_command_table(self, required_arg=False): command_table.clear() module_name = __name__ + '.' + self._testMethodName cli_command(module_name, 'test sample-vm-list', '{}#TestCommandWithConfiguredDefaults.sample_vm_list'.format(__name__)) register_cli_argument('test sample-vm-list', 'resource_group_name', CliArgumentType(options_list=('--resource-group-name', '-g'), configured_default='group', required=required_arg)) command_table['test sample-vm-list'].load_arguments() _update_command_definitions(command_table) self.argv = 'az test sample-vm-list'.split() config = Configuration(self.argv) config.get_command_table = lambda: command_table self.application = Application(config)
def test_help_long_description_and_short_description(self): def test_handler(): pass command = CliCommand("n1", test_handler, description="short description") command.add_argument("arg", "--arg", "-a", required=False) command.add_argument("b", "-b", required=False) command.help = "long description" cmd_table = {"n1": command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute("n1 -h".split()) self.assertEqual( True, io.getvalue().startswith("\nCommand\n az n1: Short description.\n Long description.") ) # pylint: disable=line-too-long
def test_help_loads(self): app = Application() with mock.patch('azure.cli.core.commands.arm.APPLICATION', app): from azure.cli.core.commands.arm import add_id_parameters parser_dict = {} cmd_tbl = app.configuration.get_command_table() app.parser.load_command_table(cmd_tbl) for cmd in cmd_tbl: try: app.configuration.load_params(cmd) except KeyError: pass app.register(app.COMMAND_TABLE_PARAMS_LOADED, add_id_parameters) app.raise_event(app.COMMAND_TABLE_PARAMS_LOADED, command_table=cmd_tbl) app.parser.load_command_table(cmd_tbl) _store_parsers(app.parser, parser_dict) for name, parser in parser_dict.items(): try: help_file = _help.GroupHelpFile(name, parser) \ if _is_group(parser) \ else _help.CommandHelpFile(name, parser) help_file.load(parser) except Exception as ex: raise _help.HelpAuthoringException('{}, {}'.format(name, ex)) extras = [k for k in azure.cli.core.help_files.helps.keys() if k not in parser_dict] self.assertTrue(len(extras) == 0, 'Found help files that don\'t map to a command: '+ str(extras))
def test_help_full_documentations(self, _): app = Application(Configuration([])) def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('foobar', '--foobar', '-fb', required=False) command.add_argument('foobar2', '--foobar2', '-fb2', required=True) command.help = """ short-summary: this module does xyz one-line or so long-summary: | this module.... kjsdflkj... klsfkj paragraph1 this module.... kjsdflkj... klsfkj paragraph2 parameters: - name: --foobar -fb type: string required: false short-summary: one line partial sentence long-summary: text, markdown, etc. populator-commands: - az vm list - default - name: --foobar2 -fb2 type: string required: true short-summary: one line partial sentence long-summary: paragraph(s) examples: - name: foo example text: example details """ cmd_table = {'n1': command} 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: This module does xyz one-line or so. This module.... kjsdflkj... klsfkj paragraph1 this module.... kjsdflkj... klsfkj paragraph2. Arguments --foobar2 -fb2 [Required]: One line partial sentence. Paragraph(s). --foobar -fb : One line partial sentence. Values from: az vm list, default. Text, markdown, etc. Global Arguments --help -h : Show this help message and exit. Examples foo example example details """ self.assertEqual(s, io.getvalue())
def test_help_long_description_multi_line(self): def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) command.help = """ long-summary: | line1 line2 """ cmd_table = {'n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split()) self.assertEqual(True, io.getvalue().startswith('\nCommand\n az n1\n Line1\n line2.')) # pylint: disable=line-too-long
def test_help_extra_missing_params(self): app = Application(Configuration([])) def test_handler(foobar2, foobar=None): # pylint: disable=unused-argument pass command = CliCommand("n1", test_handler) command.add_argument("foobar", "--foobar", "-fb", required=False) command.add_argument("foobar2", "--foobar2", "-fb2", required=True) cmd_table = {"n1": command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) # work around an argparse behavior where output is not printed and SystemExit # is not raised on Python 2.7.9 if sys.version_info < (2, 7, 10): try: app.execute("n1 -fb a --foobar value".split()) except SystemExit: pass try: app.execute("n1 -fb a --foobar2 value --foobar3 extra".split()) except SystemExit: pass 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()) 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() )
def test_help_param(self): def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('arg', '--arg', '-a', required=False) command.add_argument('b', '-b', required=False) cmd_table = {'n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application() app.initialize(config) with self.assertRaises(SystemExit): app.execute('n1 -h'.split()) with self.assertRaises(SystemExit): app.execute('n1 --help'.split())
def test_help_params_documentations(self, _): app = Application(Configuration([])) def test_handler(): pass command = CliCommand('n1', test_handler) command.add_argument('foobar', '--foobar', '-fb', required=False) command.add_argument('foobar2', '--foobar2', '-fb2', required=True) command.add_argument('foobar3', '--foobar3', '-fb3', required=False, help='the foobar3') command.help = """ parameters: - name: --foobar -fb type: string required: false short-summary: one line partial sentence long-summary: text, markdown, etc. populator-commands: - az vm list - default - name: --foobar2 -fb2 type: string required: true short-summary: one line partial sentence long-summary: paragraph(s) """ cmd_table = {'n1': command} 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 Arguments --foobar2 -fb2 [Required]: One line partial sentence. Paragraph(s). --foobar -fb : One line partial sentence. Values from: az vm list, default. Text, markdown, etc. --foobar3 -fb3 : The foobar3. Global Arguments --help -h : Show this help message and exit. """ self.assertEqual(s, io.getvalue())
def set_up_command_table(self, required_arg=False): command_table.clear() module_name = __name__ + '.' + self._testMethodName cli_command(module_name, 'test sample-vm-list', '{}#TestCommandWithConfiguredDefaults.sample_vm_list'.format(__name__)) register_cli_argument('test sample-vm-list', 'resource_group_name', CliArgumentType(options_list=('--resource-group-name', '-g'), configured_default='group', required=required_arg)) command_table['test sample-vm-list'].load_arguments() _update_command_definitions(command_table) self.argv = 'az test sample-vm-list'.split() config = Configuration() config.get_command_table = lambda argv: command_table self.application = Application(config)
def test_generic_update_empty_nodes(self): my_obj = {"prop": None, "list": [], "dict": {"dict2": None}, "dict3": {}} def my_get(): return my_obj def my_set(**kwargs): # pylint:disable=unused-argument return my_obj config = Configuration([]) app = Application(config) setattr(sys.modules[__name__], my_get.__name__, my_get) setattr(sys.modules[__name__], my_set.__name__, my_set) cli_generic_update_command( None, "gencommand", "{}#{}".format(__name__, my_get.__name__), "{}#{}".format(__name__, my_set.__name__) ) # add to prop app.execute("gencommand --add prop a=b".split()) self.assertEqual(my_obj["prop"][0]["a"], "b", "verify object added to null list") self.assertEqual(len(my_obj["prop"][0]), 1, "verify only one object added to null list") # add to list app.execute("gencommand --add list c=d".split()) self.assertEqual(my_obj["list"][0]["c"], "d", "verify object added to empty list") self.assertEqual(len(my_obj["list"]), 1, "verify only one object added to empty list") # set dict2 app.execute("gencommand --set dict.dict2.e=f".split()) self.assertEqual(my_obj["dict"]["dict2"]["e"], "f", "verify object added to null dict") self.assertEqual(len(my_obj["dict"]["dict2"]), 1, "verify only one object added to null dict") # set dict3 app.execute("gencommand --set dict3.g=h".split()) self.assertEqual(my_obj["dict3"]["g"], "h", "verify object added to empty dict") self.assertEqual(len(my_obj["dict3"]), 1, "verify only one object added to empty dict")
def test_help_param(self): def test_handler(): pass command = CliCommand("n1", test_handler) command.add_argument("arg", "--arg", "-a", required=False) command.add_argument("b", "-b", required=False) cmd_table = {"n1": command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application() app.initialize(config) with self.assertRaises(SystemExit): app.execute("n1 -h".split()) with self.assertRaises(SystemExit): app.execute("n1 --help".split())
def test_client_request_id_is_refreshed_after_execution(self): def _handler(args): return True config = Configuration() config.get_command_table = lambda *_: { 'test': CliCommand('test', _handler) } app = Application(config) app.execute(['test']) self.assertIn('x-ms-client-request-id', app.session['headers']) old_id = app.session['headers']['x-ms-client-request-id'] app.execute(['test']) self.assertIn('x-ms-client-request-id', app.session['headers']) self.assertNotEquals(old_id, app.session['headers']['x-ms-client-request-id'])
def test_client_request_id_is_not_assigned_when_application_is_created( self): app = Application() self.assertNotIn('x-ms-client-request-id', app.session['headers'])
def test_application_register_and_call_handlers(self): handler_called = [False] def handler(**kwargs): kwargs['args'][0] = True def other_handler(**kwargs): # pylint: disable=unused-variable self.assertEqual(kwargs['args'], 'secret sauce') app = Application() app.initialize(Configuration()) app.raise_event('was_handler_called', args=handler_called) self.assertFalse( handler_called[0], "Raising event with no handlers registered somehow failed...") app.register('was_handler_called', handler) self.assertFalse(handler_called[0]) # Registered handler won't get called if event with different name # is raised... app.raise_event('other_handler_called', args=handler_called) self.assertFalse(handler_called[0], 'Wrong handler called!') app.raise_event('was_handler_called', args=handler_called) self.assertTrue(handler_called[0], "Handler didn't get called") app.raise_event('other_handler_called', args='secret sauce')
def test_application_register_and_call_handlers(self): handler_called = [False] def handler(**kwargs): kwargs['args'][0] = True def other_handler(**kwargs): self.assertEqual(kwargs['args'], 'secret sauce') app = Application() app.initialize(Configuration()) app.raise_event('was_handler_called', args=handler_called) self.assertFalse(handler_called[0], "Raising event with no handlers registered somehow failed...") app.register('was_handler_called', handler) self.assertFalse(handler_called[0]) # Registered handler won't get called if event with different name # is raised... app.raise_event('other_handler_called', args=handler_called) self.assertFalse(handler_called[0], 'Wrong handler called!') app.raise_event('was_handler_called', args=handler_called) self.assertTrue(handler_called[0], "Handler didn't get called") app.raise_event('other_handler_called', args='secret sauce')
def _test(cmd_line): argv = cmd_line.split() config = Configuration() config.get_command_table = lambda argv: cmd_table application = Application(config) return application.execute(argv[1:])
def test_generic_update(self): # pylint: disable=too-many-statements my_obj = TestObject() def my_get(): return my_obj def my_set(**kwargs): #pylint:disable=unused-argument return my_obj config = Configuration([]) app = Application(config) setattr(sys.modules[__name__], my_get.__name__, my_get) setattr(sys.modules[__name__], my_set.__name__, my_set) cli_generic_update_command(None, 'update-obj', '{}#{}'.format(__name__, my_get.__name__), '{}#{}'.format(__name__, my_set.__name__)) # Test simplest ways of setting properties app.execute('update-obj --set myProp=newValue'.split()) self.assertEqual(my_obj.my_prop, 'newValue', 'set simple property') app.execute('update-obj --set myProp=val3'.split()) self.assertEqual(my_obj.my_prop, 'val3', 'set simple property again') app.execute('update-obj --set myList[0]=newValA'.split()) self.assertEqual(my_obj.my_list[0], 'newValA', 'set simple list element') app.execute('update-obj --set myList[-4]=newValB'.split()) self.assertEqual(my_obj.my_list[0], 'newValB', 'set simple list element') app.execute('update-obj --set myDict.myCamelKey=success'.split()) self.assertEqual(my_obj.my_dict['myCamelKey'], 'success', 'set simple dict element with camel case key') app.execute('update-obj --set myDict.my_snake_key=success'.split()) self.assertEqual(my_obj.my_dict['my_snake_key'], 'success', 'set simple dict element with snake case key') # Test the different ways of indexing into a list of objects or dictionaries by filter app.execute( 'update-obj --set myListOfCamelDicts[myKey=value_2].myKey=new_value' .split()) self.assertEqual(my_obj.my_list_of_camel_dicts[1]['myKey'], 'new_value', 'index into list of dictionaries by camel-case key') app.execute( 'update-obj --set myListOfSnakeDicts[my_key=value2].my_key=new_value' .split()) self.assertEqual(my_obj.my_list_of_snake_dicts[1]['my_key'], 'new_value', 'index into list of dictionaries by snake-case key') app.execute( 'update-obj --set myListOfObjects[myString=1.2.3.4].myString=new_value' .split()) self.assertEqual(my_obj.my_list_of_objects[1].my_string, 'new_value', 'index into list of objects by key') # Test setting on elements nested within lists app.execute('update-obj --set myList[1][1]=newValue'.split()) self.assertEqual(my_obj.my_list[1][1], 'newValue', 'set nested list element') app.execute('update-obj --set myList[2].myKey=newValue'.split()) self.assertEqual(my_obj.my_list[2]['myKey'], 'newValue', 'set nested dict element') app.execute('update-obj --set myList[3].myInt=50'.split()) self.assertEqual(my_obj.my_list[3].my_int, 50, 'set nested object element') # Test overwriting and removing values app.execute('update-obj --set myProp={} myProp.foo=bar'.split()) self.assertEqual(my_obj.my_prop['foo'], 'bar', 'replace scalar with dict') app.execute( 'update-obj --set myProp=[] --add myProp key1=value1 --set myProp[0].key2=value2' .split()) self.assertEqual(my_obj.my_prop[0]['key1'], 'value1', 'replace scalar with new list and add a dict entry') self.assertEqual(my_obj.my_prop[0]['key2'], 'value2', 'add a second value to the new dict entry') app.execute( 'update-obj --remove myProp --add myProp str1 str2 --remove myProp 0' .split()) self.assertEqual(len(my_obj.my_prop), 1, 'nullify property, add two and remove one') self.assertEqual(my_obj.my_prop[0], 'str2', 'nullify property, add two and remove one') # Test various --add to lists app.execute('update-obj --set myList=[]'.split()) app.execute( shlex.split( 'update-obj --add myList key1=value1 key2=value2 foo "string in quotes" [] {} foo=bar' )) self.assertEqual(my_obj.my_list[0]['key1'], 'value1', 'add a value to a dictionary') self.assertEqual(my_obj.my_list[0]['key2'], 'value2', 'add a second value to the dictionary') self.assertEqual(my_obj.my_list[1], 'foo', 'add scalar value to list') self.assertEqual(my_obj.my_list[2], 'string in quotes', 'add scalar value with quotes to list') self.assertEqual(my_obj.my_list[3], [], 'add list to a list') self.assertEqual(my_obj.my_list[4], {}, 'add dict to a list') self.assertEqual(my_obj.my_list[-1]['foo'], 'bar', 'add second dict and verify when dict is at the end') # Test --remove self.assertEqual(len(my_obj.my_list), 6, 'pre-verify length of list') app.execute('update-obj --remove myList -2'.split()) self.assertEqual(len(my_obj.my_list), 5, 'verify one item removed') self.assertEqual(my_obj.my_list[4]['foo'], 'bar', 'verify correct item removed') self.assertEqual('key1' in my_obj.my_list[0], True, 'verify dict item exists') app.execute('update-obj --remove myList[0].key1'.split()) self.assertEqual('key1' not in my_obj.my_list[0], True, 'verify dict entry can be removed')
# -------------------------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- import argparse import json from docutils import nodes from docutils.statemachine import ViewList from sphinx.util.compat import Directive from sphinx.util.nodes import nested_parse_with_titles from azure.cli.core.application import Application, Configuration import azure.cli.core._help as _help app = Application(Configuration()) for cmd in app.configuration.get_command_table(): try: app.execute(cmd.split() + ['-h']) except: pass class AzHelpGenDirective(Directive): def make_rst(self): INDENT = ' ' DOUBLEINDENT = INDENT * 2 parser_keys = [] parser_values = [] sub_parser_keys = [] sub_parser_values = []
def test_generic_update_errors(self): #pylint: disable=no-self-use my_obj = TestObject() def my_get(a1, a2): #pylint: disable=unused-argument return my_obj def my_set(**kwargs): #pylint:disable=unused-argument return my_obj config = Configuration([]) app = Application(config) setattr(sys.modules[__name__], my_get.__name__, my_get) setattr(sys.modules[__name__], my_set.__name__, my_set) cli_generic_update_command(None, 'gencommand', '{}#{}'.format(__name__, my_get.__name__), '{}#{}'.format(__name__, my_set.__name__)) def _execute_with_error(command, error, message): try: app.execute(command.split()) except CLIError as err: if not error in str(err): raise AssertionError('{}\nExpected: {}\nActual: {}'.format( message, error, str(err))) else: raise AssertionError('exception not thrown') missing_remove_message = "Couldn't find 'doesntExist' in ''. Available options: ['myDict', 'myList', 'myListOfCamelDicts', 'myListOfObjects', 'myListOfSnakeDicts', 'myProp']" _execute_with_error('gencommand --a1 1 --a2 2 --remove doesntExist', missing_remove_message, 'remove non-existent property by name') _execute_with_error('gencommand --a1 1 --a2 2 --remove doesntExist 2', missing_remove_message, 'remove non-existent property by index') remove_prop_message = "Couldn't find 'doesntExist' in 'myList.doesntExist'. Available options: index into the collection 'myList.doesntExist' with [<index>] or [<key=value>]" _execute_with_error( 'gencommand --a1 1 --a2 2 --remove myList.doesntExist.missing 2', remove_prop_message, 'remove non-existent sub-property by index') _execute_with_error('gencommand --a1 1 --a2 2 --remove myList 20', "index 20 doesn't exist on myList", 'remove out-of-range index') set_on_list_message = "Couldn't find 'doesnt_exist' in 'myList'. Available options: index into the collection 'myList' with [<index>] or [<key=value>]" _execute_with_error( 'gencommand --a1 1 --a2 2 --set myList.doesnt_exist=foo', set_on_list_message, 'set shouldn\'t work on a list') _execute_with_error( 'gencommand --a1 1 --a2 2 --set myList.doesnt_exist.doesnt_exist2=foo', set_on_list_message, 'set shouldn\'t work on a list') _execute_with_error( 'gencommand --a1 1 --a2 2 --set myList[5].doesnt_exist=foo', "index 5 doesn't exist on myList", 'index out of range in path') _execute_with_error( 'gencommand --a1 1 --a2 2 --remove myList[0]', 'invalid syntax: --remove property.list <indexToRemove> OR --remove propertyToRemove', 'remove requires index to be space-separated') app.execute( "gencommand --a1 1 --a2 2 --set myDict={'foo':'bar'}".split()) _execute_with_error( 'gencommand --a1 1 --a2 2 --set myDict.foo.doo=boo', "Couldn't find 'foo' in 'myDict'. 'myDict' does not support further indexing.", 'Cannot dot index from a scalar value') _execute_with_error( 'gencommand --a1 1 --a2 2 --set myDict.foo[0]=boo', "Couldn't find 'foo' in 'myDict'. 'myDict' does not support further indexing.", 'Cannot list index from a scalar value') _execute_with_error( 'gencommand --a1 1 --a2 2 --add myDict la=da', "invalid syntax: --add property.listProperty <key=value, string or JSON string>", 'Add only works with lists') # add an entry which makes 'myKey' no longer unique app.execute( 'gencommand --a1 1 --a2 2 --add myListOfCamelDicts myKey=value_2'. split()) _execute_with_error( 'gencommand --a1 1 --a2 2 --set myListOfCamelDicts[myKey=value_2].myKey=foo', "non-unique key 'myKey' found multiple matches on myListOfCamelDicts. " "Key must be unique.", 'indexing by key must be unique') _execute_with_error( 'gencommand --a1 1 --a2 2 --set myListOfCamelDicts[myKey=foo].myKey=foo', "item with value 'foo' doesn\'t exist for key 'myKey' on myListOfCamelDicts", 'no match found when indexing by key and value')
def test_help_group_help(self): app = Application(Configuration([])) def test_handler(): pass azure.cli.core.help_files.helps['test_group1 test_group2'] = """ type: group short-summary: this module does xyz one-line or so long-summary: | this module.... kjsdflkj... klsfkj paragraph1 this module.... kjsdflkj... klsfkj paragraph2 examples: - name: foo example text: example details """ command = CliCommand('test_group1 test_group2 n1', test_handler) command.add_argument('foobar', '--foobar', '-fb', required=False) command.add_argument('foobar2', '--foobar2', '-fb2', required=True) command.help = """ short-summary: this module does xyz one-line or so long-summary: | this module.... kjsdflkj... klsfkj paragraph1 this module.... kjsdflkj... klsfkj paragraph2 parameters: - name: --foobar -fb type: string required: false short-summary: one line partial sentence long-summary: text, markdown, etc. populator-commands: - az vm list - default - name: --foobar2 -fb2 type: string required: true short-summary: one line partial sentence long-summary: paragraph(s) examples: - name: foo example text: example details """ cmd_table = {'test_group1 test_group2 n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) with self.assertRaises(SystemExit): app.execute('test_group1 test_group2 --help'.split()) s = """ Group az test_group1 test_group2: This module does xyz one-line or so. This module.... kjsdflkj... klsfkj paragraph1 this module.... kjsdflkj... klsfkj paragraph2. Commands: n1: This module does xyz one-line or so. Examples foo example example details """ self.assertEqual(s, io.getvalue()) del azure.cli.core.help_files.helps['test_group1 test_group2']
def test_help_extra_missing_params(self): app = Application(Configuration([])) def test_handler(foobar2, foobar=None): # pylint: disable=unused-argument pass command = CliCommand('n1', test_handler) command.add_argument('foobar', '--foobar', '-fb', required=False) command.add_argument('foobar2', '--foobar2', '-fb2', required=True) cmd_table = {'n1': command} config = Configuration([]) config.get_command_table = lambda: cmd_table app = Application(config) # work around an argparse behavior where output is not printed and SystemExit # is not raised on Python 2.7.9 if sys.version_info < (2, 7, 10): try: app.execute('n1 -fb a --foobar value'.split()) except SystemExit: pass try: app.execute('n1 -fb a --foobar2 value --foobar3 extra'.split()) except SystemExit: pass 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()) 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())