Merge branch 'stable'

This commit is contained in:
Takeshi KOMIYA 2017-07-29 16:01:47 +09:00
commit abaf1cbb6b
9 changed files with 101 additions and 9 deletions

View File

@ -79,9 +79,15 @@ Deprecated
Features added Features added
-------------- --------------
* #3926: Add ``autodoc_warningiserror`` to suppress the behavior of ``-W``
option during importing target modules on autodoc
Bugs fixed Bugs fixed
---------- ----------
* #3924: docname lost after dynamically parsing RST in extension
* #3946: Typo in sphinx.sty (this was a bug with no effect in default context)
Testing Testing
-------- --------

View File

@ -386,6 +386,13 @@ There are also new config values that you can set:
This config value only requires to declare the top-level modules that This config value only requires to declare the top-level modules that
should be mocked. should be mocked.
.. confval:: autodoc_warningiserror
This value controls the behavior of :option:`sphinx-build -W` during
importing modules.
If ``False`` is given, autodoc forcely suppresses the error if the imported
module emits warnings. By default, ``True``.
Docstring preprocessing Docstring preprocessing
----------------------- -----------------------

View File

@ -454,6 +454,28 @@ The application object also provides support for emitting leveled messages.
.. automethod:: Sphinx.debug2 .. automethod:: Sphinx.debug2
Sphinx runtime information
--------------------------
The application object also provides runtime information as attributes.
.. attribute:: srcdir
Source directory.
.. attribute:: confdir
Directory containing ``conf.py``.
.. attribute:: doctreedir
Directory for storing pickled doctrees.
.. attribute:: outdir
Directory for storing built document.
.. _events: .. _events:
Sphinx core events Sphinx core events

View File

@ -19,10 +19,6 @@ Build environment API
Source directory. Source directory.
.. attribute:: confdir
Directory containing ``conf.py``.
.. attribute:: doctreedir .. attribute:: doctreedir
Directory for storing pickled doctrees. Directory for storing pickled doctrees.

View File

@ -18,6 +18,7 @@ import codecs
import fnmatch import fnmatch
import warnings import warnings
from os import path from os import path
from copy import copy
from collections import defaultdict from collections import defaultdict
from six import BytesIO, itervalues, class_types, next from six import BytesIO, itervalues, class_types, next
@ -921,6 +922,7 @@ class BuildEnvironment(object):
"""Apply all post-transforms.""" """Apply all post-transforms."""
try: try:
# set env.docname during applying post-transforms # set env.docname during applying post-transforms
backup = copy(self.temp_data)
self.temp_data['docname'] = docname self.temp_data['docname'] = docname
transformer = SphinxTransformer(doctree) transformer = SphinxTransformer(doctree)
@ -928,7 +930,7 @@ class BuildEnvironment(object):
transformer.add_transforms(self.app.post_transforms) transformer.add_transforms(self.app.post_transforms)
transformer.apply_transforms() transformer.apply_transforms()
finally: finally:
self.temp_data.clear() self.temp_data = backup
# allow custom references to be resolved # allow custom references to be resolved
self.app.emit('doctree-resolved', doctree, docname) self.app.emit('doctree-resolved', doctree, docname)

View File

@ -394,7 +394,8 @@ class Documenter(object):
logger.debug('[autodoc] import %s', self.modname) logger.debug('[autodoc] import %s', self.modname)
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ImportWarning) warnings.filterwarnings("ignore", category=ImportWarning)
__import__(self.modname) with logging.skip_warningiserror(not self.env.config.autodoc_warningiserror):
__import__(self.modname)
parent = None parent = None
obj = self.module = sys.modules[self.modname] obj = self.module = sys.modules[self.modname]
logger.debug('[autodoc] => %r', obj) logger.debug('[autodoc] => %r', obj)
@ -1615,6 +1616,7 @@ def setup(app):
app.add_config_value('autodoc_default_flags', [], True) app.add_config_value('autodoc_default_flags', [], True)
app.add_config_value('autodoc_docstring_signature', True, True) app.add_config_value('autodoc_docstring_signature', True, True)
app.add_config_value('autodoc_mock_imports', [], True) app.add_config_value('autodoc_mock_imports', [], True)
app.add_config_value('autodoc_warningiserror', True, True)
app.add_event('autodoc-process-docstring') app.add_event('autodoc-process-docstring')
app.add_event('autodoc-process-signature') app.add_event('autodoc-process-signature')
app.add_event('autodoc-skip-member') app.add_event('autodoc-skip-member')

