diff options
author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2020-08-25 16:11:49 -0400 |
---|---|---|
committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2020-08-26 17:52:34 -0400 |
commit | 478ea83336a4d1659ad06ef365db3dc5e051e46d (patch) | |
tree | cbaff855e2d73f1d86ae1230f32770e31c62ad6b /cmd2 | |
parent | 97c348c599d8fa963553593e5c19fb100b85e313 (diff) | |
download | cmd2-git-478ea83336a4d1659ad06ef365db3dc5e051e46d.tar.gz |
The functions cmd2 adds to Namespaces (get_statement() and get_handler()) are now
Cmd2AttributeWrapper objects named cmd2_statement and cmd2_handler. This makes it
easy to filter out which attributes in an argparse.Namespace were added by cmd2.
Diffstat (limited to 'cmd2')
-rw-r--r-- | cmd2/__init__.py | 2 | ||||
-rw-r--r-- | cmd2/argparse_custom.py | 20 | ||||
-rw-r--r-- | cmd2/cmd2.py | 4 | ||||
-rw-r--r-- | cmd2/decorators.py | 36 |
4 files changed, 44 insertions, 18 deletions
diff --git a/cmd2/__init__.py b/cmd2/__init__.py index 9f0bb176..81e80efe 100644 --- a/cmd2/__init__.py +++ b/cmd2/__init__.py @@ -16,7 +16,7 @@ except importlib_metadata.PackageNotFoundError: # pragma: no cover pass from .ansi import style, fg, bg -from .argparse_custom import Cmd2ArgumentParser, CompletionItem, set_default_argument_parser +from .argparse_custom import Cmd2ArgumentParser, Cmd2AttributeWrapper, CompletionItem, set_default_argument_parser # Check if user has defined a module that sets a custom value for argparse_custom.DEFAULT_ARGUMENT_PARSER import argparse diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py index 12c18644..45abe6b2 100644 --- a/cmd2/argparse_custom.py +++ b/cmd2/argparse_custom.py @@ -221,7 +221,7 @@ import re import sys # noinspection PyUnresolvedReferences,PyProtectedMember from argparse import ONE_OR_MORE, ZERO_OR_MORE, ArgumentError, _ -from typing import Callable, Optional, Tuple, Type, Union +from typing import Any, Callable, Optional, Tuple, Type, Union from . import ansi, constants @@ -904,6 +904,24 @@ class Cmd2ArgumentParser(argparse.ArgumentParser): ansi.style_aware_write(file, message) +class Cmd2AttributeWrapper: + """ + Wraps a cmd2-specific attribute added to an argparse Namespace. + This makes it easy to know which attributes in a Namespace are + arguments from a parser and which were added by cmd2. + """ + def __init__(self, attribute: Any): + self.__attribute = attribute + + def get(self) -> Any: + """Get the value of the attribute""" + return self.__attribute + + def set(self, new_val: Any) -> None: + """Set the value of the attribute""" + self.__attribute = new_val + + # The default ArgumentParser class for a cmd2 app DEFAULT_ARGUMENT_PARSER = Cmd2ArgumentParser diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index bc6691f6..103508c5 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -2685,7 +2685,7 @@ class Cmd(cmd.Cmd): def do_alias(self, args: argparse.Namespace) -> None: """Manage aliases""" # Call handler for whatever subcommand was selected - handler = args.get_handler() + handler = args.cmd2_handler.get() handler(args) # alias -> create @@ -2812,7 +2812,7 @@ class Cmd(cmd.Cmd): def do_macro(self, args: argparse.Namespace) -> None: """Manage macros""" # Call handler for whatever subcommand was selected - handler = args.get_handler() + handler = args.cmd2_handler.get() handler(args) # macro -> create diff --git a/cmd2/decorators.py b/cmd2/decorators.py index ccbbd832..c2689102 100644 --- a/cmd2/decorators.py +++ b/cmd2/decorators.py @@ -4,6 +4,7 @@ import argparse from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Tuple, Union from . import constants +from .argparse_custom import Cmd2AttributeWrapper from .exceptions import Cmd2ArgparseError from .parsing import Statement @@ -186,10 +187,10 @@ def with_argparser_and_unknown_args(parser: argparse.ArgumentParser, *, needs to be prepopulated with state data that affects parsing. :param preserve_quotes: if ``True``, then arguments passed to argparse maintain their quotes :return: function that gets passed argparse-parsed args in a ``Namespace`` and a list - 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``. + of unknown argument strings. A :class:`cmd2.argparse_custom.Cmd2AttributeWrapper` called + ``cmd2_statement`` is included in the ``Namespace`` to provide access to the :class:`cmd2.Statement` + object. that was created when parsing the command line. This can be useful if the command function + needs to know the command line. :Example: @@ -223,12 +224,12 @@ def with_argparser(parser: argparse.ArgumentParser, *, :param ns_provider: An optional function that accepts a cmd2.Cmd object as an argument and returns an argparse.Namespace. This is useful if the Namespace needs to be prepopulated with state data that affects parsing. - :param preserve_quotes: if True, then arguments passed to argparse maintain their quotes + :param preserve_quotes: if ``True``, then arguments passed to argparse maintain their quotes :param with_unknown_args: if true, then capture unknown args - :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``. + :return: function that gets passed argparse-parsed args in a ``Namespace`` + A :class:`cmd2.argparse_custom.Cmd2AttributeWrapper` called ``cmd2_statement`` is included + in the ``Namespace`` to provide access to the :class:`cmd2.Statement` object that was created when + parsing the command line. This can be useful if the command function needs to know the command line. :Example: @@ -298,13 +299,20 @@ def with_argparser(parser: argparse.ArgumentParser, *, except SystemExit: raise Cmd2ArgparseError else: - # Add statement to Namespace and a getter function for it + # Add statement to Namespace as __statement__ (this is deprecated and will be removed in 2.0) setattr(ns, constants.NS_ATTR_STATEMENT, statement) - setattr(ns, 'get_statement', lambda: statement) - # 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) + # Add wrapped statement to Namespace as cmd2_statement + setattr(ns, 'cmd2_statement', Cmd2AttributeWrapper(statement)) + + # Add wrapped subcmd handler (which can be None) to Namespace as cmd2_handler + handler = getattr(ns, constants.NS_ATTR_SUBCMD_HANDLER, None) + setattr(ns, 'cmd2_handler', Cmd2AttributeWrapper(handler)) + + # Remove the subcmd handler attribute from the Namespace + # since cmd2_handler is how a developer accesses it. + if hasattr(ns, constants.NS_ATTR_SUBCMD_HANDLER): + delattr(ns, constants.NS_ATTR_SUBCMD_HANDLER) args_list = _arg_swap(args, statement, *new_args) return func(*args_list, **kwargs) |