diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2021-11-23 18:17:32 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2021-11-23 18:17:32 +0900 |
commit | fae10db6ca6f9d5c7b0ffc0149ba9db3de314cae (patch) | |
tree | db9aab77c2b28e556e583b3179916ae17de278a0 | |
parent | fafe688cbfbd3a3f9d19fdc427e618c93f3c586d (diff) | |
parent | 259de307cac9312e7a2f107d42606185c3aa8426 (diff) | |
download | sphinx-git-fae10db6ca6f9d5c7b0ffc0149ba9db3de314cae.tar.gz |
Merge branch '4.x'
-rw-r--r-- | CHANGES | 11 | ||||
-rw-r--r-- | doc/usage/extensions/math.rst | 5 | ||||
-rw-r--r-- | sphinx/ext/autodoc/__init__.py | 14 | ||||
-rw-r--r-- | sphinx/ext/mathjax.py | 17 | ||||
-rw-r--r-- | sphinx/util/inspect.py | 11 | ||||
-rw-r--r-- | sphinx/writers/html5.py | 6 | ||||
-rw-r--r-- | tests/roots/test-ext-autodoc/target/classes.py | 3 | ||||
-rw-r--r-- | tests/test_ext_autodoc.py | 5 | ||||
-rw-r--r-- | tests/test_ext_autodoc_autoclass.py | 12 | ||||
-rw-r--r-- | tests/test_ext_math.py | 28 |
10 files changed, 98 insertions, 14 deletions
@@ -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() |