Example #1
0
    def test_prefix_file_expansion(self):
        import json, os

        def test_handler():
            pass

        def create_test_file(file, contents):
            with open(file, 'w') as f:
                f.write(contents)

        def remove_test_file(file):
            os.remove(file)

        json_test_data = json.dumps({'one': 1, 'two': 2, 'three': 3})
        create_test_file('test.json', json_test_data)

        command = CLICommand(self.mock_ctx, 'test command', test_handler)
        command.add_argument('json_data', '--param')
        cmd_table = {'test command': command}
        self.mock_ctx.commands_loader.command_table = cmd_table
        parser = CLICommandParser()
        parser.load_command_table(self.mock_ctx.commands_loader)

        args = parser.parse_args('test command --param @test.json'.split())
        self.assertEqual(json_test_data, args.json_data)

        remove_test_file('test.json')
Example #2
0
    def test_register_simple_commands(self):
        def test_handler1():
            pass

        def test_handler2():
            pass

        command = CLICommand(self.mock_ctx, 'command the-name', test_handler1)
        command2 = CLICommand(self.mock_ctx, 'sub-command the-second-name',
                              test_handler2)
        cmd_table = {
            'command the-name': command,
            'sub-command the-second-name': command2
        }

        parser = CLICommandParser()
        parser.load_command_table(cmd_table)
        args = parser.parse_args('command the-name'.split())
        self.assertIs(args.func, command)

        args = parser.parse_args('sub-command the-second-name'.split())
        self.assertIs(args.func, command2)

        CLICommandParser.error = VerifyError(self, )
        parser.parse_args('sub-command'.split())
        self.assertTrue(CLICommandParser.error.called)
Example #3
0
    def test_case_insensitive_command_path(self):
        def handler(_):
            return 'PASSED'

        command = CLICommand(self.mock_ctx, 'test command', handler)
        command.add_argument('var', '--var', '-v')
        cmd_table = {'test command': command}

        def _test(cmd_line):
            ci = CommandInvoker(cli_ctx=self.mock_ctx)
            self.mock_ctx.invocation = ci
            self.mock_ctx.invocation.commands_loader.command_table = cmd_table
            return self.mock_ctx.invocation.execute(cmd_line.split())

        # case insensitive command paths
        result = _test('TEST command --var blah')
        self.assertEqual(result.result, 'PASSED')

        result = _test('test COMMAND --var blah')
        self.assertEqual(result.result, 'PASSED')

        result = _test('test command -v blah')
        self.assertEqual(result.result, 'PASSED')

        # verify that long and short options remain case sensitive
        with mock.patch('sys.stderr', new_callable=StringIO):
            with self.assertRaises(SystemExit):
                _test('test command --vAR blah')

            with self.assertRaises(SystemExit):
                _test('test command -V blah')
Example #4
0
    def test_case_insensitive_enum_choices(self):
        from enum import Enum

        class TestEnum(Enum):  # pylint: disable=too-few-public-methods

            opt1 = "ALL_CAPS"
            opt2 = "camelCase"
            opt3 = "snake_case"

        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, 'test command', test_handler)
        command.add_argument('opt',
                             '--opt',
                             required=True,
                             **enum_choice_list(TestEnum))
        cmd_table = {'test command': command}

        parser = CLICommandParser()
        parser.load_command_table(cmd_table)

        args = parser.parse_args('test command --opt alL_cAps'.split())
        self.assertEqual(args.opt, 'ALL_CAPS')

        args = parser.parse_args('test command --opt CAMELCASE'.split())
        self.assertEqual(args.opt, 'camelCase')

        args = parser.parse_args('test command --opt sNake_CASE'.split())
        self.assertEqual(args.opt, 'snake_case')
Example #5
0
    def test_extra_nonargparse_parameters(self):
        """ Add argument that has non argparse parameters.

            'mycustomarg' should be filtered out and load_command_table
            should complete successfully instead of throwing
            TypeError: __init__() got an unexpected keyword argument 'mycustomarg'
        """
        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, 'test command', test_handler)
        command.add_argument('req', '--req', required=True, mycustomarg=True)
        cmd_table = {'test command': command}
        parser = CLICommandParser()
        parser.load_command_table(cmd_table)
