From 5bb0bb4be543fd5eca41673696a62ed80d493591 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 5 Jun 2024 18:20:58 +0200 Subject: Adding upstream version 7.3.7. Signed-off-by: Daniel Baumann --- tests/test_util/test_util_console.py | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 tests/test_util/test_util_console.py (limited to 'tests/test_util/test_util_console.py') diff --git a/tests/test_util/test_util_console.py b/tests/test_util/test_util_console.py new file mode 100644 index 0000000..b617a33 --- /dev/null +++ b/tests/test_util/test_util_console.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +import itertools +import operator +from typing import TYPE_CHECKING + +import pytest + +from sphinx.util.console import blue, reset, strip_colors, strip_escape_sequences + +if TYPE_CHECKING: + from collections.abc import Callable, Sequence + from typing import Final, TypeVar + + _T = TypeVar('_T') + +CURSOR_UP: Final[str] = '\x1b[2A' # ignored ANSI code +ERASE_LINE: Final[str] = '\x1b[2K' # supported ANSI code +TEXT: Final[str] = '\x07 Hello world!' + + +@pytest.mark.parametrize( + ('strip_function', 'ansi_base_blocks', 'text_base_blocks'), + [ + ( + strip_colors, + # double ERASE_LINE so that the tested strings may have 2 of them + [TEXT, blue(TEXT), reset(TEXT), ERASE_LINE, ERASE_LINE, CURSOR_UP], + # :func:`strip_colors` removes color codes but keeps ERASE_LINE and CURSOR_UP + [TEXT, TEXT, TEXT, ERASE_LINE, ERASE_LINE, CURSOR_UP], + ), + ( + strip_escape_sequences, + # double ERASE_LINE so that the tested strings may have 2 of them + [TEXT, blue(TEXT), reset(TEXT), ERASE_LINE, ERASE_LINE, CURSOR_UP], + # :func:`strip_escape_sequences` strips ANSI codes known by Sphinx + [TEXT, TEXT, TEXT, '', '', CURSOR_UP], + ), + ], + ids=[strip_colors.__name__, strip_escape_sequences.__name__], +) +def test_strip_ansi( + strip_function: Callable[[str], str], + ansi_base_blocks: Sequence[str], + text_base_blocks: Sequence[str], +) -> None: + assert callable(strip_function) + assert len(text_base_blocks) == len(ansi_base_blocks) + N = len(ansi_base_blocks) + + def next_ansi_blocks(choices: Sequence[str], n: int) -> Sequence[str]: + # Get a list of *n* words from a cyclic sequence of *choices*. + # + # For instance ``next_ansi_blocks(['a', 'b'], 3) == ['a', 'b', 'a']``. + stream = itertools.cycle(choices) + return list(map(operator.itemgetter(0), zip(stream, range(n)))) + + # generate all permutations of length N + for sigma in itertools.permutations(range(N), N): + # apply the permutation on the blocks with ANSI codes + ansi_blocks = list(map(ansi_base_blocks.__getitem__, sigma)) + # apply the permutation on the blocks with stripped codes + text_blocks = list(map(text_base_blocks.__getitem__, sigma)) + + for glue, n in itertools.product(['.', '\n', '\r\n'], range(4 * N)): + ansi_strings = next_ansi_blocks(ansi_blocks, n) + text_strings = next_ansi_blocks(text_blocks, n) + assert len(ansi_strings) == len(text_strings) == n + + ansi_string = glue.join(ansi_strings) + text_string = glue.join(text_strings) + assert strip_function(ansi_string) == text_string + + +def test_strip_ansi_short_forms(): + # In Sphinx, we always "normalize" the color codes so that they + # match "\x1b\[(\d\d;){0,2}(\d\d)m" but it might happen that + # some messages use '\x1b[0m' instead of ``reset(s)``, so we + # test whether this alternative form is supported or not. + + for strip_function in [strip_colors, strip_escape_sequences]: + # \x1b[m and \x1b[0m are equivalent to \x1b[00m + assert strip_function('\x1b[m') == '' + assert strip_function('\x1b[0m') == '' + + # \x1b[1m is equivalent to \x1b[01m + assert strip_function('\x1b[1mbold\x1b[0m') == 'bold' + + # \x1b[K is equivalent to \x1b[0K + assert strip_escape_sequences('\x1b[K') == '' -- cgit v1.2.3