mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #6165: autodoc: `tab_width
` setting of docutils has been ignored
This commit is contained in:
parent
de0c44196e
commit
1ea23e14df
1
CHANGES
1
CHANGES
@ -91,6 +91,7 @@ Bugs fixed
|
||||
* #6213: ifconfig: contents after headings are not shown
|
||||
* commented term in glossary directive is wrongly recognized
|
||||
* #6299: rst domain: rst:directive directive generates waste space
|
||||
* #6165: autodoc: ``tab_width`` setting of docutils has been ignored
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
@ -442,7 +442,8 @@ class Documenter:
|
||||
docstring = getdoc(self.object, self.get_attr,
|
||||
self.env.config.autodoc_inherit_docstrings)
|
||||
if docstring:
|
||||
return [prepare_docstring(docstring, ignore)]
|
||||
tab_width = self.directive.state.document.settings.tab_width
|
||||
return [prepare_docstring(docstring, ignore, tab_width)]
|
||||
return []
|
||||
|
||||
def process_doc(self, docstrings):
|
||||
@ -936,7 +937,9 @@ class DocstringSignatureMixin:
|
||||
if base not in valid_names:
|
||||
continue
|
||||
# re-prepare docstring to ignore more leading indentation
|
||||
self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[1:]))
|
||||
tab_width = self.directive.state.document.settings.tab_width # type: ignore
|
||||
self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[1:]),
|
||||
tabsize=tab_width)
|
||||
result = args, retann
|
||||
# don't look any further
|
||||
break
|
||||
@ -1179,7 +1182,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
docstrings = [initdocstring]
|
||||
else:
|
||||
docstrings.append(initdocstring)
|
||||
return [prepare_docstring(docstring, ignore) for docstring in docstrings]
|
||||
|
||||
tab_width = self.directive.state.document.settings.tab_width
|
||||
return [prepare_docstring(docstring, ignore, tab_width) for docstring in docstrings]
|
||||
|
||||
def add_content(self, more_content, no_docstring=False):
|
||||
# type: (Any, bool) -> None
|
||||
|
@ -6,10 +6,14 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst.states import Struct
|
||||
from docutils.statemachine import StringList
|
||||
from docutils.utils import assemble_option_dict
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.ext.autodoc import Options, get_documenters
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.docutils import SphinxDirective, switch_source_input
|
||||
@ -17,7 +21,7 @@ from sphinx.util.nodes import nested_parse_with_titles
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Callable, Dict, List, Set, Type # NOQA
|
||||
from typing import Any, Callable, Dict, List, Set, Type # NOQA
|
||||
from docutils.parsers.rst.state import RSTState # NOQA
|
||||
from docutils.utils import Reporter # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
@ -50,8 +54,8 @@ class DummyOptionSpec(dict):
|
||||
class DocumenterBridge:
|
||||
"""A parameters container for Documenters."""
|
||||
|
||||
def __init__(self, env, reporter, options, lineno):
|
||||
# type: (BuildEnvironment, Reporter, Options, int) -> None
|
||||
def __init__(self, env, reporter, options, lineno, state=None):
|
||||
# type: (BuildEnvironment, Reporter, Options, int, Any) -> None
|
||||
self.env = env
|
||||
self.reporter = reporter
|
||||
self.genopt = options
|
||||
@ -59,6 +63,16 @@ class DocumenterBridge:
|
||||
self.filename_set = set() # type: Set[str]
|
||||
self.result = StringList()
|
||||
|
||||
if state:
|
||||
self.state = state
|
||||
else:
|
||||
# create fake object for self.state.document.settings.tab_width
|
||||
warnings.warn('DocumenterBridge requires a state object on instantiation.',
|
||||
RemovedInSphinx40Warning)
|
||||
settings = Struct(tab_width=8)
|
||||
document = Struct(settings=settings)
|
||||
self.state = Struct(document=document)
|
||||
|
||||
def warn(self, msg):
|
||||
# type: (str) -> None
|
||||
logger.warning(msg, location=(self.env.docname, self.lineno))
|
||||
@ -131,7 +145,7 @@ class AutodocDirective(SphinxDirective):
|
||||
return []
|
||||
|
||||
# generate the output
|
||||
params = DocumenterBridge(self.env, reporter, documenter_options, lineno)
|
||||
params = DocumenterBridge(self.env, reporter, documenter_options, lineno, self.state)
|
||||
documenter = doccls(params, self.arguments[0])
|
||||
documenter.generate(more_content=self.content)
|
||||
if not params.result:
|
||||
|
@ -175,7 +175,7 @@ _app = None # type: Sphinx
|
||||
class FakeDirective(DocumenterBridge):
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
super().__init__({}, None, Options(), 0) # type: ignore
|
||||
super().__init__({}, None, Options(), 0, None) # type: ignore
|
||||
|
||||
|
||||
def get_documenter(app, obj, parent):
|
||||
@ -236,7 +236,7 @@ class Autosummary(SphinxDirective):
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
self.bridge = DocumenterBridge(self.env, self.state.document.reporter,
|
||||
Options(), self.lineno)
|
||||
Options(), self.lineno, self.state)
|
||||
|
||||
names = [x.strip().split()[0] for x in self.content
|
||||
if x.strip() and re.search(r'^[~a-zA-Z_]', x.strip()[0])]
|
||||
|
@ -15,8 +15,8 @@ if False:
|
||||
from typing import List # NOQA
|
||||
|
||||
|
||||
def prepare_docstring(s, ignore=1):
|
||||
# type: (str, int) -> List[str]
|
||||
def prepare_docstring(s, ignore=1, tabsize=8):
|
||||
# type: (str, int, int) -> List[str]
|
||||
"""Convert a docstring into lines of parseable reST. Remove common leading
|
||||
indentation, where the indentation of a given number of lines (usually just
|
||||
one) is ignored.
|
||||
@ -25,7 +25,7 @@ def prepare_docstring(s, ignore=1):
|
||||
ViewList (used as argument of nested_parse().) An empty line is added to
|
||||
act as a separator between this docstring and following content.
|
||||
"""
|
||||
lines = s.expandtabs().splitlines()
|
||||
lines = s.expandtabs(tabsize).splitlines()
|
||||
# Find minimum indentation of any non-blank lines after ignored lines.
|
||||
margin = sys.maxsize
|
||||
for line in lines[ignore:]:
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
import platform
|
||||
import sys
|
||||
from unittest.mock import Mock
|
||||
from warnings import catch_warnings
|
||||
|
||||
import pytest
|
||||
@ -36,7 +37,9 @@ def do_autodoc(app, objtype, name, options=None):
|
||||
app.env.temp_data.setdefault('docname', 'index') # set dummy docname
|
||||
doccls = app.registry.documenters[objtype]
|
||||
docoptions = process_documenter_options(doccls, app.config, options)
|
||||
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1)
|
||||
state = Mock()
|
||||
state.document.settings.tab_width = 8
|
||||
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1, state)
|
||||
documenter = doccls(bridge, name)
|
||||
documenter.generate()
|
||||
|
||||
@ -95,7 +98,9 @@ def setup_test():
|
||||
genopt = options,
|
||||
result = ViewList(),
|
||||
filename_set = set(),
|
||||
state = Mock(),
|
||||
)
|
||||
directive.state.document.settings.tab_width = 8
|
||||
|
||||
processed_docstrings = []
|
||||
processed_signatures = []
|
||||
|
Loading…
Reference in New Issue
Block a user