Skip to content

Added in_script() and in_pyscript() to cmd2.Cmd class #782

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
If these functions have an argument called `arg_tokens`, then AutoCompleter will automatically pass this
dictionary to them.
* Added CompletionError class that can be raised during argparse-based tab completion and printed to the user
* Added the following convenience methods
- `Cmd.in_script()` - return whether a text script is running
- `Cmd.in_pyscript()` - return whether a pyscript is running

## 0.9.16 (August 7, 2019)
* Bug Fixes
Expand Down
22 changes: 15 additions & 7 deletions cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,11 +626,6 @@ def visible_prompt(self) -> str:
"""
return ansi.strip_ansi(self.prompt)

@property
def aliases(self) -> Dict[str, str]:
"""Read-only property to access the aliases stored in the StatementParser."""
return self.statement_parser.aliases

def poutput(self, msg: Any, *, end: str = '\n') -> None:
"""Print message to self.stdout and appends a newline by default

Expand Down Expand Up @@ -744,7 +739,7 @@ def ppaged(self, msg: str, end: str = '\n', chop: bool = False) -> None:

# Don't attempt to use a pager that can block if redirecting or running a script (either text or Python)
# Also only attempt to use a pager if actually running in a real fully functional terminal
if functional_terminal and not self._redirecting and not self._in_py and not self._script_dir:
if functional_terminal and not self._redirecting and not self.in_pyscript() and not self.in_script():
if ansi.allow_ansi.lower() == ansi.ANSI_NEVER.lower():
msg_str = ansi.strip_ansi(msg_str)

Expand Down Expand Up @@ -1606,6 +1601,19 @@ def _autocomplete_default(self, text: str, line: str, begidx: int, endidx: int,
tokens_to_parse = raw_tokens if preserve_quotes else tokens
return completer.complete_command(tokens_to_parse, text, line, begidx, endidx)

def in_script(self) -> bool:
"""Return whether a text script is running"""
return self._current_script_dir is not None

def in_pyscript(self) -> bool:
"""Return whether a pyscript is running"""
return self._in_py

@property
def aliases(self) -> Dict[str, str]:
"""Read-only property to access the aliases stored in the StatementParser"""
return self.statement_parser.aliases

def get_names(self):
"""Return an alphabetized list of names comprising the attributes of the cmd2 class instance."""
return dir(self)
Expand Down Expand Up @@ -3228,7 +3236,7 @@ def do_py(self, args: argparse.Namespace) -> Optional[bool]:
:return: True if running of commands should stop
"""
from .py_bridge import PyBridge
if self._in_py:
if self.in_pyscript():
err = "Recursively entering interactive Python consoles is not allowed."
self.perror(err)
return
Expand Down
20 changes: 19 additions & 1 deletion tests/test_cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from unittest import mock

import cmd2
from cmd2 import ansi, clipboard, constants, utils
from cmd2 import ansi, clipboard, constants, plugin, utils
from .conftest import run_cmd, normalize, verify_help_text, HELP_HISTORY
from .conftest import SHORTCUTS_TXT, SHOW_TXT, SHOW_LONG, complete_tester

Expand Down Expand Up @@ -461,6 +461,24 @@ def test_relative_run_script_requires_an_argument(base_app):
out, err = run_cmd(base_app, '_relative_run_script')
assert 'Error: the following arguments' in err[1]

def test_in_script(request):
class HookApp(cmd2.Cmd):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.register_cmdfinalization_hook(self.hook)

def hook(self: cmd2.Cmd, data: plugin.CommandFinalizationData) -> plugin.CommandFinalizationData:
if self.in_script():
self.poutput("WE ARE IN SCRIPT")
return data

hook_app = HookApp()
test_dir = os.path.dirname(request.module.__file__)
filename = os.path.join(test_dir, 'script.txt')
out, err = run_cmd(hook_app, 'run_script {}'.format(filename))

assert "WE ARE IN SCRIPT" in out[-1]

def test_output_redirection(base_app):
fd, filename = tempfile.mkstemp(prefix='cmd2_test', suffix='.txt')
os.close(fd)
Expand Down