Skip to content

Commit d9f5f2b

Browse files
committed
Added echo parameter for calling commands from Pyscript
Documented py command's parsing limitations
1 parent 924f8a5 commit d9f5f2b

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

cmd2/cmd2.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2944,7 +2944,21 @@ def _reset_py_display() -> None:
29442944
sys.displayhook = sys.__displayhook__
29452945
sys.excepthook = sys.__excepthook__
29462946

2947-
py_parser = ACArgumentParser()
2947+
py_description = ("Invoke Python command or shell\n"
2948+
"\n"
2949+
"When invoking a command directly from the command line, note this shell has\n"
2950+
"limited ability to parse Python statements into tokens. If an opening quote is\n"
2951+
"not preceded by whitespace, its closing quote should appear before any\n"
2952+
"whitespace. Otherwise whitespace in the parsed tokens will get lost.\n"
2953+
"\n"
2954+
"Note the opening quote before 'This' in the following commands\n"
2955+
'py print("This " + "is bad")\n'
2956+
'py print("This" + " is good")\n'
2957+
"\n"
2958+
"If you see strange parsing behavior, its best to just open the Python shell by\n"
2959+
"providing no arguments to py and run more complex statements there.")
2960+
2961+
py_parser = ACArgumentParser(description=py_description)
29482962
py_parser.add_argument('command', help="command to run", nargs='?')
29492963
py_parser.add_argument('remainder', help="remainder of command", nargs=argparse.REMAINDER)
29502964

cmd2/pyscript_bridge.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import argparse
1111
import functools
1212
import sys
13-
from typing import List, Callable
13+
from typing import List, Callable, Optional
1414

1515
from .argparse_completer import _RangeAction
1616
from .utils import namedtuple_with_defaults, StdSim
@@ -38,7 +38,7 @@ def __bool__(self):
3838
return not self.stderr and self.data is not None
3939

4040

41-
def _exec_cmd(cmd2_app, func: Callable, echo: bool):
41+
def _exec_cmd(cmd2_app, func: Callable, echo: bool) -> CommandResult:
4242
"""Helper to encapsulate executing a command and capturing the results"""
4343
copy_stdout = StdSim(sys.stdout, echo)
4444
copy_stderr = StdSim(sys.stderr, echo)
@@ -65,7 +65,7 @@ def _exec_cmd(cmd2_app, func: Callable, echo: bool):
6565

6666
class ArgparseFunctor:
6767
"""
68-
Encapsulates translating python object traversal
68+
Encapsulates translating Python object traversal
6969
"""
7070
def __init__(self, echo: bool, cmd2_app, command_name: str, parser: argparse.ArgumentParser):
7171
self._echo = echo
@@ -250,7 +250,7 @@ def __init__(self, cmd2_app):
250250
self.cmd_echo = False
251251

252252
def __getattr__(self, item: str):
253-
"""Check if the attribute is a command. If so, return a callable."""
253+
"""If attribute is a command, return a callable. Otherwise return the attribute."""
254254
func = self._cmd2_app.cmd_func(item)
255255

256256
if func:
@@ -264,14 +264,23 @@ def wrap_func(args=''):
264264

265265
return wrap_func
266266
else:
267-
return super().__getattr__(item)
267+
return getattr(self._cmd2_app, item)
268268

269269
def __dir__(self):
270270
"""Return a custom set of attribute names to match the available commands"""
271271
commands = list(self._cmd2_app.get_all_commands())
272272
commands.insert(0, 'cmd_echo')
273273
return commands
274274

275-
def __call__(self, args: str):
275+
def __call__(self, args: str, echo: Optional[bool]=None) -> CommandResult:
276+
"""
277+
Call a command function (ex: do_help)
278+
:param args: The string being passed to the command
279+
:param echo: If True, output will be echoed while the command runs
280+
This temporarily overrides the value of self.cmd_echo
281+
"""
282+
if echo is None:
283+
echo = self.cmd_echo
284+
276285
return _exec_cmd(self._cmd2_app, functools.partial(self._cmd2_app.onecmd_plus_hooks, args + '\n'),
277-
self.cmd_echo)
286+
echo)

0 commit comments

Comments
 (0)