diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 281737755..c8cd44e55 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -339,7 +339,7 @@ class Builder: updated_docnames = set(self.read()) doccount = len(updated_docnames) - logger.info(bold(__('looking for now-outdated files... ')), nonl=1) + logger.info(bold(__('looking for now-outdated files... ')), nonl=True) for docname in self.env.check_dependents(self.app, updated_docnames): updated_docnames.add(docname) outdated = len(updated_docnames) - doccount diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index 38b743dea..aace9bb49 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -236,7 +236,7 @@ class MessageCatalogBuilder(I18nBuilder): # type: () -> None files = list(self._collect_templates()) files.sort() - logger.info(bold(__('building [%s]: ') % self.name), nonl=1) + logger.info(bold(__('building [%s]: ') % self.name), nonl=True) logger.info(__('targets for %d template files'), len(files)) extract_translations = self.templates.environment.extract_translations diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index b12929e8e..87b3ccac8 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -692,7 +692,7 @@ class StandaloneHTMLBuilder(Builder): def gen_indices(self): # type: () -> None - logger.info(bold(__('generating indices...')), nonl=1) + logger.info(bold(__('generating indices...')), nonl=True) # the global general index if self.use_index: @@ -710,21 +710,21 @@ class StandaloneHTMLBuilder(Builder): for pagename, context, template in pagelist: self.handle_page(pagename, context, template) - logger.info(bold(__('writing additional pages...')), nonl=1) + logger.info(bold(__('writing additional pages...')), nonl=True) # additional pages from conf.py for pagename, template in self.config.html_additional_pages.items(): - logger.info(' ' + pagename, nonl=1) + logger.info(' ' + pagename, nonl=True) self.handle_page(pagename, {}, template) # the search page if self.search: - logger.info(' search', nonl=1) + logger.info(' search', nonl=True) self.handle_page('search', {}, 'search.html') # the opensearch xml file if self.config.html_use_opensearch and self.search: - logger.info(' opensearch', nonl=1) + logger.info(' opensearch', nonl=True) fn = path.join(self.outdir, '_static', 'opensearch.xml') self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn) @@ -745,7 +745,7 @@ class StandaloneHTMLBuilder(Builder): 'genindexcounts': indexcounts, 'split_index': self.config.html_split_index, } - logger.info(' genindex', nonl=1) + logger.info(' genindex', nonl=True) if self.config.html_split_index: self.handle_page('genindex', genindexcontext, @@ -768,7 +768,7 @@ class StandaloneHTMLBuilder(Builder): 'content': content, 'collapse_index': collapse, } - logger.info(' ' + indexname, nonl=1) + logger.info(' ' + indexname, nonl=True) self.handle_page(indexname, indexcontext, 'domainindex.html') def copy_image_files(self): diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index 43aea1aa2..6637afccb 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -250,7 +250,7 @@ class LaTeXBuilder(Builder): toctree_only = entry[5] destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname), encoding='utf-8', overwrite_if_changed=True) - logger.info(__("processing %s..."), targetname, nonl=1) + logger.info(__("processing %s..."), targetname, nonl=True) toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree) if toctrees: if toctrees[0].get('maxdepth') > 0: @@ -267,7 +267,7 @@ class LaTeXBuilder(Builder): self.post_process_images(doctree) self.update_doc_context(title, author) - logger.info(__("writing... "), nonl=1) + logger.info(__("writing... "), nonl=True) docsettings.author = author docsettings.title = title docsettings.contentsname = self.get_contentsname(docname) @@ -298,7 +298,7 @@ class LaTeXBuilder(Builder): # type: (str, bool, List[str]) -> nodes.document from docutils import nodes # NOQA self.docnames = set([indexfile] + appendices) - logger.info(darkgreen(indexfile) + " ", nonl=1) + logger.info(darkgreen(indexfile) + " ", nonl=True) tree = self.env.get_doctree(indexfile) tree['docname'] = indexfile if toctree_only: @@ -388,9 +388,9 @@ class LaTeXBuilder(Builder): # copy additional files if self.config.latex_additional_files: - logger.info(bold(__('copying additional files...')), nonl=1) + logger.info(bold(__('copying additional files...')), nonl=True) for filename in self.config.latex_additional_files: - logger.info(' ' + filename, nonl=1) + logger.info(' ' + filename, nonl=True) copy_asset_file(path.join(self.confdir, filename), self.outdir) logger.info('') diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index d80370b32..95892dbaf 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -225,7 +225,7 @@ class CheckExternalLinksBuilder(Builder): if status == 'working' and info == 'old': return if lineno: - logger.info('(line %4d) ', lineno, nonl=1) + logger.info('(line %4d) ', lineno, nonl=True) if status == 'ignored': if info: logger.info(darkgray('-ignored- ') + uri + ': ' + info) diff --git a/sphinx/builders/singlehtml.py b/sphinx/builders/singlehtml.py index 2f5688bf1..e5c7159c0 100644 --- a/sphinx/builders/singlehtml.py +++ b/sphinx/builders/singlehtml.py @@ -179,15 +179,15 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder): def finish(self): # type: () -> None # no indices or search pages are supported - logger.info(bold(__('writing additional files...')), nonl=1) + logger.info(bold(__('writing additional files...')), nonl=True) # additional pages from conf.py for pagename, template in self.config.html_additional_pages.items(): - logger.info(' ' + pagename, nonl=1) + logger.info(' ' + pagename, nonl=True) self.handle_page(pagename, {}, template) if self.config.html_use_opensearch: - logger.info(' opensearch', nonl=1) + logger.info(' opensearch', nonl=True) fn = path.join(self.outdir, '_static', 'opensearch.xml') self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn) diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py index 32f5a8ee4..d01ef68b6 100644 --- a/sphinx/builders/texinfo.py +++ b/sphinx/builders/texinfo.py @@ -113,11 +113,11 @@ class TexinfoBuilder(Builder): destination = FileOutput( destination_path=path.join(self.outdir, targetname), encoding='utf-8') - logger.info(__("processing %s..."), targetname, nonl=1) + logger.info(__("processing %s..."), targetname, nonl=True) doctree = self.assemble_doctree( docname, toctree_only, appendices=(self.config.texinfo_appendices or [])) - logger.info(__("writing... "), nonl=1) + logger.info(__("writing... "), nonl=True) self.post_process_images(doctree) docwriter = TexinfoWriter(self) settings = OptionParser( @@ -139,7 +139,7 @@ class TexinfoBuilder(Builder): def assemble_doctree(self, indexfile, toctree_only, appendices): # type: (str, bool, List[str]) -> nodes.document self.docnames = set([indexfile] + appendices) - logger.info(darkgreen(indexfile) + " ", nonl=1) + logger.info(darkgreen(indexfile) + " ", nonl=True) tree = self.env.get_doctree(indexfile) tree['docname'] = indexfile if toctree_only: @@ -186,7 +186,7 @@ class TexinfoBuilder(Builder): logger.info(bold(__('copying Texinfo support files... ')), nonl=True) # copy Makefile fn = path.join(self.outdir, 'Makefile') - logger.info(fn, nonl=1) + logger.info(fn, nonl=True) try: copy_asset_file(os.path.join(template_dir, 'Makefile'), fn) except OSError as err: diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index 61738a349..2997dc216 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -153,9 +153,6 @@ def collect_pages(app): modnames = set(env._viewcode_modules) # type: ignore -# app.builder.info(' (%d module code pages)' % -# len(env._viewcode_modules), nonl=1) - for modname, entry in status_iterator( sorted(env._viewcode_modules.items()), # type: ignore __('highlighting module code... '), "blue", diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 18e9f8701..bfe99778a 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -48,7 +48,7 @@ from sphinx.util.matching import patfilter # noqa if False: # For type annotation - from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Pattern, Sequence, Set, Tuple, Union # NOQA + from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Pattern, Sequence, Set, Tuple, Type, Union # NOQA logger = logging.getLogger(__name__) @@ -676,6 +676,10 @@ def status_iterator(iterable, summary, color="darkgreen", length=0, verbosity=0, logger.info('') +class SkipProgressMessage(Exception): + pass + + class progress_message: def __init__(self, message): # type: (str) -> None @@ -686,8 +690,13 @@ class progress_message: logger.info(bold(self.message + '... '), nonl=True) def __exit__(self, exc_type, exc_value, traceback): - # type: (Any, Any, Any) -> bool - if exc_type: + # type: (Type[Exception], Exception, Any) -> bool + if isinstance(exc_value, SkipProgressMessage): + logger.info(__('skipped')) + if exc_value.args: + logger.info(*exc_value.args) + return True + elif exc_type: logger.info(__('failed')) else: logger.info(__('done')) diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py index 6759b897e..484616b03 100644 --- a/sphinx/util/nodes.py +++ b/sphinx/util/nodes.py @@ -402,7 +402,7 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc, traversed if includefile not in traversed: try: traversed.append(includefile) - logger.info(colorfunc(includefile) + " ", nonl=1) + logger.info(colorfunc(includefile) + " ", nonl=True) subtree = inline_all_toctrees(builder, docnameset, includefile, builder.env.get_doctree(includefile), colorfunc, traversed) diff --git a/tests/test_util.py b/tests/test_util.py index 0860ac6a4..0926096f4 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -18,8 +18,8 @@ import sphinx from sphinx.errors import PycodeError from sphinx.testing.util import strip_escseq from sphinx.util import ( - display_chunk, encode_uri, ensuredir, get_module_source, parselinenos, status_iterator, - xmlname_checker + SkipProgressMessage, display_chunk, encode_uri, ensuredir, get_module_source, + parselinenos, progress_message, status_iterator, xmlname_checker ) from sphinx.util import logging @@ -123,6 +123,44 @@ def test_parselinenos(): parselinenos('3-1', 10) +def test_progress_message(app, status, warning): + logging.setup(app, status, warning) + logger = logging.getLogger(__name__) + + # standard case + with progress_message('testing'): + logger.info('blah ', nonl=True) + + output = strip_escseq(status.getvalue()) + assert 'testing... blah done\n' in output + + # skipping case + with progress_message('testing'): + raise SkipProgressMessage('Reason: %s', 'error') + + output = strip_escseq(status.getvalue()) + assert 'testing... skipped\nReason: error\n' in output + + # error case + try: + with progress_message('testing'): + raise + except Exception: + pass + + output = strip_escseq(status.getvalue()) + assert 'testing... failed\n' in output + + # decorator + @progress_message('testing') + def func(): + logger.info('in func ', nonl=True) + + func() + output = strip_escseq(status.getvalue()) + assert 'testing... in func done\n' in output + + def test_xmlname_check(): checker = xmlname_checker() assert checker.match('id-pub')