From a540cfc5373cee2272de6c81be8b6fa8a78c6462 Mon Sep 17 00:00:00 2001 From: Kevin Van Brunt Date: Fri, 21 Aug 2020 12:41:29 -0400 Subject: Fixed typo --- cmd2/cmd2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd2') diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index f6a5251c..da576805 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -825,7 +825,7 @@ class Cmd(cmd.Cmd): def poutput(self, msg: Any = '', *, end: str = '\n') -> None: """Print message to self.stdout and appends a newline by default - Also handles BrokenPipeError exceptions for when a commands's output has + Also handles BrokenPipeError exceptions for when a command's output has been piped to another process and that process terminates before the cmd2 command is finished executing. -- cgit v1.2.1 From 9b5a98825a9b00807a40494e8c634c392077ccd2 Mon Sep 17 00:00:00 2001 From: Kevin Van Brunt Date: Tue, 25 Aug 2020 01:46:04 -0400 Subject: Fixed RecursionError when printing an argparse.Namespace caused by custom attribute cmd2 was adding Added get_statement() function to argparse.Namespace which returns __statement__ attribute --- cmd2/cmd2.py | 4 +++- cmd2/constants.py | 11 ++++------- cmd2/decorators.py | 14 ++++++++------ 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'cmd2') diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index da576805..bc6691f6 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -663,7 +663,9 @@ class Cmd(cmd.Cmd): raise CommandSetRegistrationError('Could not find argparser for command "{}" needed by subcommand: {}' .format(command_name, str(method))) - subcmd_parser.set_defaults(cmd2_handler=method) + # Set the subcommand handler function + defaults = {constants.NS_ATTR_SUBCMD_HANDLER: method} + subcmd_parser.set_defaults(**defaults) def find_subcommand(action: argparse.ArgumentParser, subcmd_names: List[str]) -> argparse.ArgumentParser: if not subcmd_names: diff --git a/cmd2/constants.py b/cmd2/constants.py index 9eaa9957..037a7cab 100644 --- a/cmd2/constants.py +++ b/cmd2/constants.py @@ -37,10 +37,6 @@ HELP_FUNC_PREFIX = 'help_' # All command completer functions start with this COMPLETER_FUNC_PREFIX = 'complete_' -############################################################################## -# The following are optional attributes added to do_* command functions -############################################################################## - # The custom help category a command belongs to CMD_ATTR_HELP_CATEGORY = 'help_category' @@ -50,9 +46,6 @@ CMD_ATTR_ARGPARSER = 'argparser' # Whether or not tokens are unquoted before sending to argparse CMD_ATTR_PRESERVE_QUOTES = 'preserve_quotes' -# optional attribute -SUBCMD_HANDLER = 'cmd2_handler' - # subcommand attributes for the base command name and the subcommand name SUBCMD_ATTR_COMMAND = 'parent_command' SUBCMD_ATTR_NAME = 'subcommand_name' @@ -60,3 +53,7 @@ SUBCMD_ATTR_ADD_PARSER_KWARGS = 'subcommand_add_parser_kwargs' # arpparse attribute linking to command set instance PARSER_ATTR_COMMANDSET = 'command_set' + +# custom attributes added to argparse Namespaces +NS_ATTR_SUBCMD_HANDLER = '__subcmd_handler__' +NS_ATTR_STATEMENT = '__statement__' diff --git a/cmd2/decorators.py b/cmd2/decorators.py index 689f29c5..ccbbd832 100644 --- a/cmd2/decorators.py +++ b/cmd2/decorators.py @@ -1,7 +1,6 @@ # coding=utf-8 """Decorators for ``cmd2`` commands""" import argparse -import types from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Tuple, Union from . import constants @@ -190,6 +189,7 @@ def with_argparser_and_unknown_args(parser: argparse.ArgumentParser, *, of unknown argument strings. A member called ``__statement__`` is added to the ``Namespace`` to provide command functions access to the :class:`cmd2.Statement` object. This can be useful if the command function needs to know the command line. + ``__statement__`` can also be retrieved by calling ``get_statement()`` on the ``Namespace``. :Example: @@ -228,6 +228,7 @@ def with_argparser(parser: argparse.ArgumentParser, *, :return: function that gets passed the argparse-parsed args in a Namespace A member called __statement__ is added to the Namespace to provide command functions access to the Statement object. This can be useful if the command function needs to know the command line. + ``__statement__`` can also be retrieved by calling ``get_statement()`` on the ``Namespace``. :Example: @@ -297,12 +298,13 @@ def with_argparser(parser: argparse.ArgumentParser, *, except SystemExit: raise Cmd2ArgparseError else: - setattr(ns, '__statement__', statement) + # Add statement to Namespace and a getter function for it + setattr(ns, constants.NS_ATTR_STATEMENT, statement) + setattr(ns, 'get_statement', lambda: statement) - def get_handler(ns_self: argparse.Namespace) -> Optional[Callable]: - return getattr(ns_self, constants.SUBCMD_HANDLER, None) - - setattr(ns, 'get_handler', types.MethodType(get_handler, ns)) + # Add getter function for subcmd handler, which can be None + subcmd_handler = getattr(ns, constants.NS_ATTR_SUBCMD_HANDLER, None) + setattr(ns, 'get_handler', lambda: subcmd_handler) args_list = _arg_swap(args, statement, *new_args) return func(*args_list, **kwargs) -- cgit v1.2.1