Example #6
0
    def test_nargs_parameter(self):
        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, 'test command', test_handler)
        command.add_argument('req', '--req', required=True, nargs=2)
        cmd_table = {'test command': command}

        parser = CLICommandParser()
        parser.load_command_table(cmd_table)

        args = parser.parse_args('test command --req yep nope'.split())
        self.assertIs(args.func, command)

        CLICommandParser.error = VerifyError(self)
        parser.parse_args('test command -req yep'.split())
        self.assertTrue(CLICommandParser.error.called)
Example #7
0
    def test_required_parameter(self):
        def test_handler(args):  # pylint: disable=unused-argument
            pass

        command = CLICommand(self.mock_ctx, 'test command', test_handler)
        command.add_argument('req', '--req', required=True)
        cmd_table = {'test command': command}
        self.mock_ctx.commands_loader.command_table = cmd_table

        parser = CLICommandParser()
        parser.load_command_table(self.mock_ctx.commands_loader)

        args = parser.parse_args('test command --req yep'.split())
        self.assertIs(args.func, command)

        CLICommandParser.error = VerifyError(self)
        parser.parse_args('test command'.split())
        self.assertTrue(CLICommandParser.error.called)
Example #8
0
    def test_help_full_documentations(self, _):
        def test_handler():
            pass

        self.mock_ctx = MockContext()
        command = CLICommand(self.mock_ctx, '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:
                        - mycli abc xyz
                        - 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}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 -h'.split())
        s = """
Command
    {} 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: mycli abc xyz, default.
        Text, markdown, etc.

Global Arguments
    --help -h                : Show this help message and exit.

Examples
    foo example
        example details

"""
        self.assertEqual(s.format(self.cliname), io.getvalue())
