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