mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Let docutils know the location of `docutils.conf
` for Sphinx
This commit is contained in:
parent
d80801deeb
commit
81946e423a
2
CHANGES
2
CHANGES
@ -23,6 +23,8 @@ Incompatible changes
|
||||
:py:meth:`.Sphinx.add_transform()`
|
||||
* #4827: All ``substitution_definition`` nodes are removed from doctree on
|
||||
reading phase
|
||||
* ``docutils.conf`` on ``$HOME`` and ``/etc`` directories are ignored. Only
|
||||
``docutils.conf`` on confdir is refered.
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
@ -293,7 +293,8 @@ def build_main(argv=sys.argv[1:]): # type: ignore
|
||||
|
||||
app = None
|
||||
try:
|
||||
with patch_docutils(), docutils_namespace():
|
||||
confdir = args.confdir or args.sourcedir
|
||||
with patch_docutils(confdir), docutils_namespace():
|
||||
app = Sphinx(args.sourcedir, args.confdir, args.outputdir,
|
||||
args.doctreedir, args.builder, confoverrides, status,
|
||||
warning, args.freshenv, args.warningiserror,
|
||||
|
@ -19,7 +19,6 @@ from collections import defaultdict
|
||||
from copy import copy
|
||||
from os import path
|
||||
|
||||
from docutils.frontend import OptionParser
|
||||
from docutils.utils import Reporter, get_source_line
|
||||
from six import BytesIO, class_types, next
|
||||
from six.moves import cPickle as pickle
|
||||
@ -561,9 +560,8 @@ class BuildEnvironment(object):
|
||||
"""Parse a file and add/update inventory entries for the doctree."""
|
||||
self.prepare_settings(docname)
|
||||
|
||||
docutilsconf = path.join(self.srcdir, 'docutils.conf')
|
||||
# read docutils.conf from source dir, not from current dir
|
||||
OptionParser.standard_config_files[1] = docutilsconf
|
||||
# Add confdir/docutils.conf to dependencies list if exists
|
||||
docutilsconf = path.join(self.app.confdir, 'docutils.conf')
|
||||
if path.isfile(docutilsconf):
|
||||
self.note_dependency(docutilsconf)
|
||||
|
||||
|
@ -179,7 +179,8 @@ class BuildDoc(Command):
|
||||
app = None
|
||||
|
||||
try:
|
||||
with patch_docutils(), docutils_namespace():
|
||||
confdir = self.config_dir or self.source_dir
|
||||
with patch_docutils(confdir), docutils_namespace():
|
||||
app = Sphinx(self.source_dir, self.config_dir,
|
||||
builder_target_dir, self.doctree_dir,
|
||||
builder, confoverrides, status_stream,
|
||||
|
@ -10,16 +10,17 @@
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import re
|
||||
import types
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
from copy import copy
|
||||
from distutils.version import LooseVersion
|
||||
from os import path
|
||||
|
||||
import docutils
|
||||
from docutils import nodes
|
||||
from docutils.languages import get_language
|
||||
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
|
||||
from docutils.statemachine import StateMachine
|
||||
from docutils.utils import Reporter
|
||||
@ -34,7 +35,7 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Generator, Iterator, List, Set, Tuple # NOQA
|
||||
from typing import Any, Callable, Generator, List, Set, Tuple # NOQA
|
||||
from docutils.statemachine import State, ViewList # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
@ -47,7 +48,7 @@ additional_nodes = set() # type: Set[nodes.Node]
|
||||
|
||||
@contextmanager
|
||||
def docutils_namespace():
|
||||
# type: () -> Iterator[None]
|
||||
# type: () -> Generator[None, None, None]
|
||||
"""Create namespace for reST parsers."""
|
||||
try:
|
||||
_directives = copy(directives._directives)
|
||||
@ -94,29 +95,53 @@ def unregister_node(node):
|
||||
delattr(nodes.SparseNodeVisitor, 'depart_' + node.__name__)
|
||||
|
||||
|
||||
def patched_get_language(language_code, reporter=None):
|
||||
# type: (unicode, Reporter) -> Any
|
||||
"""A wrapper for docutils.languages.get_language().
|
||||
@contextmanager
|
||||
def patched_get_language():
|
||||
# type: () -> Generator[None, None, None]
|
||||
"""Patch docutils.languages.get_language() temporarily.
|
||||
|
||||
This ignores the second argument ``reporter`` to suppress warnings.
|
||||
refs: https://github.com/sphinx-doc/sphinx/issues/3788
|
||||
"""
|
||||
return get_language(language_code)
|
||||
from docutils.languages import get_language
|
||||
|
||||
def patched_get_language(language_code, reporter=None):
|
||||
# type: (unicode, Reporter) -> Any
|
||||
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
|
||||
|
||||
|
||||
@contextmanager
|
||||
def using_user_docutils_conf(confdir):
|
||||
# type: (unicode) -> Generator[None, None, None]
|
||||
"""Let docutils know the location of ``docutils.conf`` for Sphinx."""
|
||||
try:
|
||||
docutilsconfig = os.environ.get('DOCUTILSCONFIG', None)
|
||||
if confdir:
|
||||
os.environ['DOCUTILSCONFIG'] = path.join(path.abspath(confdir), 'docutils.conf') # type: ignore # NOQA
|
||||
|
||||
yield
|
||||
finally:
|
||||
if docutilsconfig is None:
|
||||
os.environ.pop('DOCUTILSCONFIG')
|
||||
else:
|
||||
os.environ['DOCUTILSCONFIG'] = docutilsconfig
|
||||
|
||||
|
||||
@contextmanager
|
||||
def patch_docutils(confdir=None):
|
||||
# type: (unicode) -> Generator[None, None, None]
|
||||
"""Patch to docutils temporarily."""
|
||||
with patched_get_language(), using_user_docutils_conf(confdir):
|
||||
yield
|
||||
|
||||
|
||||
class ElementLookupError(Exception):
|
||||
pass
|
||||
|
||||
@ -257,7 +282,7 @@ def directive_helper(obj, has_content=None, argument_spec=None, **option_spec):
|
||||
|
||||
@contextmanager
|
||||
def switch_source_input(state, content):
|
||||
# type: (State, ViewList) -> Generator
|
||||
# type: (State, ViewList) -> Generator[None, None, None]
|
||||
"""Switch current source input of state temporarily."""
|
||||
try:
|
||||
# remember the original ``get_source_and_line()`` method
|
||||
|
@ -15,6 +15,7 @@ import sys
|
||||
import pytest
|
||||
|
||||
from sphinx.testing.path import path
|
||||
from sphinx.util.docutils import patch_docutils
|
||||
|
||||
|
||||
def regex_count(expr, result):
|
||||
@ -23,7 +24,9 @@ def regex_count(expr, result):
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='docutilsconf', freshenv=True, docutilsconf='')
|
||||
def test_html_with_default_docutilsconf(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
|
||||
assert regex_count(r'<th class="field-name">', result) == 1
|
||||
@ -39,7 +42,9 @@ def test_html_with_default_docutilsconf(app, status, warning):
|
||||
'\n')
|
||||
)
|
||||
def test_html_with_docutilsconf(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
|
||||
assert regex_count(r'<th class="field-name">', result) == 0
|
||||
@ -50,25 +55,29 @@ def test_html_with_docutilsconf(app, status, warning):
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='docutilsconf')
|
||||
def test_html(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='docutilsconf')
|
||||
def test_latex(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@pytest.mark.sphinx('man', testroot='docutilsconf')
|
||||
def test_man(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@pytest.mark.sphinx('texinfo', testroot='docutilsconf')
|
||||
def test_texinfo(app, status, warning):
|
||||
app.builder.build(['contents'])
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='docutilsconf',
|
||||
@ -87,4 +96,5 @@ def test_docutils_source_link_with_nonascii_file(app, status, warning):
|
||||
'nonascii filename not supported on this filesystem encoding: '
|
||||
'%s', FILESYSTEMENCODING)
|
||||
|
||||
app.builder.build_all()
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build_all()
|
||||
|
Loading…
Reference in New Issue
Block a user