From cf7da1843c45a4c2df7a749f7886a2d2ba0ee92a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 19:25:40 +0200 Subject: Adding upstream version 7.2.6. Signed-off-by: Daniel Baumann --- sphinx/util/display.py | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 sphinx/util/display.py (limited to 'sphinx/util/display.py') diff --git a/sphinx/util/display.py b/sphinx/util/display.py new file mode 100644 index 0000000..199119c --- /dev/null +++ b/sphinx/util/display.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import functools +from typing import Any, Callable, TypeVar + +from sphinx.locale import __ +from sphinx.util import logging +from sphinx.util.console import bold # type: ignore[attr-defined] + +if False: + from collections.abc import Iterable, Iterator + from types import TracebackType + +logger = logging.getLogger(__name__) + + +def display_chunk(chunk: Any) -> str: + if isinstance(chunk, (list, tuple)): + if len(chunk) == 1: + return str(chunk[0]) + return f'{chunk[0]} .. {chunk[-1]}' + return str(chunk) + + +T = TypeVar('T') + + +def status_iterator( + iterable: Iterable[T], + summary: str, + color: str = 'darkgreen', + length: int = 0, + verbosity: int = 0, + stringify_func: Callable[[Any], str] = display_chunk, +) -> Iterator[T]: + single_line = verbosity < 1 + bold_summary = bold(summary) + if length == 0: + logger.info(bold_summary, nonl=True) + for item in iterable: + logger.info(stringify_func(item) + ' ', nonl=True, color=color) + yield item + else: + for i, item in enumerate(iterable, start=1): + if single_line: + # clear the entire line ('Erase in Line') + logger.info('\x1b[2K', nonl=True) + logger.info(f'{bold_summary}[{i / length: >4.0%}] ', nonl=True) # NoQA: G004 + # Emit the string representation of ``item`` + logger.info(stringify_func(item), nonl=True, color=color) + # If in single-line mode, emit a carriage return to move the cursor + # to the start of the line. + # If not, emit a newline to move the cursor to the next line. + logger.info('\r' * single_line, nonl=single_line) + yield item + logger.info('') + + +class SkipProgressMessage(Exception): + pass + + +class progress_message: + def __init__(self, message: str) -> None: + self.message = message + + def __enter__(self) -> None: + logger.info(bold(self.message + '... '), nonl=True) + + def __exit__( + self, + typ: type[BaseException] | None, + val: BaseException | None, + tb: TracebackType | None, + ) -> bool: + if isinstance(val, SkipProgressMessage): + logger.info(__('skipped')) + if val.args: + logger.info(*val.args) + return True + elif val: + logger.info(__('failed')) + else: + logger.info(__('done')) + + return False + + def __call__(self, f: Callable) -> Callable: + @functools.wraps(f) + def wrapper(*args: Any, **kwargs: Any) -> Any: + with self: + return f(*args, **kwargs) + + return wrapper -- cgit v1.2.3