summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2019-06-27 11:03:09 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2019-06-27 11:03:09 -0400
commit447479ecd6ef2cf01434485c4c93537c8be1a566 (patch)
tree8d823db306a78b6aa4ae61987b0a870c32cc4d9d
parent5b7a45edf20d70a19c6b8d3706d8e542e1bcf30d (diff)
downloadcmd2-git-447479ecd6ef2cf01434485c4c93537c8be1a566.tar.gz
Made allow_ansi an application-wide setting and moved it to ansi.py
-rw-r--r--cmd2/ansi.py8
-rw-r--r--cmd2/cmd2.py43
-rw-r--r--cmd2/constants.py5
-rw-r--r--tests/test_cmd2.py24
4 files changed, 46 insertions, 34 deletions
diff --git a/cmd2/ansi.py b/cmd2/ansi.py
index 7ae9016e..3e5fdbc2 100644
--- a/cmd2/ansi.py
+++ b/cmd2/ansi.py
@@ -8,6 +8,14 @@ import colorama
from colorama import Fore, Back, Style
from wcwidth import wcswidth
+# Values for allow_ansi setting
+ANSI_NEVER = 'Never'
+ANSI_TERMINAL = 'Terminal'
+ANSI_ALWAYS = 'Always'
+
+# Controls when ANSI escape sequences are allowed in output
+allow_ansi = ANSI_TERMINAL
+
# Regular expression to match ANSI escape sequences
ANSI_ESCAPE_RE = re.compile(r'\x1b[^m]*m')
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 609a9e02..eccee1f9 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -374,7 +374,6 @@ class Cmd(cmd.Cmd):
self.quit_on_sigint = False # Quit the loop on interrupt instead of just resetting prompt
# Attributes which ARE dynamically settable at runtime
- self.allow_ansi = constants.ANSI_TERMINAL
self.continuation_prompt = '> '
self.debug = False
self.echo = False
@@ -385,16 +384,20 @@ class Cmd(cmd.Cmd):
self.timing = False # Prints elapsed time for each command
# To make an attribute settable with the "do_set" command, add it to this ...
- self.settable = {'allow_ansi': 'Allow ANSI escape sequences in output (valid values: Terminal, Always, Never)',
- 'continuation_prompt': 'On 2nd+ line of input',
- 'debug': 'Show full error stack on error',
- 'echo': 'Echo command issued into output',
- 'editor': 'Program used by ``edit``',
- 'feedback_to_output': 'Include nonessentials in `|`, `>` results',
- 'locals_in_py': 'Allow access to your application in py via self',
- 'prompt': 'The prompt issued to solicit input',
- 'quiet': "Don't print nonessential feedback",
- 'timing': 'Report execution times'}
+ self.settable = \
+ {
+ # allow_ansi is a special case in which it's an application-wide setting defined in ansi.py
+ 'allow_ansi': 'Allow ANSI escape sequences in output (valid values: Terminal, Always, Never)',
+ 'continuation_prompt': 'On 2nd+ line of input',
+ 'debug': 'Show full error stack on error',
+ 'echo': 'Echo command issued into output',
+ 'editor': 'Program used by ``edit``',
+ 'feedback_to_output': 'Include nonessentials in `|`, `>` results',
+ 'locals_in_py': 'Allow access to your application in py via self',
+ 'prompt': 'The prompt issued to solicit input',
+ 'quiet': "Don't print nonessential feedback",
+ 'timing': 'Report execution times'
+ }
# Commands to exclude from the help menu and tab completion
self.hidden_commands = ['eof', '_relative_load', '_relative_run_script']
@@ -551,6 +554,16 @@ class Cmd(cmd.Cmd):
# ----- Methods related to presenting output to the user -----
@property
+ def allow_ansi(self) -> str:
+ """Read-only property needed to support do_set when it reads allow_ansi"""
+ return ansi.allow_ansi
+
+ @allow_ansi.setter
+ def allow_ansi(self, new_val: str) -> None:
+ """Read-only property needed to support do_set when it sets allow_ansi"""
+ ansi.allow_ansi = new_val
+
+ @property
def visible_prompt(self) -> str:
"""Read-only property to get the visible prompt with any ANSI escape codes stripped.
@@ -581,8 +594,8 @@ class Cmd(cmd.Cmd):
Honor the current colors setting, which requires us to check whether the fileobject is a tty.
"""
- if self.allow_ansi.lower() == constants.ANSI_NEVER.lower() or \
- (self.allow_ansi.lower() == constants.ANSI_TERMINAL.lower() and not fileobj.isatty()):
+ if ansi.allow_ansi.lower() == ansi.ANSI_NEVER.lower() or \
+ (ansi.allow_ansi.lower() == ansi.ANSI_TERMINAL.lower() and not fileobj.isatty()):
msg = ansi.strip_ansi(msg)
fileobj.write(msg)
@@ -612,7 +625,7 @@ class Cmd(cmd.Cmd):
:param msg: message to print (anything convertible to a str with '{}'.format() is OK)
:param end: string appended after the end of the message, default a newline
- :param apply_style: If True, then ErrorStyle will be applied to the message text. Set to False in cases
+ :param apply_style: If True, then ansi.style_error will be applied to the message text. Set to False in cases
where the message text already has the desired style. Defaults to True.
"""
if apply_style:
@@ -691,7 +704,7 @@ class Cmd(cmd.Cmd):
# 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 self.allow_ansi.lower() == constants.ANSI_NEVER.lower():
+ if ansi.allow_ansi.lower() == ansi.ANSI_NEVER.lower():
msg_str = ansi.strip_ansi(msg_str)
pager = self.pager
diff --git a/cmd2/constants.py b/cmd2/constants.py
index ed196f22..9fd58b01 100644
--- a/cmd2/constants.py
+++ b/cmd2/constants.py
@@ -16,8 +16,3 @@ MULTILINE_TERMINATOR = ';'
LINE_FEED = '\n'
DEFAULT_SHORTCUTS = {'?': 'help', '!': 'shell', '@': 'run_script', '@@': '_relative_run_script'}
-
-# Values for cmd2's allow_ansi setting
-ANSI_NEVER = 'Never'
-ANSI_TERMINAL = 'Terminal'
-ANSI_ALWAYS = 'Always'
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index 5eeb442e..f56555aa 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -1459,7 +1459,7 @@ def test_poutput_none(outsim_app):
def test_poutput_color_always(outsim_app):
msg = 'Hello World'
- outsim_app.allow_ansi = 'Always'
+ ansi.allow_ansi = ansi.ANSI_ALWAYS
outsim_app.poutput(ansi.style(msg, fg='cyan'))
out = outsim_app.stdout.getvalue()
expected = Fore.CYAN + msg + Fore.RESET + '\n'
@@ -1467,7 +1467,7 @@ def test_poutput_color_always(outsim_app):
def test_poutput_color_never(outsim_app):
msg = 'Hello World'
- outsim_app.allow_ansi = 'Never'
+ ansi.allow_ansi = ansi.ANSI_NEVER
outsim_app.poutput(ansi.style(msg, fg='cyan'))
out = outsim_app.stdout.getvalue()
expected = msg + '\n'
@@ -1767,7 +1767,7 @@ def test_ppaged(outsim_app):
def test_ppaged_strips_ansi_when_redirecting(outsim_app):
msg = 'testing...'
end = '\n'
- outsim_app.allow_ansi = cmd2.constants.ANSI_TERMINAL
+ ansi.allow_ansi = ansi.ANSI_TERMINAL
outsim_app._redirecting = True
outsim_app.ppaged(Fore.RED + msg)
out = outsim_app.stdout.getvalue()
@@ -1776,7 +1776,7 @@ def test_ppaged_strips_ansi_when_redirecting(outsim_app):
def test_ppaged_strips_ansi_when_redirecting_if_always(outsim_app):
msg = 'testing...'
end = '\n'
- outsim_app.allow_ansi = cmd2.constants.ANSI_ALWAYS
+ ansi.allow_ansi = ansi.ANSI_ALWAYS
outsim_app._redirecting = True
outsim_app.ppaged(Fore.RED + msg)
out = outsim_app.stdout.getvalue()
@@ -1910,13 +1910,9 @@ class AnsiApp(cmd2.Cmd):
# perror uses colors by default
self.perror(args)
-def test_ansi_default():
- app = AnsiApp()
- assert app.allow_ansi == cmd2.constants.ANSI_TERMINAL
-
def test_ansi_pouterr_always_tty(mocker, capsys):
app = AnsiApp()
- app.allow_ansi = cmd2.constants.ANSI_ALWAYS
+ ansi.allow_ansi = ansi.ANSI_ALWAYS
mocker.patch.object(app.stdout, 'isatty', return_value=True)
mocker.patch.object(sys.stderr, 'isatty', return_value=True)
@@ -1938,7 +1934,7 @@ def test_ansi_pouterr_always_tty(mocker, capsys):
def test_ansi_pouterr_always_notty(mocker, capsys):
app = AnsiApp()
- app.allow_ansi = cmd2.constants.ANSI_ALWAYS
+ ansi.allow_ansi = ansi.ANSI_ALWAYS
mocker.patch.object(app.stdout, 'isatty', return_value=False)
mocker.patch.object(sys.stderr, 'isatty', return_value=False)
@@ -1960,7 +1956,7 @@ def test_ansi_pouterr_always_notty(mocker, capsys):
def test_ansi_terminal_tty(mocker, capsys):
app = AnsiApp()
- app.allow_ansi = cmd2.constants.ANSI_TERMINAL
+ ansi.allow_ansi = ansi.ANSI_TERMINAL
mocker.patch.object(app.stdout, 'isatty', return_value=True)
mocker.patch.object(sys.stderr, 'isatty', return_value=True)
@@ -1981,7 +1977,7 @@ def test_ansi_terminal_tty(mocker, capsys):
def test_ansi_terminal_notty(mocker, capsys):
app = AnsiApp()
- app.allow_ansi = cmd2.constants.ANSI_TERMINAL
+ ansi.allow_ansi = ansi.ANSI_TERMINAL
mocker.patch.object(app.stdout, 'isatty', return_value=False)
mocker.patch.object(sys.stderr, 'isatty', return_value=False)
@@ -1995,7 +1991,7 @@ def test_ansi_terminal_notty(mocker, capsys):
def test_ansi_never_tty(mocker, capsys):
app = AnsiApp()
- app.allow_ansi = cmd2.constants.ANSI_NEVER
+ ansi.allow_ansi = ansi.ANSI_NEVER
mocker.patch.object(app.stdout, 'isatty', return_value=True)
mocker.patch.object(sys.stderr, 'isatty', return_value=True)
@@ -2009,7 +2005,7 @@ def test_ansi_never_tty(mocker, capsys):
def test_ansi_never_notty(mocker, capsys):
app = AnsiApp()
- app.allow_ansi = cmd2.constants.ANSI_NEVER
+ ansi.allow_ansi = ansi.ANSI_NEVER
mocker.patch.object(app.stdout, 'isatty', return_value=False)
mocker.patch.object(sys.stderr, 'isatty', return_value=False)