summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2021-11-23 18:17:32 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2021-11-23 18:17:32 +0900
commitfae10db6ca6f9d5c7b0ffc0149ba9db3de314cae (patch)
treedb9aab77c2b28e556e583b3179916ae17de278a0
parentfafe688cbfbd3a3f9d19fdc427e618c93f3c586d (diff)
parent259de307cac9312e7a2f107d42606185c3aa8426 (diff)
downloadsphinx-git-fae10db6ca6f9d5c7b0ffc0149ba9db3de314cae.tar.gz
Merge branch '4.x'
-rw-r--r--CHANGES11
-rw-r--r--doc/usage/extensions/math.rst5
-rw-r--r--sphinx/ext/autodoc/__init__.py14
-rw-r--r--sphinx/ext/mathjax.py17
-rw-r--r--sphinx/util/inspect.py11
-rw-r--r--sphinx/writers/html5.py6
-rw-r--r--tests/roots/test-ext-autodoc/target/classes.py3
-rw-r--r--tests/test_ext_autodoc.py5
-rw-r--r--tests/test_ext_autodoc_autoclass.py12
-rw-r--r--tests/test_ext_math.py28
10 files changed, 98 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index 5bfc8171d..537f9e95f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -47,6 +47,8 @@ Features added
Bugs fixed
----------
+* #9866: autodoc: doccoment for the imported class was ignored
+* #9878: mathjax: MathJax configuration is placed after loading MathJax itself
* #9857: Generated RFC links use outdated base url
Testing
@@ -67,11 +69,20 @@ Deprecated
Features added
--------------
+* #9864: mathjax: Support chnaging the loading method of MathJax to "defer" via
+ :confval:`mathjax_options`
+
Bugs fixed
----------
* #9838: autodoc: AttributeError is raised on building document for functions
decorated by functools.lru_cache
+* #9879: autodoc: AttributeError is raised on building document for an object
+ having invalid __doc__ atribute
+* #9872: html: Class namespace collision between autodoc signatures and
+ docutils-0.17
+* #9864: mathjax: Failed to render equations via MathJax v2. The loading method
+ of MathJax is back to "async" method again
Testing
--------
diff --git a/doc/usage/extensions/math.rst b/doc/usage/extensions/math.rst
index 764bf5dd3..626306089 100644
--- a/doc/usage/extensions/math.rst
+++ b/doc/usage/extensions/math.rst
@@ -200,6 +200,11 @@ Sphinx but is set to automatically include it from a third-party site.
.. versionadded:: 1.8
+ .. versionchanged:: 4.4.1
+
+ Allow to change the loading method (async or defer) of MathJax if "async"
+ or "defer" key is set.
+
.. confval:: mathjax3_config
The configuration options for MathJax v3 (which is used by default).
diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py
index 2cdf224cb..157e57e3a 100644
--- a/sphinx/ext/autodoc/__init__.py
+++ b/sphinx/ext/autodoc/__init__.py
@@ -1704,7 +1704,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
classdoc_from = self.options.get('class-doc-from', self.config.autoclass_content)
docstrings = []
- attrdocstring = self.get_attr(self.object, '__doc__', None)
+ attrdocstring = getdoc(self.object, self.get_attr)
if attrdocstring:
docstrings.append(attrdocstring)
@@ -1743,14 +1743,22 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
def get_variable_comment(self) -> Optional[List[str]]:
try:
key = ('', '.'.join(self.objpath))
- analyzer = ModuleAnalyzer.for_module(self.get_real_modname())
+ if self.doc_as_attr:
+ analyzer = ModuleAnalyzer.for_module(self.modname)
+ else:
+ analyzer = ModuleAnalyzer.for_module(self.get_real_modname())
analyzer.analyze()
- return list(self.analyzer.attr_docs.get(key, []))
+ return list(analyzer.attr_docs.get(key, []))
except PycodeError:
return None
def add_content(self, more_content: Optional[StringList], no_docstring: bool = False
) -> None:
+ if self.doc_as_attr and self.modname != self.get_real_modname():
+ # override analyzer to obtain doccomment around its definition.
+ self.analyzer = ModuleAnalyzer.for_module(self.modname)
+ self.analyzer.analyze()
+
if self.doc_as_attr and not self.get_variable_comment():
try:
more_content = StringList([_('alias of %s') % restify(self.object)], source='')
diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py
index eb06908d3..30d038d84 100644
--- a/sphinx/ext/mathjax.py
+++ b/sphinx/ext/mathjax.py
@@ -81,11 +81,6 @@ def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: Dict
domain = cast(MathDomain, app.env.get_domain('math'))
if app.registry.html_assets_policy == 'always' or domain.has_equations(pagename):
# Enable mathjax only if equations exists
- options = {'defer': 'defer'}
- if app.config.mathjax_options:
- options.update(app.config.mathjax_options)
- app.add_js_file(app.config.mathjax_path, **options) # type: ignore
-
if app.config.mathjax2_config:
if app.config.mathjax_path == MATHJAX_URL:
logger.warning(
@@ -97,6 +92,18 @@ def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: Dict
body = 'window.MathJax = %s' % json.dumps(app.config.mathjax3_config)
app.add_js_file(None, body=body)
+ options = {}
+ if app.config.mathjax_options:
+ options.update(app.config.mathjax_options)
+ if 'async' not in options and 'defer' not in options:
+ if app.config.mathjax3_config:
+ # Load MathJax v3 via "defer" method
+ options['defer'] = 'defer'
+ else:
+ # Load other MathJax via "async" method
+ options['async'] = 'async'
+ app.add_js_file(app.config.mathjax_path, **options)
+
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_html_math_renderer('mathjax',
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 3a39bde1d..24ea49ae0 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -871,6 +871,13 @@ def getdoc(obj: Any, attrgetter: Callable = safe_getattr,
* inherited docstring
* inherited decorated methods
"""
+ def getdoc_internal(obj: Any, attrgetter: Callable = safe_getattr) -> Optional[str]:
+ doc = attrgetter(obj, '__doc__', None)
+ if isinstance(doc, str):
+ return doc
+ else:
+ return None
+
if cls and name and isclassmethod(obj, cls, name):
for basecls in getmro(cls):
meth = basecls.__dict__.get(name)
@@ -879,7 +886,7 @@ def getdoc(obj: Any, attrgetter: Callable = safe_getattr,
if doc is not None or not allow_inherited:
return doc
- doc = attrgetter(obj, '__doc__', None)
+ doc = getdoc_internal(obj)
if ispartial(obj) and doc == obj.__class__.__doc__:
return getdoc(obj.func)
elif doc is None and allow_inherited:
@@ -888,7 +895,7 @@ def getdoc(obj: Any, attrgetter: Callable = safe_getattr,
for basecls in getmro(cls):
meth = safe_getattr(basecls, name, None)
if meth is not None:
- doc = attrgetter(meth, '__doc__', None)
+ doc = getdoc_internal(meth)
if doc is not None:
break
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index 15fd15449..bba07f447 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -13,7 +13,7 @@ import posixpath
import re
import urllib.parse
import warnings
-from typing import TYPE_CHECKING, Iterable, Tuple, cast
+from typing import TYPE_CHECKING, Iterable, Set, Tuple, cast
from docutils import nodes
from docutils.nodes import Element, Node, Text
@@ -56,6 +56,10 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
"""
builder: "StandaloneHTMLBuilder" = None
+ # Override docutils.writers.html5_polyglot:HTMLTranslator
+ # otherwise, nodes like <inline classes="s">...</inline> will be
+ # converted to <s>...</s> by `visit_inline`.
+ supported_inline_tags: Set[str] = set()
def __init__(self, document: nodes.document, builder: Builder) -> None:
super().__init__(document, builder)
diff --git a/tests/roots/test-ext-autodoc/target/classes.py b/tests/roots/test-ext-autodoc/target/classes.py
index d18128584..5ba0294fb 100644
--- a/tests/roots/test-ext-autodoc/target/classes.py
+++ b/tests/roots/test-ext-autodoc/target/classes.py
@@ -37,3 +37,6 @@ Alias = Foo
#: docstring
OtherAlias = Bar
+
+#: docstring
+IntAlias = int
diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py
index 8f14392b2..c853fbb03 100644
--- a/tests/test_ext_autodoc.py
+++ b/tests/test_ext_autodoc.py
@@ -1870,12 +1870,15 @@ def test_autodoc_GenericAlias(app):
' .. py:attribute:: Class.T',
' :module: target.genericalias',
'',
+ ' A list of int',
+ '',
' alias of :py:class:`~typing.List`\\ [:py:class:`int`]',
'',
'.. py:attribute:: T',
' :module: target.genericalias',
'',
- ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]',
+ ' A list of int',
+ '',
]
else:
assert list(actual) == [
diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py
index 9c730f425..6f4e21060 100644
--- a/tests/test_ext_autodoc_autoclass.py
+++ b/tests/test_ext_autodoc_autoclass.py
@@ -407,6 +407,18 @@ def test_class_alias_having_doccomment(app):
]
+def test_class_alias_for_imported_object_having_doccomment(app):
+ actual = do_autodoc(app, 'class', 'target.classes.IntAlias')
+ assert list(actual) == [
+ '',
+ '.. py:attribute:: IntAlias',
+ ' :module: target.classes',
+ '',
+ ' docstring',
+ '',
+ ]
+
+
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_coroutine(app):
options = {"members": None}
diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py
index 7c78954b7..175c9e0f5 100644
--- a/tests/test_ext_math.py
+++ b/tests/test_ext_math.py
@@ -71,7 +71,7 @@ def test_mathjax_options(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').read_text()
- assert ('<script defer="defer" integrity="sha384-0123456789" '
+ assert ('<script async="async" integrity="sha384-0123456789" '
'src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">'
'</script>' in content)
@@ -221,6 +221,7 @@ def test_mathjax3_config(app, status, warning):
content = (app.outdir / 'index.html').read_text()
assert MATHJAX_URL in content
+ assert ('<script defer="defer" src="%s">' % MATHJAX_URL in content)
assert ('<script>window.MathJax = {"extensions": ["tex2jax.js"]}</script>' in content)
@@ -231,13 +232,36 @@ def test_mathjax2_config(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').read_text()
- assert MATHJAX_URL in content
+ assert ('<script async="async" src="%s">' % MATHJAX_URL in content)
assert ('<script type="text/x-mathjax-config">'
'MathJax.Hub.Config({"extensions": ["tex2jax.js"]})'
'</script>' in content)
@pytest.mark.sphinx('html', testroot='ext-math',
+ confoverrides={'extensions': ['sphinx.ext.mathjax'],
+ 'mathjax_options': {'async': 'async'},
+ 'mathjax3_config': {'extensions': ['tex2jax.js']}})
+def test_mathjax_options_async_for_mathjax3(app, status, warning):
+ app.builder.build_all()
+
+ content = (app.outdir / 'index.html').read_text()
+ assert MATHJAX_URL in content
+ assert ('<script async="async" src="%s">' % MATHJAX_URL in content)
+
+
+@pytest.mark.sphinx('html', testroot='ext-math',
+ confoverrides={'extensions': ['sphinx.ext.mathjax'],
+ 'mathjax_options': {'defer': 'defer'},
+ 'mathjax2_config': {'extensions': ['tex2jax.js']}})
+def test_mathjax_options_defer_for_mathjax2(app, status, warning):
+ app.builder.build_all()
+
+ content = (app.outdir / 'index.html').read_text()
+ assert ('<script defer="defer" src="%s">' % MATHJAX_URL in content)
+
+
+@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_is_installed_only_if_document_having_math(app, status, warning):
app.builder.build_all()