View File

@ -6,7 +6,7 @@
% %
\NeedsTeXFormat{LaTeX2e}[1995/12/01] \NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{sphinx}[2017/06/17 v1.6.3 LaTeX package (Sphinx markup)] \ProvidesPackage{sphinx}[2017/07/24 v1.6.4 LaTeX package (Sphinx markup)]
% provides \ltx@ifundefined % provides \ltx@ifundefined
% (many packages load ltxcmds: graphicx does for pdftex and lualatex but % (many packages load ltxcmds: graphicx does for pdftex and lualatex but
@ -1166,7 +1166,7 @@
% and there is consequently no corresponding package option % and there is consequently no corresponding package option
\definecolor{sphinxnoteBgColor}{rgb}{1,1,1} \definecolor{sphinxnoteBgColor}{rgb}{1,1,1}
\definecolor{sphinxhintBgColor}{rgb}{1,1,1} \definecolor{sphinxhintBgColor}{rgb}{1,1,1}
\definecolor{sphinimportantBgColor}{rgb}{1,1,1} \definecolor{sphinximportantBgColor}{rgb}{1,1,1}
\definecolor{sphinxtipBgColor}{rgb}{1,1,1} \definecolor{sphinxtipBgColor}{rgb}{1,1,1}
% Others get more distinction % Others get more distinction

View File

@ -249,6 +249,27 @@ def pending_logging():
memhandler.flushTo(logger) memhandler.flushTo(logger)
@contextmanager
def skip_warningiserror(skip=True):
# type: (bool) -> Generator
"""contextmanager to skip WarningIsErrorFilter for a while."""
logger = logging.getLogger()
if skip is False:
yield
else:
try:
disabler = DisableWarningIsErrorFilter()
for handler in logger.handlers:
# use internal method; filters.insert() directly to install disabler
# before WarningIsErrorFilter
handler.filters.insert(0, disabler)
yield
finally:
for handler in logger.handlers:
handler.removeFilter(disabler)
class LogCollector(object): class LogCollector(object):
def __init__(self): def __init__(self):
# type: () -> None # type: () -> None
@ -330,7 +351,10 @@ class WarningIsErrorFilter(logging.Filter):
def filter(self, record): def filter(self, record):
# type: (logging.LogRecord) -> bool # type: (logging.LogRecord) -> bool
if self.app.warningiserror: if getattr(record, 'skip_warningsiserror', False):
# disabled by DisableWarningIsErrorFilter
return True
elif self.app.warningiserror:
location = getattr(record, 'location', '') location = getattr(record, 'location', '')
if location: if location:
raise SphinxWarning(location + ":" + record.msg % record.args) raise SphinxWarning(location + ":" + record.msg % record.args)
@ -340,6 +364,15 @@ class WarningIsErrorFilter(logging.Filter):
return True return True
class DisableWarningIsErrorFilter(logging.Filter):
"""Disable WarningIsErrorFilter if this filter installed."""
def filter(self, record):
# type: (logging.LogRecord) -> bool
record.skip_warningsiserror = True # type: ignore
return True
class WarningLogRecordTranslator(logging.Filter): class WarningLogRecordTranslator(logging.Filter):
"""Converts a log record to one Sphinx expects """Converts a log record to one Sphinx expects

View File

@ -272,3 +272,27 @@ def test_output_with_unencodable_char(app, status, warning):
status.seek(0) status.seek(0)
logger.info(u"unicode \u206d...") logger.info(u"unicode \u206d...")
assert status.getvalue() == "unicode ?...\n" assert status.getvalue() == "unicode ?...\n"
def test_skip_warningiserror(app, status, warning):
logging.setup(app, status, warning)
logger = logging.getLogger(__name__)
app.warningiserror = True
with logging.skip_warningiserror():
logger.warning('message')
# if False, warning raises SphinxWarning exception
with pytest.raises(SphinxWarning):
with logging.skip_warningiserror(False):
logger.warning('message')
# It also works during pending_warnings.
with logging.pending_warnings():
with logging.skip_warningiserror():
logger.warning('message')
with pytest.raises(SphinxWarning):
with logging.pending_warnings():
with logging.skip_warningiserror(False):
logger.warning('message')