mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '2229_suppress_warnings'
This commit is contained in:
commit
3939c4d684
2
CHANGES
2
CHANGES
@ -18,6 +18,8 @@ Features added
|
||||
* Define ``\crossref`` macro to redefine the style of references
|
||||
* #2301: Texts in the classic html theme should be hyphenated.
|
||||
* #2355: Define ``\termref`` macro to redefine the style of ``term`` roles.
|
||||
* Add :confval:`suppress_warnings` to suppress arbitrary warning message (experimental)
|
||||
* #2229: Fix no warning is given for unknown options
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
@ -212,6 +212,26 @@ General configuration
|
||||
|
||||
.. versionadded:: 0.5
|
||||
|
||||
.. confval:: suppress_warnings
|
||||
|
||||
A list of warning types to suppress arbitrary warning messages.
|
||||
|
||||
Sphinx supports following warning types:
|
||||
|
||||
* ref.term
|
||||
* ref.ref
|
||||
* ref.numref
|
||||
* ref.keyword
|
||||
* ref.option
|
||||
* ref.citation
|
||||
* ref.doc
|
||||
|
||||
You can choose from these types.
|
||||
|
||||
Now, this option should be considered *experimental*.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
.. confval:: needs_sphinx
|
||||
|
||||
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
|
||||
|
@ -41,6 +41,7 @@ from sphinx.util import pycompat # noqa: imported for side-effects
|
||||
from sphinx.util import import_object
|
||||
from sphinx.util.tags import Tags
|
||||
from sphinx.util.osutil import ENOENT
|
||||
from sphinx.util.logging import is_suppressed_warning
|
||||
from sphinx.util.console import bold, lightgray, darkgray, darkgreen, \
|
||||
term_width_line
|
||||
|
||||
@ -318,7 +319,7 @@ class Sphinx(object):
|
||||
wfile.flush()
|
||||
self.messagelog.append(message)
|
||||
|
||||
def warn(self, message, location=None, prefix='WARNING: '):
|
||||
def warn(self, message, location=None, prefix='WARNING: ', type=None, subtype=None):
|
||||
"""Emit a warning.
|
||||
|
||||
If *location* is given, it should either be a tuple of (docname, lineno)
|
||||
@ -326,12 +327,17 @@ class Sphinx(object):
|
||||
|
||||
*prefix* usually should not be changed.
|
||||
|
||||
*type* and *subtype* are used to suppress warnings with :confval:`suppress_warnings`.
|
||||
|
||||
.. note::
|
||||
|
||||
For warnings emitted during parsing, you should use
|
||||
:meth:`.BuildEnvironment.warn` since that will collect all
|
||||
warnings during parsing for later output.
|
||||
"""
|
||||
if is_suppressed_warning(type, subtype, self.config.suppress_warnings):
|
||||
return
|
||||
|
||||
if isinstance(location, tuple):
|
||||
docname, lineno = location
|
||||
if docname:
|
||||
|
@ -260,12 +260,12 @@ class Builder(object):
|
||||
|
||||
# while reading, collect all warnings from docutils
|
||||
warnings = []
|
||||
self.env.set_warnfunc(lambda *args: warnings.append(args))
|
||||
self.env.set_warnfunc(lambda *args, **kwargs: warnings.append((args, kwargs)))
|
||||
updated_docnames = set(self.env.update(self.config, self.srcdir,
|
||||
self.doctreedir, self.app))
|
||||
self.env.set_warnfunc(self.warn)
|
||||
for warning in warnings:
|
||||
self.warn(*warning)
|
||||
for warning, kwargs in warnings:
|
||||
self.warn(*warning, **kwargs)
|
||||
|
||||
doccount = len(updated_docnames)
|
||||
self.info(bold('looking for now-outdated files... '), nonl=1)
|
||||
@ -350,7 +350,7 @@ class Builder(object):
|
||||
self.info('done')
|
||||
|
||||
warnings = []
|
||||
self.env.set_warnfunc(lambda *args: warnings.append(args))
|
||||
self.env.set_warnfunc(lambda *args, **kwargs: warnings.append((args, kwargs)))
|
||||
if self.parallel_ok:
|
||||
# number of subprocesses is parallel-1 because the main process
|
||||
# is busy loading doctrees and doing write_doc_serialized()
|
||||
@ -366,13 +366,16 @@ class Builder(object):
|
||||
doctree = self.env.get_and_resolve_doctree(docname, self)
|
||||
self.write_doc_serialized(docname, doctree)
|
||||
self.write_doc(docname, doctree)
|
||||
for warning in warnings:
|
||||
self.warn(*warning)
|
||||
for warning, kwargs in warnings:
|
||||
self.warn(*warning, **kwargs)
|
||||
|
||||
def _write_parallel(self, docnames, warnings, nproc):
|
||||
def write_process(docs):
|
||||
local_warnings = []
|
||||
self.env.set_warnfunc(lambda *args: local_warnings.append(args))
|
||||
|
||||
def warnfunc(*args, **kwargs):
|
||||
local_warnings.append((args, kwargs))
|
||||
self.env.set_warnfunc(warnfunc)
|
||||
for docname, doctree in docs:
|
||||
self.write_doc(docname, doctree)
|
||||
return local_warnings
|
||||
@ -402,8 +405,8 @@ class Builder(object):
|
||||
self.info(bold('waiting for workers...'))
|
||||
tasks.join()
|
||||
|
||||
for warning in warnings:
|
||||
self.warn(*warning)
|
||||
for warning, kwargs in warnings:
|
||||
self.warn(*warning, **kwargs)
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
"""A place where you can add logic before :meth:`write_doc` is run"""
|
||||
|
@ -76,6 +76,7 @@ class Config(object):
|
||||
templates_path = ([], 'html'),
|
||||
template_bridge = (None, 'html', string_classes),
|
||||
keep_warnings = (False, 'env'),
|
||||
suppress_warnings = ([], 'env'),
|
||||
modindex_common_prefix = ([], 'html'),
|
||||
rst_epilog = (None, 'env', string_classes),
|
||||
rst_prolog = (None, 'env', string_classes),
|
||||
|
@ -447,7 +447,7 @@ class StandardDomain(Domain):
|
||||
'productionlist': ProductionList,
|
||||
}
|
||||
roles = {
|
||||
'option': OptionXRefRole(),
|
||||
'option': OptionXRefRole(warn_dangling=True),
|
||||
'envvar': EnvVarXRefRole(),
|
||||
# links to tokens in grammar productions
|
||||
'token': XRefRole(),
|
||||
@ -485,6 +485,7 @@ class StandardDomain(Domain):
|
||||
'the label must precede a section header)',
|
||||
'numref': 'undefined label: %(target)s',
|
||||
'keyword': 'unknown keyword: %(target)s',
|
||||
'option': 'unknown option: %(target)s',
|
||||
}
|
||||
|
||||
enumerable_nodes = { # node_class -> (figtype, title_getter)
|
||||
|
@ -242,7 +242,7 @@ class BuildEnvironment:
|
||||
self.versioning_condition = condition
|
||||
self.versioning_compare = compare
|
||||
|
||||
def warn(self, docname, msg, lineno=None):
|
||||
def warn(self, docname, msg, lineno=None, **kwargs):
|
||||
"""Emit a warning.
|
||||
|
||||
This differs from using ``app.warn()`` in that the warning may not
|
||||
@ -250,11 +250,11 @@ class BuildEnvironment:
|
||||
the update of the environment.
|
||||
"""
|
||||
# strange argument order is due to backwards compatibility
|
||||
self._warnfunc(msg, (docname, lineno))
|
||||
self._warnfunc(msg, (docname, lineno), **kwargs)
|
||||
|
||||
def warn_node(self, msg, node):
|
||||
def warn_node(self, msg, node, **kwargs):
|
||||
"""Like :meth:`warn`, but with source information taken from *node*."""
|
||||
self._warnfunc(msg, '%s:%s' % get_source_line(node))
|
||||
self._warnfunc(msg, '%s:%s' % get_source_line(node), **kwargs)
|
||||
|
||||
def clear_doc(self, docname):
|
||||
"""Remove all traces of a source file in the inventory."""
|
||||
@ -576,7 +576,7 @@ class BuildEnvironment:
|
||||
def read_process(docs):
|
||||
self.app = app
|
||||
self.warnings = []
|
||||
self.set_warnfunc(lambda *args: self.warnings.append(args))
|
||||
self.set_warnfunc(lambda *args, **kwargs: self.warnings.append((args, kwargs)))
|
||||
for docname in docs:
|
||||
self.read_doc(docname, app)
|
||||
# allow pickling self to send it back
|
||||
@ -603,8 +603,8 @@ class BuildEnvironment:
|
||||
app.info(bold('waiting for workers...'))
|
||||
tasks.join()
|
||||
|
||||
for warning in warnings:
|
||||
self._warnfunc(*warning)
|
||||
for warning, kwargs in warnings:
|
||||
self._warnfunc(*warning, **kwargs)
|
||||
|
||||
def check_dependents(self, already):
|
||||
to_rewrite = self.assign_section_numbers() + self.assign_figure_numbers()
|
||||
@ -1540,7 +1540,7 @@ class BuildEnvironment:
|
||||
(node['refdomain'], typ)
|
||||
else:
|
||||
msg = '%r reference target not found: %%(target)s' % typ
|
||||
self.warn_node(msg % {'target': target}, node)
|
||||
self.warn_node(msg % {'target': target}, node, type='ref', subtype=typ)
|
||||
|
||||
def _resolve_doc_reference(self, builder, node, contnode):
|
||||
# directly reference to document by source name;
|
||||
|
29
sphinx/util/logging.py
Normal file
29
sphinx/util/logging.py
Normal file
@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinx.util.logging
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Logging utility functions for Sphinx.
|
||||
|
||||
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
||||
def is_suppressed_warning(type, subtype, suppress_warnings):
|
||||
"""Check the warning is suppressed or not."""
|
||||
if type is None:
|
||||
return False
|
||||
|
||||
for warning_type in suppress_warnings:
|
||||
if '.' in warning_type:
|
||||
target, subtarget = warning_type.split('.', 1)
|
||||
else:
|
||||
target, subtarget = warning_type, None
|
||||
|
||||
if target == type:
|
||||
if (subtype is None or subtarget is None or
|
||||
subtarget == subtype or subtarget == '*'):
|
||||
return True
|
||||
|
||||
return False
|
@ -40,6 +40,7 @@ HTML_WARNINGS = ENV_WARNINGS + """\
|
||||
%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
|
||||
%(root)s/markup.txt:271: WARNING: Could not lex literal_block as "c". Highlighting skipped.
|
||||
%(root)s/footnote.txt:60: WARNING: citation not found: missing
|
||||
%(root)s/markup.txt:160: WARNING: unknown option: &option
|
||||
"""
|
||||
|
||||
if PY3:
|
||||
|
@ -24,6 +24,7 @@ from test_build_html import ENV_WARNINGS
|
||||
|
||||
|
||||
LATEX_WARNINGS = ENV_WARNINGS + """\
|
||||
%(root)s/markup.txt:160: WARNING: unknown option: &option
|
||||
%(root)s/footnote.txt:60: WARNING: citation not found: missing
|
||||
%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
|
||||
%(root)s/markup.txt:271: WARNING: Could not lex literal_block as "c". Highlighting skipped.
|
||||
|
@ -23,6 +23,7 @@ from test_build_html import ENV_WARNINGS
|
||||
|
||||
|
||||
TEXINFO_WARNINGS = ENV_WARNINGS + """\
|
||||
%(root)s/markup.txt:160: WARNING: unknown option: &option
|
||||
%(root)s/footnote.txt:60: WARNING: citation not found: missing
|
||||
%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
|
||||
%(root)s/images.txt:29: WARNING: no matching candidate for image URI u'svgimg.\\*'
|
||||
|
26
tests/test_util_logging.py
Normal file
26
tests/test_util_logging.py
Normal file
@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_util_logging
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test logging util.
|
||||
|
||||
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
from sphinx.util.logging import is_suppressed_warning
|
||||
|
||||
|
||||
def test_is_suppressed_warning():
|
||||
suppress_warnings = ["ref", "files.*", "rest.duplicated_labels"]
|
||||
|
||||
assert is_suppressed_warning(None, None, suppress_warnings) is False
|
||||
assert is_suppressed_warning("ref", None, suppress_warnings) is True
|
||||
assert is_suppressed_warning("ref", "numref", suppress_warnings) is True
|
||||
assert is_suppressed_warning("ref", "option", suppress_warnings) is True
|
||||
assert is_suppressed_warning("files", "image", suppress_warnings) is True
|
||||
assert is_suppressed_warning("files", "stylesheet", suppress_warnings) is True
|
||||
assert is_suppressed_warning("rest", "syntax", suppress_warnings) is False
|
||||
assert is_suppressed_warning("rest", "duplicated_labels", suppress_warnings) is True
|
Loading…
Reference in New Issue
Block a user