diff --git a/sphinx/application.py b/sphinx/application.py index ba5aa2ca2..9e4831e1b 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -24,7 +24,6 @@ from six.moves import cStringIO import docutils from docutils import nodes -from docutils.languages import get_language as docutils_get_language from docutils.parsers.rst import directives, roles import sphinx @@ -108,14 +107,6 @@ ENV_PICKLE_FILENAME = 'environment.pickle' logger = logging.getLogger(__name__) -# monkey patch docutils get_language -def patched_docutils_get_language(language_code, reporter=None): # NOQA - return docutils_get_language(language_code) - - -docutils.languages.get_language = patched_docutils_get_language - - class Sphinx(object): def __init__(self, srcdir, confdir, outdir, doctreedir, buildername, diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index 650f88b44..7b6cf0860 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -24,7 +24,7 @@ from sphinx.errors import SphinxError from sphinx.application import Sphinx from sphinx.util import Tee, format_exception_cut_frames, save_traceback from sphinx.util.console import red, nocolor, color_terminal # type: ignore -from sphinx.util.docutils import docutils_namespace +from sphinx.util.docutils import docutils_namespace, patch_docutils from sphinx.util.osutil import abspath, fs_encoding from sphinx.util.pycompat import terminal_safe @@ -299,7 +299,7 @@ def main(argv): app = None try: - with docutils_namespace(): + with patch_docutils(), docutils_namespace(): app = Sphinx(srcdir, confdir, outdir, doctreedir, opts.builder, confoverrides, status, warning, opts.freshenv, opts.warningiserror, opts.tags, opts.verbosity, opts.jobs) diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py index 8e773923f..d219a14d9 100644 --- a/sphinx/setup_command.py +++ b/sphinx/setup_command.py @@ -23,7 +23,7 @@ from distutils.errors import DistutilsOptionError, DistutilsExecError # type: i from sphinx.application import Sphinx from sphinx.cmdline import handle_exception from sphinx.util.console import nocolor, color_terminal -from sphinx.util.docutils import docutils_namespace +from sphinx.util.docutils import docutils_namespace, patch_docutils from sphinx.util.osutil import abspath if False: @@ -183,7 +183,7 @@ class BuildDoc(Command): app = None try: - with docutils_namespace(): + with patch_docutils(), docutils_namespace(): app = Sphinx(self.source_dir, self.config_dir, builder_target_dir, self.doctree_dir, builder, confoverrides, status_stream, diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 8bb0b3661..1fe72af58 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -13,9 +13,11 @@ from __future__ import absolute_import import re import types from copy import copy +from distutils.version import LooseVersion from contextlib import contextmanager import docutils +from docutils.languages import get_language from docutils.utils import Reporter from docutils.parsers.rst import directives, roles, convert_directive_function @@ -34,7 +36,7 @@ if False: from sphinx.environment import BuildEnvironment # NOQA -__version_info__ = tuple(map(int, docutils.__version__.split('.'))) +__version_info__ = tuple(LooseVersion(docutils.__version__).version) @contextmanager @@ -51,6 +53,29 @@ def docutils_namespace(): roles._roles = _roles +def patched_get_language(language_code, reporter=None): + # type: (unicode, Reporter) -> Any + """A wrapper for docutils.languages.get_language(). + + This ignores the second argument ``reporter`` to suppress warnings. + refs: https://github.com/sphinx-doc/sphinx/issues/3788 + """ + return get_language(language_code) + + +@contextmanager +def patch_docutils(): + # type: () -> Iterator[None] + """Patch to docutils temporarily.""" + try: + docutils.languages.get_language = patched_get_language + + yield + finally: + # restore original implementations + docutils.languages.get_language = get_language + + class ElementLookupError(Exception): pass