diff options
author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-06-27 11:03:09 -0400 |
---|---|---|
committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-06-27 11:03:09 -0400 |
commit | 447479ecd6ef2cf01434485c4c93537c8be1a566 (patch) | |
tree | 8d823db306a78b6aa4ae61987b0a870c32cc4d9d | |
parent | 5b7a45edf20d70a19c6b8d3706d8e542e1bcf30d (diff) | |
download | cmd2-git-447479ecd6ef2cf01434485c4c93537c8be1a566.tar.gz |
Made allow_ansi an application-wide setting and moved it to ansi.py
-rw-r--r-- | cmd2/ansi.py | 8 | ||||
-rw-r--r-- | cmd2/cmd2.py | 43 | ||||
-rw-r--r-- | cmd2/constants.py | 5 | ||||
-rw-r--r-- | tests/test_cmd2.py | 24 |
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) |