From 7165a4f1e474d68e20c8ec812ca59eb1a38e1b03 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sat, 27 May 2017 16:47:31 +0200 Subject: [PATCH 1/4] Fix #3788: Docutils emits warnings for unsupported languages This monkey-patches docutils.languages.get_language() to suppress Docutils emitted warning when the document settings use a language_code for which Docutils has no ready-made localisation. The language_code is needed for functioning of the smartquotes transform. --- CHANGES | 1 + sphinx/application.py | 10 ++++++++++ sphinx/environment/__init__.py | 16 ++++++++++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index d85606bcc..b8dd5169a 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,7 @@ Bugs fixed * #3796: env.resolve_references() crashes when non-document node given * #3803: Sphinx crashes with invalid PO files * #3791: PDF "continued on next page" for long tables isn't internationalized +* #3788: smartquotes emits warnings for unsupported languages Testing -------- diff --git a/sphinx/application.py b/sphinx/application.py index 075f828fb..ba5aa2ca2 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -22,7 +22,9 @@ from collections import deque from six import iteritems 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 @@ -106,6 +108,14 @@ 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/environment/__init__.py b/sphinx/environment/__init__.py index 8aefa64f9..dbade8d4e 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -25,7 +25,7 @@ from six.moves import cPickle as pickle from docutils.io import NullOutput from docutils.core import Publisher -from docutils.utils import Reporter, get_source_line +from docutils.utils import Reporter, get_source_line, normalize_language_tag from docutils.utils.smartquotes import smartchars from docutils.parsers.rst import roles from docutils.parsers.rst.languages import en as english @@ -672,18 +672,22 @@ class BuildEnvironment(object): self.settings['trim_footnote_reference_space'] = \ self.config.trim_footnote_reference_space self.settings['gettext_compact'] = self.config.gettext_compact - language = (self.config.language or 'en').replace('_', '-') + + language = self.config.language or 'en' self.settings['language_code'] = language + self.settings['smart_quotes'] = True if self.config.html_use_smartypants is not None: warnings.warn("html_use_smartypants option is deprecated. Smart " "quotes are on by default; if you want to disable " "or customize them, use the smart_quotes option in " "docutils.conf.", RemovedInSphinx17Warning) - if language in smartchars.quotes: - self.settings['smart_quotes'] = self.config.html_use_smartypants - elif language in smartchars.quotes: # We enable smartypants by default - self.settings['smart_quotes'] = True + self.settings['smart_quotes'] = self.config.html_use_smartypants + for tag in normalize_language_tag(language): + if tag in smartchars.quotes: + break + else: + self.settings['smart_quotes'] = False docutilsconf = path.join(self.srcdir, 'docutils.conf') # read docutils.conf from source dir, not from current dir From 2817623500aa312f293a3ed8072058d79d46e8f4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 28 May 2017 10:05:41 +0900 Subject: [PATCH 2/4] Skip testing for websupport if sqlalchemy not installed --- tests/test_websupport.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_websupport.py b/tests/test_websupport.py index 93ed637be..51cb2b287 100644 --- a/tests/test_websupport.py +++ b/tests/test_websupport.py @@ -12,6 +12,7 @@ from sphinx.websupport import WebSupport try: sqlalchemy_missing = False + import sqlalchemy # NOQA except ImportError: sqlalchemy_missing = True From b396e6ac5c92ad154bd1d4d08e3904504da992e7 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 28 May 2017 10:10:29 +0900 Subject: [PATCH 3/4] Refactor patching docutils --- sphinx/application.py | 9 --------- sphinx/cmdline.py | 4 ++-- sphinx/setup_command.py | 4 ++-- sphinx/util/docutils.py | 27 ++++++++++++++++++++++++++- 4 files changed, 30 insertions(+), 14 deletions(-) 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 From ada4f6e19ada878a970c2cc9552dd831533f216b Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 28 May 2017 10:38:41 +0900 Subject: [PATCH 4/4] Fix flake8 violation --- sphinx/application.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sphinx/application.py b/sphinx/application.py index 9e4831e1b..075f828fb 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -22,7 +22,6 @@ from collections import deque from six import iteritems from six.moves import cStringIO -import docutils from docutils import nodes from docutils.parsers.rst import directives, roles