From d3c91f951255c6729a53e38c895ddc0af036b5b9 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sat, 13 May 2023 02:50:38 +0100 Subject: [PATCH] Refactor ``status_iterator`` --- sphinx/util/display.py | 34 ++++++++++++++++++++-------------- tests/test_util_display.py | 37 ++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/sphinx/util/display.py b/sphinx/util/display.py index 99b76599a1e..f0e016c3ada 100644 --- a/sphinx/util/display.py +++ b/sphinx/util/display.py @@ -5,7 +5,7 @@ from sphinx.locale import __ from sphinx.util import logging -from sphinx.util.console import bold, colorize, term_width_line # type: ignore +from sphinx.util.console import bold # type: ignore if False: from types import TracebackType @@ -32,20 +32,26 @@ def status_iterator( 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 i, item in enumerate(iterable, start=1): - item_str = colorize(color, stringify_func(item)) - if length == 0: - logger.info(item_str, nonl=True) - logger.info(' ', nonl=True) - else: - s = f'{bold(summary)}[{int(100 * i / length): >3d}%] {item_str}' - if verbosity: - logger.info(s + '\n', nonl=True) - else: - logger.info(term_width_line(s), nonl=True) - yield item + 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('') diff --git a/tests/test_util_display.py b/tests/test_util_display.py index 52950402ebe..b4fc892031e 100644 --- a/tests/test_util_display.py +++ b/tests/test_util_display.py @@ -1,7 +1,5 @@ """Tests util functions.""" -from unittest.mock import patch - import pytest from sphinx.testing.util import strip_escseq @@ -23,17 +21,21 @@ def test_display_chunk(): @pytest.mark.sphinx('dummy') -@patch('sphinx.util.console._tw', 40) # terminal width = 40 -def test_status_iterator(app, status, warning): +def test_status_iterator_length_0(app, status, warning): logging.setup(app, status, warning) - # # test for old_status_iterator - # status.seek(0) - # status.truncate(0) - # yields = list(status_iterator(['hello', 'sphinx', 'world'], 'testing ... ')) - # output = strip_escseq(status.getvalue()) - # assert 'testing ... hello sphinx world \n' in output - # assert yields == ['hello', 'sphinx', 'world'] + # test for status_iterator (length=0) + status.seek(0) + status.truncate(0) + yields = list(status_iterator(['hello', 'sphinx', 'world'], 'testing ... ')) + output = strip_escseq(status.getvalue()) + assert 'testing ... hello sphinx world \n' in output + assert yields == ['hello', 'sphinx', 'world'] + + +@pytest.mark.sphinx('dummy') +def test_status_iterator_verbosity_0(app, status, warning): + logging.setup(app, status, warning) # test for status_iterator (verbosity=0) status.seek(0) @@ -41,11 +43,16 @@ def test_status_iterator(app, status, warning): yields = list(status_iterator(['hello', 'sphinx', 'world'], 'testing ... ', length=3, verbosity=0)) output = strip_escseq(status.getvalue()) - assert 'testing ... [ 33%] hello \r' in output - assert 'testing ... [ 66%] sphinx \r' in output - assert 'testing ... [100%] world \r\n' in output + assert 'testing ... [ 33%] hello\r' in output + assert 'testing ... [ 67%] sphinx\r' in output + assert 'testing ... [100%] world\r\n' in output assert yields == ['hello', 'sphinx', 'world'] + +@pytest.mark.sphinx('dummy') +def test_status_iterator_verbosity_1(app, status, warning): + logging.setup(app, status, warning) + # test for status_iterator (verbosity=1) status.seek(0) status.truncate(0) @@ -53,7 +60,7 @@ def test_status_iterator(app, status, warning): length=3, verbosity=1)) output = strip_escseq(status.getvalue()) assert 'testing ... [ 33%] hello\n' in output - assert 'testing ... [ 66%] sphinx\n' in output + assert 'testing ... [ 67%] sphinx\n' in output assert 'testing ... [100%] world\n\n' in output assert yields == ['hello', 'sphinx', 'world']