def test_strip_ansi(): assert strutils.strip_ansi( '\x1b[0m\x1b[1;36mart\x1b[46;34m\xdc') == 'art\xdc' assert strutils.strip_ansi( u'\x1b[0m\x1b[1;36mart\x1b[46;34m\xdc') == u'artÜ' assert strutils.strip_ansi( u'╒══════╕\n│ \x1b[1mCell\x1b[0m │\n╘══════╛') == ( u'╒══════╕\n' u'│ Cell │\n' u'╘══════╛') assert strutils.strip_ansi( u'ls\r\n\x1B[00m\x1b[01;31mfile.zip\x1b[00m\r\n\x1b[01;31m') == \ u'ls\r\nfile.zip\r\n' assert strutils.strip_ansi( u'\t\u001b[0;35mIP\u001b[0m\t\u001b[0;36m192.1.0.2\u001b[0m') == \ u'\tIP\t192.1.0.2' assert strutils.strip_ansi(u'(╯°□°)╯︵ \x1b[1m┻━┻\x1b[0m') == ( u'(╯°□°)╯︵ ┻━┻') assert strutils.strip_ansi('(╯°□°)╯︵ \x1b[1m┻━┻\x1b[0m') == ( '(╯°□°)╯︵ ┻━┻') assert strutils.strip_ansi( b'(\xe2\x95\xaf\xc2\xb0\xe2\x96\xa1\xc2\xb0)\xe2\x95\xaf\xef\xb8' b'\xb5 \x1b[1m\xe2\x94\xbb\xe2\x94\x81\xe2\x94\xbb\x1b[0m') == ( b'(\xe2\x95\xaf\xc2\xb0\xe2\x96\xa1\xc2\xb0)\xe2\x95\xaf\xef\xb8' b'\xb5 \xe2\x94\xbb\xe2\x94\x81\xe2\x94\xbb') assert strutils.strip_ansi( bytearray(u'(╯°□°)╯︵ \x1b[1m┻━┻\x1b[0m', 'utf-8')) == \ bytearray( b'(\xe2\x95\xaf\xc2\xb0\xe2\x96\xa1\xc2\xb0)\xe2\x95\xaf\xef\xb8' b'\xb5 \xe2\x94\xbb\xe2\x94\x81\xe2\x94\xbb')
def run(self, *args, dry_run=False): """ Run a shell command, return the output and keep error message. Removes ANSI escape codes, and returns ready-to-use strings. """ # Serialize Path objects to strings. args = list(map(str, flatten(args))) args_str = click.style(' '.join(args), fg='white') logger.debug(f"► {args_str}") code = 0 output = None error = None if not dry_run: code, output, error = run(*args) else: logger.warning("Dry-run: skip execution of command.") # Normalize messages. if error: error = strip_ansi(error) error = error if error else None if output: output = strip_ansi(output) output = output if output else None # Non-successful run. if code and error: # Produce an exception and eventually raise it. exception = CLIError(code, output, error) if self.raise_on_cli_error: raise exception # Accumulate errors. self.cli_errors.append(exception) # Log <stdout> and <stderr> output. if output: logger.debug(indent(output, ' ')) if error: # Non-fatal error messages are logged as warnings. log_func = logger.error if code else logger.warning log_func(indent(error, ' ')) return output
def _deserialize(self, value, attr, data): out = super()._deserialize(value, attr, data) out = out.strip() if self.lower: out = out.lower() if strutils.html2text(out) != out: self.fail('invalid') elif strutils.strip_ansi(out) != out: self.fail('invalid') return out
def check_manager_selection(result, selected=MANAGER_IDS): """ Check inclusion and exclusion of a set of managers. Check all manager are there by default. .. todo: Parametrize/fixturize signals to pin point output depending on subcommand. """ assert isinstance(selected, (frozenset, set)) found_managers = set() skipped_managers = set() for mid in MANAGER_IDS: # List of signals indicating a package manager has been retained by # the CLI. Roughly sorted from most specific to more forgiving. signals = [ # Common "not found" warning message. "warning: Skip unavailable {} manager.".format( mid) in result.stderr, # Common "not implemented" optional command warning message. bool(re.search( r"warning: (Sync|Cleanup) not implemented for {}.".format( mid), result.stderr)), # Stats line at the end of output. "{}: ".format(mid) in result.stdout.splitlines( )[-1] if result.stdout else '', # Match output of managers command. bool(re.search(r"\s+│\s+{}\s+│\s+(✓|✘).+│\s+(✓|✘)".format(mid), strip_ansi(result.stdout))), # Sync command. "Sync {} package info...".format(mid) in result.stderr, # Upgrade command. "Updating all outdated packages from {}...".format( mid) in result.stderr, # Cleanup command. "Cleanup {}...".format(mid) in result.stderr, # Log message for backup command. "Dumping packages from {}...".format(mid) in result.stderr, # Restoring message. "Restore {} packages...".format(mid) in result.stderr, # Warning message for restore command. "warning: No [{}] section found.".format(mid) in result.stderr] if True in signals: found_managers.add(mid) else: skipped_managers.add(mid) # Compare managers reported by the CLI and those expected. assert found_managers == selected assert skipped_managers == MANAGER_IDS - selected
def run(self, args, dry_run=False): """ Run a shell command, return the output and keep error message. Removes ANSI escape codes, and returns ready-to-use strings. """ assert isinstance(args, list) logger.debug("Running `{}`...".format(' '.join(args))) code = 0 output = None error = None if not dry_run: code, output, error = run(*args) else: logger.warning("Dry-run mode active: skip execution of command.") # Normalize messages. if error: error = strip_ansi(error) error = error if error else None if output: output = strip_ansi(output) output = output if output else None if code and error: exception = CLIError(code, output, error) if self.raise_on_cli_error: raise exception else: logger.error(error) self.cli_errors.append(exception) logger.debug(output) return output
def sort_method(line): """ Serialize line's content for natural sorting. 1. Extract each cell value in the order provided by `sort_order`; 2. Strip terminal color formating; 3. Then tokenize each cell's content for user-friendly natural sorting. """ sorting_key = [] for cell in itemgetter(*sort_order)(line): if isinstance(cell, TokenizedString): key = cell else: key = TokenizedString(strip_ansi(cell)) sorting_key.append(key) return tuple(sorting_key)
def echo(msg, **kw): """A better-behaved :func:`print()` function for command-line applications. Writes text or bytes to a file or stream and flushes. Seamlessly handles stripping ANSI color codes when the output file is not a TTY. >>> echo('test') test Args: msg (str): A text or byte string to echo. err (bool): Set the default output file to ``sys.stderr`` file (file): Stream or other file-like object to output to. Defaults to ``sys.stdout``, or ``sys.stderr`` if *err* is True. nl (bool): If ``True``, sets *end* to ``'\\n'``, the newline character. end (str): Explicitly set the line-ending character. Setting this overrides *nl*. color (bool): Set to ``True``/``False`` to always/never echo ANSI color codes. Defaults to inspecting whether *file* is a TTY. """ msg = msg or '' if not isinstance(msg, (unicode, bytes)): msg = unicode(msg) is_err = kw.pop('err', False) _file = kw.pop('file', sys.stdout if not is_err else sys.stderr) end = kw.pop('end', None) enable_color = kw.pop('color', None) if enable_color is None: enable_color = not should_strip_ansi(_file) if end is None: if kw.pop('nl', True): end = u'\n' if isinstance(msg, unicode) else b'\n' if end: msg += end if msg: if not enable_color: msg = strip_ansi(msg) _file.write(msg) _file.flush() return
def echo(msg, **kw): msg = msg or '' is_err = kw.pop('err', False) _file = kw.pop('file', sys.stdout if not is_err else sys.stderr) end = kw.pop('end', None) enable_color = kw.pop('color', None) if enable_color is None: enable_color = not should_strip_ansi(_file) if end is None: if kw.pop('nl', True): end = u'\n' if isinstance(msg, unicode) else b'\n' if end: msg += end if msg: if not enable_color: msg = strip_ansi(msg) _file.write(msg) _file.flush() return