Use `sphinx._cli.util.colour in sphinx.util.console` (#13241)

This commit is contained in:
Adam Turner
2025-01-16 16:57:28 +00:00
committed by GitHub
parent dd7a00dfb5
commit a56fdad70b
36 changed files with 149 additions and 272 deletions

View File

@@ -10,7 +10,7 @@ if sys.platform == 'win32':
import colorama
_COLOURING_DISABLED = True
_COLOURING_DISABLED = False
def terminal_supports_colour() -> bool:
@@ -19,6 +19,7 @@ def terminal_supports_colour() -> bool:
return False
if sys.platform == 'win32':
colorama.just_fix_windows_console()
return True
if 'FORCE_COLOUR' in os.environ or 'FORCE_COLOR' in os.environ:
return True
if os.environ.get('CI', '') in {'true', '1'}:
@@ -58,6 +59,7 @@ def _create_colour_func(escape_code: str, /) -> Callable[[str], str]:
return text
return f'\x1b[{escape_code}m{text}\x1b[39;49;00m'
inner.__escape_code = escape_code # type: ignore[attr-defined]
return inner
@@ -75,7 +77,7 @@ else:
def inner(text: str) -> str:
if _COLOURING_DISABLED:
return text
return f'\x01\x1b[{escape_code}m\x02{text}\x01\x1b[39;49;00m\x02'
return f'\1\x1b[{escape_code}m\2{text}\1\x1b[39;49;00m\2'
return inner

View File

@@ -16,6 +16,7 @@ from docutils.parsers.rst import roles
import sphinx
from sphinx import locale, package_dir
from sphinx._cli.util.colour import bold
from sphinx.config import Config
from sphinx.environment import BuildEnvironment
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
@@ -27,7 +28,6 @@ from sphinx.registry import SphinxComponentRegistry
from sphinx.util import docutils, logging
from sphinx.util._pathlib import _StrPath, _StrPathProperty
from sphinx.util.build_phase import BuildPhase
from sphinx.util.console import bold
from sphinx.util.display import progress_message
from sphinx.util.i18n import CatalogRepository
from sphinx.util.logging import prefixed_warnings

View File

@@ -13,6 +13,7 @@ from typing import TYPE_CHECKING, final
from docutils import nodes
from docutils.utils import DependencyList
from sphinx._cli.util.colour import bold
from sphinx.environment import (
CONFIG_CHANGED_REASON,
CONFIG_OK,
@@ -29,7 +30,6 @@ from sphinx.util import (
from sphinx.util._importer import import_object
from sphinx.util._pathlib import _StrPathProperty
from sphinx.util.build_phase import BuildPhase
from sphinx.util.console import bold
from sphinx.util.display import progress_message, status_iterator
from sphinx.util.docutils import sphinx_domains
from sphinx.util.i18n import CatalogRepository, docname_to_domain

View File

@@ -7,11 +7,11 @@ import os.path
from typing import TYPE_CHECKING
from sphinx import package_dir
from sphinx._cli.util.colour import bold
from sphinx.builders import Builder
from sphinx.locale import _, __
from sphinx.theming import HTMLThemeFactory
from sphinx.util import logging
from sphinx.util.console import bold
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import ensuredir, os_path

View File

@@ -14,11 +14,11 @@ from uuid import uuid4
from docutils import nodes
from sphinx import addnodes, package_dir
from sphinx._cli.util.colour import bold
from sphinx.builders import Builder
from sphinx.errors import ThemeError
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import bold
from sphinx.util.display import status_iterator
from sphinx.util.i18n import docname_to_domain
from sphinx.util.index_entries import split_index_msg

View File

@@ -23,6 +23,7 @@ from docutils.io import DocTreeInput, StringOutput
from sphinx import __display_version__, package_dir
from sphinx import version_info as sphinx_version
from sphinx._cli.util.colour import bold
from sphinx.builders import Builder
from sphinx.builders.html._assets import (
_CascadingStyleSheet,
@@ -45,7 +46,6 @@ from sphinx.util import logging
from sphinx.util._pathlib import _StrPath
from sphinx.util._timestamps import _format_rfc3339_microseconds
from sphinx.util._uri import is_url
from sphinx.util.console import bold
from sphinx.util.display import progress_message, status_iterator
from sphinx.util.docutils import new_document
from sphinx.util.fileutil import copy_asset

View File

@@ -12,6 +12,7 @@ from docutils.frontend import OptionParser
import sphinx.builders.latex.nodes # NoQA: F401 # Workaround: import this before writer to avoid ImportError
from sphinx import addnodes, highlighting, package_dir
from sphinx._cli.util.colour import darkgreen
from sphinx.builders import Builder
from sphinx.builders.latex.constants import (
ADDITIONAL_SETTINGS,
@@ -25,7 +26,6 @@ from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import NoUri, SphinxError
from sphinx.locale import _, __
from sphinx.util import logging, texescape
from sphinx.util.console import darkgreen
from sphinx.util.display import progress_message, status_iterator
from sphinx.util.docutils import SphinxFileOutput, new_document
from sphinx.util.fileutil import copy_asset_file

View File

@@ -24,12 +24,12 @@ from requests.exceptions import (
)
from requests.exceptions import Timeout as RequestTimeout
from sphinx._cli.util.colour import darkgray, darkgreen, purple, red, turquoise
from sphinx.builders.dummy import DummyBuilder
from sphinx.locale import __
from sphinx.transforms.post_transforms import SphinxPostTransform
from sphinx.util import logging, requests
from sphinx.util._uri import encode_uri
from sphinx.util.console import darkgray, darkgreen, purple, red, turquoise
from sphinx.util.http_date import rfc1123_to_epoch
from sphinx.util.nodes import get_node_line

View File

@@ -10,10 +10,10 @@ from docutils.frontend import OptionParser
from docutils.io import FileOutput
from sphinx import addnodes
from sphinx._cli.util.colour import darkgreen
from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import darkgreen
from sphinx.util.display import progress_message
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import ensuredir, make_filename_from_project

View File

@@ -7,12 +7,12 @@ from typing import TYPE_CHECKING
from docutils import nodes
from sphinx._cli.util.colour import darkgreen
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.deprecation import RemovedInSphinx10Warning
from sphinx.environment.adapters.toctree import global_toctree_for_doc
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import darkgreen
from sphinx.util.display import progress_message
from sphinx.util.nodes import inline_all_toctrees

View File

@@ -12,12 +12,12 @@ from docutils.frontend import OptionParser
from docutils.io import FileOutput
from sphinx import addnodes, package_dir
from sphinx._cli.util.colour import darkgreen
from sphinx.builders import Builder
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import NoUri
from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.console import darkgreen
from sphinx.util.display import progress_message, status_iterator
from sphinx.util.docutils import new_document
from sphinx.util.nodes import inline_all_toctrees

View File

@@ -13,12 +13,11 @@ from typing import TYPE_CHECKING
import sphinx._cli.util.errors
import sphinx.locale
from sphinx import __display_version__
from sphinx._cli.util.colour import terminal_supports_colour
from sphinx._cli.util.colour import disable_colour, terminal_supports_colour
from sphinx.application import Sphinx
from sphinx.locale import __
from sphinx.util._io import TeeStripANSI
from sphinx.util._pathlib import _StrPath
from sphinx.util.console import nocolor
from sphinx.util.docutils import docutils_namespace, patch_docutils
from sphinx.util.osutil import ensuredir
@@ -328,7 +327,7 @@ def _validate_filenames(
def _validate_colour_support(colour: str) -> None:
if colour == 'no' or (colour == 'auto' and not terminal_supports_colour()):
nocolor()
disable_colour()
def _parse_logging(

View File

@@ -16,10 +16,9 @@ from contextlib import chdir
from typing import TYPE_CHECKING
import sphinx
from sphinx._cli.util.colour import terminal_supports_colour
from sphinx._cli.util.colour import blue, bold, disable_colour, terminal_supports_colour
from sphinx.cmd.build import build_main
from sphinx.util._pathlib import _StrPath
from sphinx.util.console import blue, bold, nocolor
from sphinx.util.osutil import rmtree
if TYPE_CHECKING:
@@ -93,7 +92,7 @@ class Make:
def build_help(self) -> None:
if not terminal_supports_colour():
nocolor()
disable_colour()
print(bold('Sphinx v%s' % sphinx.__display_version__))
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2))

View File

@@ -31,9 +31,14 @@ from docutils.utils import column_width
import sphinx.locale
from sphinx import __display_version__, package_dir
from sphinx._cli.util.colour import terminal_supports_colour
from sphinx._cli.util.colour import (
bold,
disable_colour,
red,
terminal_supports_colour,
)
from sphinx.locale import __
from sphinx.util.console import bold, colorize, nocolor, red
from sphinx.util.console import colorize
from sphinx.util.osutil import ensuredir
from sphinx.util.template import SphinxRenderer
@@ -726,7 +731,7 @@ def main(argv: Sequence[str] = (), /) -> int:
sphinx.locale.init_console()
if not terminal_supports_colour():
nocolor()
disable_colour()
# parse options
parser = get_parser()

View File

@@ -17,10 +17,10 @@ from importlib import import_module
from typing import TYPE_CHECKING
import sphinx
from sphinx._cli.util.colour import red
from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import red
from sphinx.util.inspect import safe_getattr
if TYPE_CHECKING:

View File

@@ -19,10 +19,10 @@ from packaging.specifiers import InvalidSpecifier, SpecifierSet
from packaging.version import Version
import sphinx
from sphinx._cli.util.colour import bold
from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import bold
from sphinx.util.docutils import SphinxDirective
from sphinx.util.osutil import relpath

View File

@@ -15,7 +15,7 @@ from docutils.parsers.rst import directives, roles
import sphinx.application
import sphinx.locale
import sphinx.pycode
from sphinx.util.console import strip_colors
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.util.docutils import additional_nodes
if TYPE_CHECKING:
@@ -271,7 +271,11 @@ def _clean_up_global_state() -> None:
# deprecated name -> (object to return, canonical path or '', removal version)
_DEPRECATED_OBJECTS: dict[str, tuple[Any, str, tuple[int, int]]] = {
'strip_escseq': (strip_colors, 'sphinx.util.console.strip_colors', (9, 0)),
'strip_escseq': (
strip_escape_sequences,
'sphinx.util.console.strip_escape_sequences',
(9, 0),
),
}

View File

@@ -127,10 +127,10 @@ def __getattr__(name: str) -> Any:
return patfilter
if name == 'strip_colors':
from sphinx.util.console import strip_colors
if name == 'strip_escape_sequences':
from sphinx._cli.util.errors import strip_escape_sequences
return strip_colors
return strip_escape_sequences
if name in {
'caption_ref_re',

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from sphinx.util.console import strip_escape_sequences
from sphinx._cli.util.errors import strip_escape_sequences
if TYPE_CHECKING:
from typing import Protocol

View File

@@ -2,74 +2,39 @@
from __future__ import annotations
import re
import shutil
import sys
from typing import TYPE_CHECKING
from sphinx._cli.util.colour import (
terminal_supports_colour as color_terminal, # NoQA: F401
import sphinx._cli.util.colour
from sphinx._cli.util.colour import ( # NoQA: F401
_create_input_mode_colour_func,
colourise,
darkblue,
darkgray,
darkgreen,
darkred,
disable_colour,
enable_colour,
faint,
fuchsia,
green,
lightgray,
purple,
red,
reset,
standout,
teal,
terminal_supports_colour,
turquoise,
underline,
white,
yellow,
)
from sphinx._cli.util.errors import strip_escape_sequences
if TYPE_CHECKING:
from typing import Final
# fmt: off
def reset(text: str) -> str: ...
def bold(text: str) -> str: ...
def faint(text: str) -> str: ...
def standout(text: str) -> str: ...
def underline(text: str) -> str: ...
def blink(text: str) -> str: ...
def black(text: str) -> str: ...
def white(text: str) -> str: ...
def red(text: str) -> str: ...
def green(text: str) -> str: ...
def yellow(text: str) -> str: ...
def blue(text: str) -> str: ...
def fuchsia(text: str) -> str: ...
def teal(text: str) -> str: ...
def darkgray(text: str) -> str: ...
def lightgray(text: str) -> str: ...
def darkred(text: str) -> str: ...
def darkgreen(text: str) -> str: ...
def brown(text: str) -> str: ...
def darkblue(text: str) -> str: ...
def purple(text: str) -> str: ...
def turquoise(text: str) -> str: ...
# fmt: on
try:
# check if colorama is installed to support color on Windows
import colorama
COLORAMA_AVAILABLE = True
except ImportError:
COLORAMA_AVAILABLE = False
_CSI: Final[str] = re.escape('\x1b[') # 'ESC [': Control Sequence Introducer
# Pattern matching ANSI control sequences containing colors.
_ansi_color_re: Final[re.Pattern[str]] = re.compile(r'\x1b\[(?:\d+;){0,2}\d*m')
_ansi_re: Final[re.Pattern[str]] = re.compile(
_CSI
+ r"""
(?:
(?:\d+;){0,2}\d*m # ANSI color code ('m' is equivalent to '0m')
|
[012]?K # ANSI Erase in Line ('K' is equivalent to '0K')
)""",
re.VERBOSE | re.ASCII,
)
"""Pattern matching ANSI CSI colors (SGR) and erase line (EL) sequences.
See :func:`strip_escape_sequences` for details.
"""
codes: dict[str, str] = {}
color_terminal = terminal_supports_colour
nocolor = disable_colour
coloron = enable_colour
strip_colors = strip_escape_sequences
def terminal_safe(s: str) -> str:
@@ -86,7 +51,7 @@ _tw: int = get_terminal_width()
def term_width_line(text: str) -> str:
if not codes:
if sphinx._cli.util.colour._COLOURING_DISABLED:
# if no coloring, don't output fancy backspaces
return text + '\n'
else:
@@ -94,103 +59,13 @@ def term_width_line(text: str) -> str:
return text.ljust(_tw + len(text) - len(strip_escape_sequences(text))) + '\r'
def nocolor() -> None:
if sys.platform == 'win32' and COLORAMA_AVAILABLE:
colorama.deinit()
codes.clear()
def coloron() -> None:
codes.update(_orig_codes)
def colorize(name: str, text: str, input_mode: bool = False) -> str:
def escseq(name: str) -> str:
# Wrap escape sequence with ``\1`` and ``\2`` to let readline know
# it is non-printable characters
# ref: https://tiswww.case.edu/php/chet/readline/readline.html
#
# Note: This hack does not work well in Windows (see #5059)
escape = codes.get(name, '')
if input_mode and escape and sys.platform != 'win32':
return '\1' + escape + '\2'
else:
return escape
if input_mode:
colour_func = globals()[name]
escape_code = getattr(colour_func, '__escape_code', '')
if not escape_code:
return colour_func(text)
inner = _create_input_mode_colour_func(escape_code)
return inner(text)
return escseq(name) + text + escseq('reset')
def strip_colors(s: str) -> str:
"""Remove the ANSI color codes in a string *s*.
.. caution::
This function is not meant to be used in production and should only
be used for testing Sphinx's output messages.
.. seealso:: :func:`strip_escape_sequences`
"""
return _ansi_color_re.sub('', s)
def strip_escape_sequences(text: str, /) -> str:
r"""Remove the ANSI CSI colors and "erase in line" sequences.
Other `escape sequences `__ (e.g., VT100-specific functions) are not
supported and only control sequences *natively* known to Sphinx (i.e.,
colors declared in this module and "erase entire line" (``'\x1b[2K'``))
are eliminated by this function.
.. caution::
This function is not meant to be used in production and should only
be used for testing Sphinx's output messages that were not tempered
with by third-party extensions.
.. versionadded:: 7.3
This function is added as an *experimental* feature.
__ https://en.wikipedia.org/wiki/ANSI_escape_code
"""
return _ansi_re.sub('', text)
def create_color_func(name: str) -> None:
def inner(text: str) -> str:
return colorize(name, text)
globals()[name] = inner
_attrs = {
'reset': '39;49;00m',
'bold': '01m',
'faint': '02m',
'standout': '03m',
'underline': '04m',
'blink': '05m',
}
for __name, __value in _attrs.items():
codes[__name] = '\x1b[' + __value
_colors = [
('black', 'darkgray'),
('darkred', 'red'),
('darkgreen', 'green'),
('brown', 'yellow'),
('darkblue', 'blue'),
('purple', 'fuchsia'),
('turquoise', 'teal'),
('lightgray', 'white'),
]
for __i, (__dark, __light) in enumerate(_colors, 30):
codes[__dark] = '\x1b[%im' % __i
codes[__light] = '\x1b[%im' % (__i + 60)
_orig_codes = codes.copy()
for _name in codes:
create_color_func(_name)
return colourise(name, text)

View File

@@ -2,10 +2,9 @@ from __future__ import annotations
import functools
from sphinx._cli.util.colour import terminal_supports_colour
from sphinx._cli.util.colour import bold, terminal_supports_colour
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import bold
if False:
from collections.abc import Callable, Iterable, Iterator

View File

View File

@@ -4,45 +4,38 @@ import itertools
import operator
from typing import TYPE_CHECKING
import pytest
from sphinx.util.console import blue, reset, strip_colors, strip_escape_sequences
from sphinx._cli.util.colour import blue, reset
from sphinx._cli.util.errors import strip_escape_sequences
if TYPE_CHECKING:
from collections.abc import Callable, Sequence
from collections.abc import Sequence
from typing import Final
CURSOR_UP: Final[str] = '\x1b[2A' # ignored ANSI code
ERASE_LINE: Final[str] = '\x1b[2K' # supported ANSI code
TEXT: Final[str] = '\x07 Hello world!'
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)
def test_strip_escape_sequences() -> None:
# double ERASE_LINE so that the tested strings may have 2 of them
ansi_base_blocks = [
TEXT,
blue(TEXT),
reset(TEXT),
ERASE_LINE,
ERASE_LINE,
CURSOR_UP,
]
# :func:`strip_escape_sequences` strips ANSI codes known by Sphinx
text_base_blocks = [
TEXT,
TEXT,
TEXT,
'',
'',
CURSOR_UP,
]
assert len(text_base_blocks) == len(ansi_base_blocks)
N = len(ansi_base_blocks)
@@ -67,7 +60,7 @@ def test_strip_ansi(
ansi_string = glue.join(ansi_strings)
text_string = glue.join(text_strings)
assert strip_function(ansi_string) == text_string
assert strip_escape_sequences(ansi_string) == text_string
def test_strip_ansi_short_forms():
@@ -76,7 +69,7 @@ def test_strip_ansi_short_forms():
# 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:
for strip_function in strip_escape_sequences, strip_escape_sequences:
# \x1b[m and \x1b[0m are equivalent to \x1b[00m
assert strip_function('\x1b[m') == ''
assert strip_function('\x1b[0m') == ''

View File

@@ -13,10 +13,10 @@ import pytest
from docutils import nodes
import sphinx.application
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.errors import ExtensionError
from sphinx.testing.util import SphinxTestApp
from sphinx.util import logging
from sphinx.util.console import strip_colors
if TYPE_CHECKING:
import os
@@ -84,14 +84,14 @@ def test_emit_with_nonascii_name_node(app):
@pytest.mark.sphinx('html', testroot='root')
def test_extensions(app):
app.setup_extension('shutil')
warning = strip_colors(app.warning.getvalue())
warning = strip_escape_sequences(app.warning.getvalue())
assert "extension 'shutil' has no setup() function" in warning
@pytest.mark.sphinx('html', testroot='root')
def test_extension_in_blacklist(app):
app.setup_extension('sphinxjp.themecore')
msg = strip_colors(app.warning.getvalue())
msg = strip_escape_sequences(app.warning.getvalue())
assert msg.startswith("WARNING: the extension 'sphinxjp.themecore' was")

View File

@@ -9,9 +9,9 @@ from typing import TYPE_CHECKING
import pytest
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.builders.html import validate_html_extra_path, validate_html_static_path
from sphinx.errors import ConfigError
from sphinx.util.console import strip_colors
from sphinx.util.inventory import InventoryFile
from tests.test_builders.xpath_data import FIGURE_CAPTION
@@ -512,7 +512,7 @@ def test_validate_html_extra_path(app):
validate_html_extra_path(app, app.config)
assert app.config.html_extra_path == ['_static']
warnings = strip_colors(app.warning.getvalue()).splitlines()
warnings = strip_escape_sequences(app.warning.getvalue()).splitlines()
assert "html_extra_path entry '/path/to/not_found' does not exist" in warnings[0]
assert warnings[1].endswith(' is placed inside outdir')
assert warnings[2].endswith(' does not exist')
@@ -536,7 +536,7 @@ def test_validate_html_static_path(app):
validate_html_static_path(app, app.config)
assert app.config.html_static_path == ['_static']
warnings = strip_colors(app.warning.getvalue()).splitlines()
warnings = strip_escape_sequences(app.warning.getvalue()).splitlines()
assert "html_static_path entry '/path/to/not_found' does not exist" in warnings[0]
assert warnings[1].endswith(' is placed inside outdir')
assert warnings[2].endswith(' does not exist')
@@ -598,7 +598,7 @@ def test_html_remove_sources_before_write_gh_issue_10786(app):
app.build()
assert not target.exists()
ws = strip_colors(app.warning.getvalue()).splitlines()
ws = strip_escape_sequences(app.warning.getvalue()).splitlines()
assert len(ws) >= 1
file = os.fsdecode(target)

View File

@@ -19,6 +19,7 @@ import pytest
from urllib3.poolmanager import PoolManager
import sphinx.util.http_date
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.builders.linkcheck import (
CheckRequest,
Hyperlink,
@@ -28,7 +29,6 @@ from sphinx.builders.linkcheck import (
)
from sphinx.util import requests
from sphinx.util._pathlib import _StrPath
from sphinx.util.console import strip_colors
from tests.utils import CERT_FILE, serve_application
@@ -775,7 +775,7 @@ def test_linkcheck_allowed_redirects(app: SphinxTestApp) -> None:
assert (
f'index.rst:3: WARNING: redirect http://{address}/path2 - with Found to '
f'http://{address}/?redirected=1\n'
) in strip_colors(app.warning.getvalue())
) in strip_escape_sequences(app.warning.getvalue())
assert len(app.warning.getvalue().splitlines()) == 1
@@ -1061,7 +1061,7 @@ def test_too_many_requests_retry_after_int_delay(app, capsys):
'info': '',
}
rate_limit_log = f'-rate limited- http://{address}/ | sleeping...\n'
assert rate_limit_log in strip_colors(app.status.getvalue())
assert rate_limit_log in strip_escape_sequences(app.status.getvalue())
_stdout, stderr = capsys.readouterr()
assert stderr == textwrap.dedent(
"""\

View File

@@ -7,8 +7,8 @@ import traceback
import pytest
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.errors import SphinxError
from sphinx.util.console import strip_colors
ENV_WARNINGS = """\
{root}/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
@@ -55,7 +55,7 @@ TEXINFO_WARNINGS = (
def _check_warnings(expected_warnings: str, warning: str) -> None:
warnings = strip_colors(re.sub(re.escape(os.sep) + '{1,2}', '/', warning))
warnings = strip_escape_sequences(re.sub(re.escape(os.sep) + '{1,2}', '/', warning))
assert re.match(f'{expected_warnings}$', warnings), (
"Warnings don't match:\n"
f'--- Expected (regex):\n{expected_warnings}\n'
@@ -127,7 +127,7 @@ def setup(app):
tmp_path.joinpath('index.rst').write_text('Test\n====\n', encoding='utf-8')
app = make_app(srcdir=tmp_path)
app.build()
assert strip_colors(app.warning.getvalue()).strip() == (
assert strip_escape_sequences(app.warning.getvalue()).strip() == (
"WARNING: cannot cache unpickable configuration value: 'my_config' "
'(because it contains a function, class, or module object) [config.cache]'
)

View File

@@ -7,6 +7,7 @@ from pathlib import Path
import pytest
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.builders.latex import LaTeXBuilder
from sphinx.config import Config
@@ -17,7 +18,6 @@ from sphinx.environment import (
CONFIG_OK,
_differing_config_keys,
)
from sphinx.util.console import strip_colors
@pytest.mark.sphinx('dummy', testroot='basic')
@@ -28,7 +28,7 @@ def test_config_status(make_app, app_params):
app1 = make_app(*args, freshenv=True, **kwargs)
assert app1.env.config_status == CONFIG_NEW
app1.build()
output = strip_colors(app1.status.getvalue())
output = strip_escape_sequences(app1.status.getvalue())
# assert 'The configuration has changed' not in output
assert '[new config] 1 added' in output
@@ -36,7 +36,7 @@ def test_config_status(make_app, app_params):
app2 = make_app(*args, **kwargs)
assert app2.env.config_status == CONFIG_OK
app2.build()
output = strip_colors(app2.status.getvalue())
output = strip_escape_sequences(app2.status.getvalue())
assert 'The configuration has changed' not in output
assert '0 added, 0 changed, 0 removed' in output
@@ -49,7 +49,7 @@ def test_config_status(make_app, app_params):
assert app3.env.config_status == CONFIG_CHANGED
app3.build()
shutil.move(other_fname, fname)
output = strip_colors(app3.status.getvalue())
output = strip_escape_sequences(app3.status.getvalue())
assert 'The configuration has changed' in output
assert "[config changed ('master_doc')] 1 added," in output
@@ -60,7 +60,7 @@ def test_config_status(make_app, app_params):
assert app4.env.config_status == CONFIG_EXTENSIONS_CHANGED
app4.build()
want_str = "[extensions changed ('sphinx.ext.autodoc')] 1 added"
output = strip_colors(app4.status.getvalue())
output = strip_escape_sequences(app4.status.getvalue())
assert 'The configuration has changed' not in output
assert want_str in output

View File

@@ -11,6 +11,7 @@ import pytest
from docutils import nodes
from sphinx import addnodes
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.builders.html import INVENTORY_FILENAME
from sphinx.config import Config
from sphinx.errors import ConfigError
@@ -27,7 +28,6 @@ from sphinx.ext.intersphinx._load import (
)
from sphinx.ext.intersphinx._resolve import missing_reference
from sphinx.ext.intersphinx._shared import _IntersphinxProject
from sphinx.util.console import strip_colors
from tests.test_util.intersphinx_data import (
INVENTORY_V2,
@@ -530,7 +530,7 @@ def test_validate_intersphinx_mapping_warnings(app):
match=r'^Invalid `intersphinx_mapping` configuration \(16 errors\).$',
):
validate_intersphinx_mapping(app, app.config)
warnings = strip_colors(app.warning.getvalue()).splitlines()
warnings = strip_escape_sequences(app.warning.getvalue()).splitlines()
assert len(warnings) == len(bad_intersphinx_mapping) - 3
assert warnings == [
"ERROR: Invalid intersphinx project identifier `''` in intersphinx_mapping. Project identifiers must be non-empty strings.",
@@ -705,7 +705,7 @@ def test_intersphinx_role(app):
app.build()
content = (app.outdir / 'index.html').read_text(encoding='utf8')
warnings = strip_colors(app.warning.getvalue()).splitlines()
warnings = strip_escape_sequences(app.warning.getvalue()).splitlines()
index_path = app.srcdir / 'index.rst'
assert warnings == [
f"{index_path}:21: WARNING: role for external cross-reference not found in domain 'py': 'nope' [intersphinx.external]",

View File

@@ -18,8 +18,8 @@ from babel.messages.catalog import Catalog
from docutils import nodes
from sphinx import locale
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.testing.util import assert_node, etree_parse
from sphinx.util.console import strip_colors
from sphinx.util.nodes import NodeMatcher
if TYPE_CHECKING:
@@ -1893,7 +1893,7 @@ def test_image_glob_intl_using_figure_language_filename(app):
def getwarning(warnings: StringIO) -> str:
return strip_colors(warnings.getvalue().replace(os.sep, '/'))
return strip_escape_sequences(warnings.getvalue().replace(os.sep, '/'))
@pytest.mark.sphinx(

View File

@@ -8,9 +8,9 @@ from typing import TYPE_CHECKING
import pytest
from sphinx._cli.util.colour import disable_colour, enable_colour
from sphinx.cmd import quickstart as qs
from sphinx.testing.util import SphinxTestApp
from sphinx.util.console import coloron, nocolor
if TYPE_CHECKING:
from collections.abc import Callable
@@ -21,7 +21,7 @@ warnfile = StringIO()
def setup_module():
nocolor()
disable_colour()
def mock_input(
@@ -50,7 +50,7 @@ real_input: Callable[[str], str] = input
def teardown_module():
qs.term_input = real_input
coloron()
enable_colour()
def test_do_prompt():

View File

@@ -4,7 +4,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from sphinx.util.console import strip_colors
from sphinx._cli.util.errors import strip_escape_sequences
if TYPE_CHECKING:
from pathlib import Path
@@ -35,7 +35,7 @@ Title
)
app = make_app(srcdir=tmp_path)
app.build()
warnings = strip_colors(app.warning.getvalue()).lstrip()
warnings = strip_escape_sequences(app.warning.getvalue()).lstrip()
warnings = warnings.replace(str(tmp_path / 'index.rst'), 'source/index.rst')
assert (
warnings

View File

@@ -5,13 +5,13 @@ from __future__ import annotations
import pytest
import sphinx.util
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.deprecation import RemovedInSphinx10Warning, RemovedInSphinx90Warning
from sphinx.errors import ExtensionError
from sphinx.util._files import DownloadFiles, FilenameUniqDict
from sphinx.util._importer import import_object
from sphinx.util._lines import parse_line_num_spec
from sphinx.util._uri import encode_uri, is_url
from sphinx.util.console import strip_colors
from sphinx.util.index_entries import _split_into, split_index_msg
from sphinx.util.matching import patfilter
from sphinx.util.nodes import (
@@ -78,7 +78,7 @@ def test_exported_attributes():
assert sphinx.util.isurl is is_url
assert sphinx.util.parselinenos is parse_line_num_spec
assert sphinx.util.patfilter is patfilter
assert sphinx.util.strip_colors is strip_colors
assert sphinx.util.strip_escape_sequences is strip_escape_sequences
assert sphinx.util.caption_ref_re is caption_ref_re
assert sphinx.util.explicit_title_re is explicit_title_re
assert sphinx.util.nested_parse_with_titles is nested_parse_with_titles

View File

@@ -4,8 +4,8 @@ from __future__ import annotations
import pytest
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.util import logging
from sphinx.util.console import strip_colors
from sphinx.util.display import (
SkipProgressMessage,
display_chunk,
@@ -30,7 +30,7 @@ def test_status_iterator_length_0(app):
app.status.seek(0)
app.status.truncate(0)
yields = list(status_iterator(['hello', 'sphinx', 'world'], 'testing ... '))
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert 'testing ... hello sphinx world \n' in output
assert yields == ['hello', 'sphinx', 'world']
@@ -47,7 +47,7 @@ def test_status_iterator_verbosity_0(app, monkeypatch):
['hello', 'sphinx', 'world'], 'testing ... ', length=3, verbosity=0
)
assert list(yields) == ['hello', 'sphinx', 'world']
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert 'testing ... [ 33%] hello\r' in output
assert 'testing ... [ 67%] sphinx\r' in output
assert 'testing ... [100%] world\r\n' in output
@@ -65,7 +65,7 @@ def test_status_iterator_verbosity_1(app, monkeypatch):
['hello', 'sphinx', 'world'], 'testing ... ', length=3, verbosity=1
)
assert list(yields) == ['hello', 'sphinx', 'world']
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert 'testing ... [ 33%] hello\n' in output
assert 'testing ... [ 67%] sphinx\n' in output
assert 'testing ... [100%] world\n\n' in output
@@ -80,14 +80,14 @@ def test_progress_message(app):
with progress_message('testing'):
logger.info('blah ', nonl=True)
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert 'testing... blah done\n' in output
# skipping case
with progress_message('testing'):
raise SkipProgressMessage('Reason: %s', 'error') # NoQA: EM101,TRY003
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert 'testing... skipped\nReason: error\n' in output
# error case
@@ -97,7 +97,7 @@ def test_progress_message(app):
except Exception:
pass
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert 'testing... failed\n' in output
# decorator
@@ -106,5 +106,5 @@ def test_progress_message(app):
logger.info('in func ', nonl=True)
func()
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert 'testing... in func done\n' in output

View File

@@ -7,8 +7,8 @@ from unittest import mock
import pytest
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.jinja2glue import BuiltinTemplateLoader
from sphinx.util.console import strip_colors
from sphinx.util.fileutil import _template_basename, copy_asset, copy_asset_file
@@ -127,7 +127,7 @@ def test_copy_asset_template(app):
app.build(force_all=True)
expected_msg = r'^Writing evaluated template result to [^\n]*\bAPI.html$'
output = strip_colors(app.status.getvalue())
output = strip_escape_sequences(app.status.getvalue())
assert re.findall(expected_msg, output, flags=re.MULTILINE)
@@ -136,7 +136,7 @@ def test_copy_asset_overwrite(app):
app.build()
src = app.srcdir / 'myext_static' / 'custom-styles.css'
dst = app.outdir / '_static' / 'custom-styles.css'
assert strip_colors(app.warning.getvalue()) == (
assert strip_escape_sequences(app.warning.getvalue()) == (
f'WARNING: Aborted attempted copy from {src} to {dst} '
'(the destination path has existing data). '
'[misc.copy_overwrite]\n'

View File

@@ -9,8 +9,9 @@ from pathlib import Path
import pytest
from docutils import nodes
from sphinx._cli.util.errors import strip_escape_sequences
from sphinx.util import logging
from sphinx.util.console import colorize, strip_colors
from sphinx.util.console import colorize
from sphinx.util.logging import is_suppressed_warning, prefixed_warnings
from sphinx.util.parallel import ParallelTasks
@@ -115,7 +116,7 @@ def test_once_warning_log(app):
logger.warning('message: %d', 1, once=True)
logger.warning('message: %d', 2, once=True)
warnings = strip_colors(app.warning.getvalue())
warnings = strip_escape_sequences(app.warning.getvalue())
assert 'WARNING: message: 1\nWARNING: message: 2\n' in warnings
@@ -271,7 +272,7 @@ def test_pending_warnings(app):
assert 'WARNING: message3' not in app.warning.getvalue()
# actually logged as ordered
warnings = strip_colors(app.warning.getvalue())
warnings = strip_escape_sequences(app.warning.getvalue())
assert 'WARNING: message2\nWARNING: message3' in warnings
@@ -381,7 +382,7 @@ def test_show_warning_types(app):
logger.warning('message3', type='test')
logger.warning('message4', type='test', subtype='logging')
warnings = strip_colors(app.warning.getvalue()).splitlines()
warnings = strip_escape_sequences(app.warning.getvalue()).splitlines()
assert warnings == [
'WARNING: message2',