Example #9
0
    def test_help_extra_missing_params(self):
        def test_handler(foobar2, foobar=None):  # pylint: disable=unused-argument
            pass

        command = CLICommand(self.mock_ctx, 'n1', test_handler)
        command.add_argument('foobar', '--foobar', '-fb', required=False)
        command.add_argument('foobar2', '--foobar2', '-fb2', required=True)
        cmd_table = {'n1': command}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            # 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:
                    self.mock_ctx.invoke('n1 -fb a --foobar value'.split())
                except SystemExit:
                    pass

                try:
                    self.mock_ctx.invoke('n1 -fb a --foobar2 value --foobar3 extra'.split())
                except SystemExit:
                    pass
            else:
                with self.assertRaises(SystemExit):
                    self.mock_ctx.invoke('n1 -fb a --foobar value'.split())
                with self.assertRaises(SystemExit):
                    self.mock_ctx.invoke('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())
Example #10
0
    def test_help_with_param_specified(self, _):
        def test_handler():
            pass

        self.mock_ctx = MockContext()
        command = CLICommand(self.mock_ctx, 'n1', test_handler)
        command.add_argument('arg', '--arg', '-a', required=False)
        command.add_argument('b', '-b', required=False)
        cmd_table = {'n1': command}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 --arg foo -h'.split())

        s = """
Command
    {} n1

Arguments
    --arg -a
    -b

Global Arguments
    --help -h: Show this help message and exit.
"""

        self.assertEqual(s.format(self.cliname), io.getvalue())
Example #11
0
    def test_help_params_documentations(self, _):
        def test_handler():
            pass

        self.mock_ctx = MockContext()
        command = CLICommand(self.mock_ctx, '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:
                    - mycli abc xyz
                    - default
                - name: --foobar2 -fb2
                  type: string
                  required: true
                  short-summary: one line partial sentence
                  long-summary: paragraph(s)
            """
        cmd_table = {'n1': command}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 -h'.split())
        s = """
Command
    {} n1

Arguments
    --foobar2 -fb2 [Required]: One line partial sentence.
        Paragraph(s).
    --foobar -fb             : One line partial sentence.  Values from: mycli abc xyz, default.
        Text, markdown, etc.
    --foobar3 -fb3           : The foobar3.

Global Arguments
    --help -h                : Show this help message and exit.
"""
        self.assertEqual(s.format(self.cliname), io.getvalue())
Example #12
0
    def test_help_docstring_description_overrides_short_description(self):
        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, '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}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 -h'.split())
            self.assertTrue('n1: Docstring summary.' in io.getvalue())
Example #13
0
    def test_help_long_description_and_short_description(self):
        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, '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}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 -h'.split())
            self.assertTrue(io.getvalue().startswith('\nCommand\n    {} n1: Short description.\n        Long description.'.format(self.cliname)))  # pylint: disable=line-too-long
Example #14
0
    def test_choice_list_with_ints(self):
        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, '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}
        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 -h'.split())
Example #15
0
    def test_list_value_parameter(self):
        handler_args = {}
        def handler(args):
            handler_args.update(args)

        command = CLICommand(self.mock_ctx, 'test command', handler)
        command.add_argument('hello', '--hello', nargs='+')
        command.add_argument('something', '--something')
        cmd_table = {'test command': command}
        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            self.mock_ctx.invoke('test command --hello world sir --something else'.split())
        self.assertEqual(handler_args['something'], 'else')
        self.assertEqual(handler_args['hello'][0], 'world')
        self.assertEqual(handler_args['hello'][1], 'sir')
Example #16
0
    def test_help_param(self):
        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, 'n1', test_handler)
        command.add_argument('arg', '--arg', '-a', required=False)
        command.add_argument('b', '-b', required=False)
        cmd_table = {'n1': command}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 -h'.split())

            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 --help'.split())
Example #17
0
    def test_list_value_parameter(self):
        handler_args = {}

        def handler(args):
            handler_args.update(args)

        command = CLICommand(self.mock_ctx, 'test command', handler)
        command.add_argument('hello', '--hello', nargs='+')
        command.add_argument('something', '--something')
        cmd_table = {'test command': command}
        self.invoke_with_command_table(
            'test command --hello world sir --something else', cmd_table)
        self.assertEqual(handler_args['something'], 'else')
        self.assertEqual(handler_args['hello'][0], 'world')
        self.assertEqual(handler_args['hello'][1], 'sir')
Example #18
0
    def test_help_global_params(self, _):

        def register_globals(_, **kwargs):
            arg_group = kwargs.get('arg_group')
            arg_group.add_argument('--exampl',
                                   help='This is a new global argument.')

        self.mock_ctx = MockContext()
        self.mock_ctx._event_handlers[EVENT_PARSER_GLOBAL_CREATE].append(register_globals)  # pylint: disable=protected-access

        def test_handler():
            pass

        command = CLICommand(self.mock_ctx, '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}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('n1 -h'.split())

        s = """
Command
    {} n1
        Line1
        line2.

Arguments
    --arg -a
    -b

Global Arguments
    --exampl : This is a new global argument.
    --help -h: Show this help message and exit.
"""
        self.assertEqual(s.format(self.cliname), io.getvalue())
Example #19
0
    def test_help_group_children(self):
        def test_handler():
            pass

        def test_handler2():
            pass

        command = CLICommand(self.mock_ctx, 'group1 group3 n1', test_handler)
        command.add_argument('foobar', '--foobar', '-fb', required=False)
        command.add_argument('foobar2', '--foobar2', '-fb2', required=True)

        command2 = CLICommand(self.mock_ctx, '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}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('group1 -h'.split())
            s = '\nGroup\n    {} group1\n\nSubgroups:\n    group2\n    group3\n\n'.format(self.cliname)
            self.assertEqual(s, io.getvalue())
Example #20
0
    def test_help_group_help(self):
        def test_handler():
            pass
        from knack.help_files import helps
        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(self.mock_ctx, '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:
                    - mycli abc xyz
                    - 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}

        with mock.patch.object(CLICommandsLoader, 'load_command_table', return_value=cmd_table):
            with self.assertRaises(SystemExit):
                self.mock_ctx.invoke('test_group1 test_group2 --help'.split())
        s = """
Group
    {} 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.format(self.cliname), io.getvalue())
        del helps['test_group1 test_group2']
Example #21
0
 def load_command_table(self, args):
     self.command_table['abc xyz'] = CLICommand(
         self.cli_ctx, 'abc xyz', a_test_command_handler)
     self.command_table['abc list'] = CLICommand(
         self.cli_ctx, 'abc list', a_test_command_handler)
     return OrderedDict(self.command_table)