summaryrefslogtreecommitdiff
path: root/cmd2
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2020-08-25 16:11:49 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2020-08-26 17:52:34 -0400
commit478ea83336a4d1659ad06ef365db3dc5e051e46d (patch)
treecbaff855e2d73f1d86ae1230f32770e31c62ad6b /cmd2
parent97c348c599d8fa963553593e5c19fb100b85e313 (diff)
downloadcmd2-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__.py2
-rw-r--r--cmd2/argparse_custom.py20
-rw-r--r--cmd2/cmd2.py4
-rw-r--r--cmd2/decorators.py36
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)