From 95d2d470c68b97b332a67f42bcc434ec6da7c2f9 Mon Sep 17 00:00:00 2001 From: Kevin Van Brunt Date: Mon, 4 Mar 2019 01:21:06 -0500 Subject: [PATCH] Fixed exception caused by using preserve_quotes argument of with_argument_list decorator --- CHANGELOG.md | 4 ++++ cmd2/cmd2.py | 19 ++++++++++--------- docs/argument_processing.rst | 2 +- docs/freefeatures.rst | 13 ------------- examples/arg_print.py | 2 +- examples/decorator_example.py | 2 +- examples/exit_code.py | 2 +- examples/hooks.py | 2 +- examples/paged_output.py | 4 ++-- examples/python_scripting.py | 2 +- examples/tab_completion.py | 2 +- tests/test_argparse.py | 6 +++--- tests/test_cmd2.py | 2 +- 13 files changed, 27 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1139853fa..4824d55ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ ``AutoCompleter`` which has since developed a dependency on ``cmd2`` methods. * Removed ability to call commands in ``pyscript`` as if they were functions (e.g ``app.help()``) in favor of only supporting one ``pyscript`` interface. This simplifies future maintenance. + * To fix an exception caused by passing arguments to ``@with_argument_list``, the basic usage of this + decorator had to change. It must now always have parenthesis. + * @with_argument_list() instead of @with_argument_list + ## 0.9.10 (February 22, 2019) * Bug Fixes diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 24e140fda..1577be414 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -175,25 +175,26 @@ def cat_decorator(func): return cat_decorator -def with_argument_list(func: Callable[[Statement], Optional[bool]], - preserve_quotes: bool = False) -> Callable[[List], Optional[bool]]: +def with_argument_list(preserve_quotes: bool = False) -> Callable[[List], Optional[bool]]: """A decorator to alter the arguments passed to a do_* cmd2 method. Default passes a string of whatever the user typed. With this decorator, the decorated method will receive a list of arguments parsed from user input using shlex.split(). - :param func: do_* method this decorator is wrapping :param preserve_quotes: if True, then argument quotes will not be stripped :return: function that gets passed a list of argument strings """ import functools - @functools.wraps(func) - def cmd_wrapper(self, cmdline): - lexed_arglist = parse_quoted_string(cmdline, preserve_quotes) - return func(self, lexed_arglist) + def arg_decorator(func: Callable[[Statement], Optional[bool]]): + @functools.wraps(func) + def cmd_wrapper(self, cmdline): + lexed_arglist = parse_quoted_string(cmdline, preserve_quotes) + return func(self, lexed_arglist) - cmd_wrapper.__doc__ = func.__doc__ - return cmd_wrapper + cmd_wrapper.__doc__ = func.__doc__ + return cmd_wrapper + + return arg_decorator def with_argparser_and_unknown_args(argparser: argparse.ArgumentParser, preserve_quotes: bool = False) -> \ diff --git a/docs/argument_processing.rst b/docs/argument_processing.rst index 4c77fa803..befaa0d18 100644 --- a/docs/argument_processing.rst +++ b/docs/argument_processing.rst @@ -371,7 +371,7 @@ argument list instead of a string:: # cmdline contains a string pass - @with_argument_list + @with_argument_list() def do_speak(self, arglist): # arglist contains a list of arguments pass diff --git a/docs/freefeatures.rst b/docs/freefeatures.rst index c70a2d93b..befac60e9 100644 --- a/docs/freefeatures.rst +++ b/docs/freefeatures.rst @@ -217,19 +217,6 @@ of using ``pyscript`` is shown below along with the **examples/arg_printer.py** arg 2: 'bar' arg 3: 'baz' -.. note:: - - If you want to be able to pass arguments with spaces to scripts, then we strongly recommend using one of the decorators, - such as ``with_argument_list``. ``cmd2`` will pass your **do_*** methods a list of arguments in this case. - - When using this decorator, you can then put arguments in quotes like so (NOTE: the ``do_pyscript`` method uses this decorator:: - - (Cmd) pyscript examples/arg_printer.py hello '23 fnord' - Running Python script 'arg_printer.py' which was called with 2 arguments - arg 1: 'hello' - arg 2: '23 fnord' - - IPython (optional) ================== diff --git a/examples/arg_print.py b/examples/arg_print.py index 1a1038589..4e35e130e 100755 --- a/examples/arg_print.py +++ b/examples/arg_print.py @@ -33,7 +33,7 @@ def do_aprint(self, statement): self.poutput('statement.argv = {!r}'.format(statement.argv)) self.poutput('statement.command = {!r}'.format(statement.command)) - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_lprint(self, arglist): """Print the argument list this basic command is called with.""" self.poutput('lprint was called with the following list of arguments: {!r}'.format(arglist)) diff --git a/examples/decorator_example.py b/examples/decorator_example.py index 5d127619b..d5c038e6f 100755 --- a/examples/decorator_example.py +++ b/examples/decorator_example.py @@ -71,7 +71,7 @@ def do_tag(self, args): """create a html tag""" self.poutput('<{0}>{1}'.format(args.tag, ' '.join(args.content))) - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_tagg(self, arglist): """verion of creating an html tag using arglist instead of argparser""" if len(arglist) >= 2: diff --git a/examples/exit_code.py b/examples/exit_code.py index 8ae2d3104..06a34eefb 100755 --- a/examples/exit_code.py +++ b/examples/exit_code.py @@ -13,7 +13,7 @@ class ReplWithExitCode(cmd2.Cmd): def __init__(self): super().__init__() - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_exit(self, arg_list: List[str]) -> bool: """Exit the application with an optional exit code. diff --git a/examples/hooks.py b/examples/hooks.py index b6f6263e6..6f0d31934 100755 --- a/examples/hooks.py +++ b/examples/hooks.py @@ -93,7 +93,7 @@ def abbrev_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.Postpars data.statement = self.statement_parser.parse(raw) return data - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_list(self, arglist: List[str]) -> None: """Generate a list of 10 numbers.""" if arglist: diff --git a/examples/paged_output.py b/examples/paged_output.py index a0674a626..1563b43f9 100755 --- a/examples/paged_output.py +++ b/examples/paged_output.py @@ -24,7 +24,7 @@ def page_file(self, file_path: str, chop: bool=False): except FileNotFoundError: self.perror('ERROR: file {!r} not found'.format(filename), traceback_war=False) - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_page_wrap(self, args: List[str]): """Read in a text file and display its output in a pager, wrapping long lines if they don't fit. @@ -37,7 +37,7 @@ def do_page_wrap(self, args: List[str]): complete_page_wrap = cmd2.Cmd.path_complete - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_page_truncate(self, args: List[str]): """Read in a text file and display its output in a pager, truncating long lines if they don't fit. diff --git a/examples/python_scripting.py b/examples/python_scripting.py index 7847b8b60..4ed4a2fe5 100755 --- a/examples/python_scripting.py +++ b/examples/python_scripting.py @@ -48,7 +48,7 @@ def postcmd(self, stop: bool, line: str) -> bool: self._set_prompt() return stop - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_cd(self, arglist): """Change directory. Usage: diff --git a/examples/tab_completion.py b/examples/tab_completion.py index 77d62988a..834f0adae 100755 --- a/examples/tab_completion.py +++ b/examples/tab_completion.py @@ -56,7 +56,7 @@ def complete_add_item(self, text, line, begidx, endidx): return self.flag_based_complete(text, line, begidx, endidx, flag_dict=flag_dict) - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_list_item(self, args): """List item command help""" self.poutput("You listed {}".format(args)) diff --git a/tests/test_argparse.py b/tests/test_argparse.py index 7db35c714..10c6c03f0 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -61,15 +61,15 @@ def do_tag(self, args): self.stdout.write('<{0}>{1}'.format(args.tag, ' '.join(args.content))) self.stdout.write('\n') - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_arglist(self, arglist): if isinstance(arglist, list): self.stdout.write('True') else: self.stdout.write('False') - @cmd2.with_argument_list - @cmd2.with_argument_list + @cmd2.with_argument_list() + @cmd2.with_argument_list() def do_arglisttwice(self, arglist): if isinstance(arglist, list): self.stdout.write(' '.join(arglist)) diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index faef21f91..332db07e5 100644 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -2266,7 +2266,7 @@ class ReplWithExitCode(cmd2.Cmd): def __init__(self): super().__init__() - @cmd2.with_argument_list + @cmd2.with_argument_list() def do_exit(self, arg_list) -> bool: """Exit the application with an optional exit code.