diff options
36 files changed, 459 insertions, 193 deletions
@@ -47,6 +47,11 @@ Features added * #9695: More CSS classes on Javascript domain descriptions * #9683: Revert the removal of ``add_stylesheet()`` API. It will be kept until the Sphinx-6.0 release +* #2068, add :confval:`intersphinx_disabled_reftypes` for disabling + interphinx resolution of cross-references that do not have an explicit + inventory specification. Specific types of cross-references can be disabled, + e.g., ``std:doc`` or all cross-references in a specific domain, + e.g., ``std:*``. Bugs fixed ---------- @@ -80,8 +85,15 @@ Bugs fixed * #9678: linkcheck: file extension was shown twice in warnings * #9697: py domain: An index entry with parens was registered for ``py:method`` directive with ``:property:`` option +* #9775: py domain: Literal typehint was converted to a cross reference when + :confval:`autodoc_typehints='description'` * #9708: needs_extension failed to check double-digit version correctly * #9688: Fix :rst:dir:`code`` does not recognize ``:class:`` option +* #9733: Fix for logging handler flushing warnings in the middle of the docs + build +* #9656: Fix warnings without subtype being incorrectly suppressed +* Intersphinx, for unresolved references with an explicit inventory, + e.g., ``proj:myFunc``, leave the inventory prefix in the unresolved text. Testing -------- diff --git a/doc/usage/extensions/intersphinx.rst b/doc/usage/extensions/intersphinx.rst index 478ddb7ae..a3e65bed6 100644 --- a/doc/usage/extensions/intersphinx.rst +++ b/doc/usage/extensions/intersphinx.rst @@ -148,6 +148,35 @@ linking: exception is raised if the server has not issued a response for timeout seconds. +.. confval:: intersphinx_disabled_reftypes + + .. versionadded:: 4.3 + + A list of strings being either: + + - the name of a specific reference type in a domain, + e.g., ``std:doc``, ``py:func``, or ``cpp:class``, + - the name of a domain, and a wildcard, e.g., + ``std:*``, ``py:*``, or ``cpp:*``, or + - simply a wildcard ``*``. + + The default value is an empty list. + + When a cross-reference without an explicit inventory specification is being + resolved by intersphinx, skip resolution if it matches one of the + specifications in this list. + + For example, with ``intersphinx_disabled_reftypes = ['std:doc']`` + a cross-reference ``:doc:`installation``` will not be attempted to be + resolved by intersphinx, but ``:doc:`otherbook:installation``` will be + attempted to be resolved in the inventory named ``otherbook`` in + :confval:`intersphinx_mapping`. + At the same time, all cross-references generated in, e.g., Python, + declarations will still be attempted to be resolved by intersphinx. + + If ``*`` is in the list of domains, then no references without an explicit + inventory will be resolved by intersphinx. + Showing all links of an Intersphinx mapping file ------------------------------------------------ diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 9bb9a1e72..fd6a78892 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -353,17 +353,21 @@ class PyXrefMixin: split_contnode = bool(contnode and contnode.astext() == target) + in_literal = False results = [] for sub_target in filter(None, sub_targets): if split_contnode: contnode = nodes.Text(sub_target) - if delims_re.match(sub_target): + if in_literal or delims_re.match(sub_target): results.append(contnode or innernode(sub_target, sub_target)) else: results.append(self.make_xref(rolename, domain, sub_target, innernode, contnode, env, inliner, location)) + if sub_target in ('Literal', 'typing.Literal'): + in_literal = True + return results diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 4795d1ae2..d5f92d6fb 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -29,11 +29,11 @@ import posixpath import sys import time from os import path -from typing import IO, Any, Dict, List, Tuple +from typing import IO, Any, Dict, List, Optional, Tuple from urllib.parse import urlsplit, urlunsplit from docutils import nodes -from docutils.nodes import TextElement +from docutils.nodes import Element, TextElement from docutils.utils import relative_path import sphinx @@ -41,11 +41,12 @@ from sphinx.addnodes import pending_xref from sphinx.application import Sphinx from sphinx.builders.html import INVENTORY_FILENAME from sphinx.config import Config +from sphinx.domains import Domain from sphinx.environment import BuildEnvironment from sphinx.locale import _, __ from sphinx.util import logging, requests from sphinx.util.inventory import InventoryFile -from sphinx.util.typing import Inventory +from sphinx.util.typing import Inventory, InventoryItem logger = logging.getLogger(__name__) @@ -258,105 +259,211 @@ def load_mappings(app: Sphinx) -> None: inventories.main_inventory.setdefault(type, {}).update(objects) -def missing_reference(app: Sphinx, env: BuildEnvironment, node: pending_xref, - contnode: TextElement) -> nodes.reference: - """Attempt to resolve a missing reference via intersphinx references.""" - target = node['reftarget'] - inventories = InventoryAdapter(env) - objtypes: List[str] = None - if node['reftype'] == 'any': - # we search anything! - objtypes = ['%s:%s' % (domain.name, objtype) - for domain in env.domains.values() - for objtype in domain.object_types] - domain = None +def _create_element_from_result(domain: Domain, inv_name: Optional[str], + data: InventoryItem, + node: pending_xref, contnode: TextElement) -> Element: + proj, version, uri, dispname = data + if '://' not in uri and node.get('refdoc'): + # get correct path in case of subdirectories + uri = path.join(relative_path(node['refdoc'], '.'), uri) + if version: + reftitle = _('(in %s v%s)') % (proj, version) else: - domain = node.get('refdomain') - if not domain: + reftitle = _('(in %s)') % (proj,) + newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle) + if node.get('refexplicit'): + # use whatever title was given + newnode.append(contnode) + elif dispname == '-' or \ + (domain.name == 'std' and node['reftype'] == 'keyword'): + # use whatever title was given, but strip prefix + title = contnode.astext() + if inv_name is not None and title.startswith(inv_name + ':'): + newnode.append(contnode.__class__(title[len(inv_name) + 1:], + title[len(inv_name) + 1:])) + else: + newnode.append(contnode) + else: + # else use the given display name (used for :ref:) + newnode.append(contnode.__class__(dispname, dispname)) + return newnode + + +def _resolve_reference_in_domain_by_target( + inv_name: Optional[str], inventory: Inventory, + domain: Domain, objtypes: List[str], + target: str, + node: pending_xref, contnode: TextElement) -> Optional[Element]: + for objtype in objtypes: + if objtype not in inventory: + # Continue if there's nothing of this kind in the inventory + continue + + if target in inventory[objtype]: + # Case sensitive match, use it + data = inventory[objtype][target] + elif objtype == 'std:term': + # Check for potential case insensitive matches for terms only + target_lower = target.lower() + insensitive_matches = list(filter(lambda k: k.lower() == target_lower, + inventory[objtype].keys())) + if insensitive_matches: + data = inventory[objtype][insensitive_matches[0]] + else: + # No case insensitive match either, continue to the next candidate + continue + else: + # Could reach here if we're not a term but have a case insensitive match. + # This is a fix for terms specifically, but potentially should apply to + # other types. + continue + return _create_element_from_result(domain, inv_name, data, node, contnode) + return None + + +def _resolve_reference_in_domain(env: BuildEnvironment, + inv_name: Optional[str], inventory: Inventory, + honor_disabled_refs: bool, + domain: Domain, objtypes: List[str], + node: pending_xref, contnode: TextElement + ) -> Optional[Element]: + # we adjust the object types for backwards compatibility + if domain.name == 'std' and 'cmdoption' in objtypes: + # until Sphinx-1.6, cmdoptions are stored as std:option + objtypes.append('option') + if domain.name == 'py' and 'attribute' in objtypes: + # Since Sphinx-2.1, properties are stored as py:method + objtypes.append('method') + + # the inventory contains domain:type as objtype + objtypes = ["{}:{}".format(domain.name, t) for t in objtypes] + + # now that the objtypes list is complete we can remove the disabled ones + if honor_disabled_refs: + disabled = env.config.intersphinx_disabled_reftypes + objtypes = [o for o in objtypes if o not in disabled] + + # without qualification + res = _resolve_reference_in_domain_by_target(inv_name, inventory, domain, objtypes, + node['reftarget'], node, contnode) + if res is not None: + return res + + # try with qualification of the current scope instead + full_qualified_name = domain.get_full_qualified_name(node) + if full_qualified_name is None: + return None + return _resolve_reference_in_domain_by_target(inv_name, inventory, domain, objtypes, + full_qualified_name, node, contnode) + + +def _resolve_reference(env: BuildEnvironment, inv_name: Optional[str], inventory: Inventory, + honor_disabled_refs: bool, + node: pending_xref, contnode: TextElement) -> Optional[Element]: + # disabling should only be done if no inventory is given + honor_disabled_refs = honor_disabled_refs and inv_name is None + + if honor_disabled_refs and '*' in env.config.intersphinx_disabled_reftypes: + return None + + typ = node['reftype'] + if typ == 'any': + for domain_name, domain in env.domains.items(): + if honor_disabled_refs \ + and (domain_name + ":*") in env.config.intersphinx_disabled_reftypes: + continue + objtypes = list(domain.object_types) + res = _resolve_reference_in_domain(env, inv_name, inventory, + honor_disabled_refs, + domain, objtypes, + node, contnode) + if res is not None: + return res + return None + else: + domain_name = node.get('refdomain') + if not domain_name: # only objects in domains are in the inventory return None - objtypes = env.get_domain(domain).objtypes_for_role(node['reftype']) + if honor_disabled_refs \ + and (domain_name + ":*") in env.config.intersphinx_disabled_reftypes: + return None + domain = env.get_domain(domain_name) + objtypes = domain.objtypes_for_role(typ) if not objtypes: return None - objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes] - if 'std:cmdoption' in objtypes: - # until Sphinx-1.6, cmdoptions are stored as std:option - objtypes.append('std:option') - if 'py:attribute' in objtypes: - # Since Sphinx-2.1, properties are stored as py:method - objtypes.append('py:method') - - to_try = [(inventories.main_inventory, target)] - if domain: - full_qualified_name = env.get_domain(domain).get_full_qualified_name(node) - if full_qualified_name: - to_try.append((inventories.main_inventory, full_qualified_name)) - in_set = None - if ':' in target: - # first part may be the foreign doc set name - setname, newtarget = target.split(':', 1) - if setname in inventories.named_inventory: - in_set = setname - to_try.append((inventories.named_inventory[setname], newtarget)) - if domain: - node['reftarget'] = newtarget - full_qualified_name = env.get_domain(domain).get_full_qualified_name(node) - if full_qualified_name: - to_try.append((inventories.named_inventory[setname], full_qualified_name)) - for inventory, target in to_try: - for objtype in objtypes: - if objtype not in inventory: - # Continue if there's nothing of this kind in the inventory - continue - if target in inventory[objtype]: - # Case sensitive match, use it - proj, version, uri, dispname = inventory[objtype][target] - elif objtype == 'std:term': - # Check for potential case insensitive matches for terms only - target_lower = target.lower() - insensitive_matches = list(filter(lambda k: k.lower() == target_lower, - inventory[objtype].keys())) - if insensitive_matches: - proj, version, uri, dispname = inventory[objtype][insensitive_matches[0]] - else: - # No case insensitive match either, continue to the next candidate - continue - else: - # Could reach here if we're not a term but have a case insensitive match. - # This is a fix for terms specifically, but potentially should apply to - # other types. - continue + return _resolve_reference_in_domain(env, inv_name, inventory, + honor_disabled_refs, + domain, objtypes, + node, contnode) - if '://' not in uri and node.get('refdoc'): - # get correct path in case of subdirectories - uri = path.join(relative_path(node['refdoc'], '.'), uri) - if version: - reftitle = _('(in %s v%s)') % (proj, version) - else: - reftitle = _('(in %s)') % (proj,) - newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle) - if node.get('refexplicit'): - # use whatever title was given - newnode.append(contnode) - elif dispname == '-' or \ - (domain == 'std' and node['reftype'] == 'keyword'): - # use whatever title was given, but strip prefix - title = contnode.astext() - if in_set and title.startswith(in_set + ':'): - newnode.append(contnode.__class__(title[len(in_set) + 1:], - title[len(in_set) + 1:])) - else: - newnode.append(contnode) - else: - # else use the given display name (used for :ref:) - newnode.append(contnode.__class__(dispname, dispname)) - return newnode - # at least get rid of the ':' in the target if no explicit title given - if in_set is not None and not node.get('refexplicit', True): - if len(contnode) and isinstance(contnode[0], nodes.Text): - contnode[0] = nodes.Text(newtarget, contnode[0].rawsource) - return None +def inventory_exists(env: BuildEnvironment, inv_name: str) -> bool: + return inv_name in InventoryAdapter(env).named_inventory + + +def resolve_reference_in_inventory(env: BuildEnvironment, + inv_name: str, + node: pending_xref, contnode: TextElement + ) -> Optional[Element]: + """Attempt to resolve a missing reference via intersphinx references. + + Resolution is tried in the given inventory with the target as is. + + Requires ``inventory_exists(env, inv_name)``. + """ + assert inventory_exists(env, inv_name) + return _resolve_reference(env, inv_name, InventoryAdapter(env).named_inventory[inv_name], + False, node, contnode) + + +def resolve_reference_any_inventory(env: BuildEnvironment, + honor_disabled_refs: bool, + node: pending_xref, contnode: TextElement + ) -> Optional[Element]: + """Attempt to resolve a missing reference via intersphinx references. + + Resolution is tried with the target as is in any inventory. + """ + return _resolve_reference(env, None, InventoryAdapter(env).main_inventory, + honor_disabled_refs, + node, contnode) + + +def resolve_reference_detect_inventory(env: BuildEnvironment, + node: pending_xref, contnode: TextElement + ) -> Optional[Element]: + """Attempt to resolve a missing reference via intersphinx references. + + Resolution is tried first with the target as is in any inventory. + If this does not succeed, then the target is split by the first ``:``, + to form ``inv_name:newtarget``. If ``inv_name`` is a named inventory, then resolution + is tried in that inventory with the new target. + """ + + # ordinary direct lookup, use data as is + res = resolve_reference_any_inventory(env, True, node, contnode) + if res is not None: + return res + + # try splitting the target into 'inv_name:target' + target = node['reftarget'] + if ':' not in target: + return None + inv_name, newtarget = target.split(':', 1) + if not inventory_exists(env, inv_name): + return None + node['reftarget'] = newtarget + res_inv = resolve_reference_in_inventory(env, inv_name, node, contnode) + node['reftarget'] = target + return res_inv + + +def missing_reference(app: Sphinx, env: BuildEnvironment, node: pending_xref, + contnode: TextElement) -> Optional[Element]: + """Attempt to resolve a missing reference via intersphinx references.""" + + return resolve_reference_detect_inventory(env, node, contnode) def normalize_intersphinx_mapping(app: Sphinx, config: Config) -> None: @@ -387,6 +494,7 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.add_config_value('intersphinx_mapping', {}, True) app.add_config_value('intersphinx_cache_limit', 5, False) app.add_config_value('intersphinx_timeout', None, False) + app.add_config_value('intersphinx_disabled_reftypes', [], True) app.connect('config-inited', normalize_intersphinx_mapping, priority=800) app.connect('builder-inited', load_mappings) app.connect('missing-reference', missing_reference) diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.mo b/sphinx/locale/ca/LC_MESSAGES/sphinx.mo Binary files differindex 9e2239146..4330d14c5 100644 --- a/sphinx/locale/ca/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/ca/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.po b/sphinx/locale/ca/LC_MESSAGES/sphinx.po index 407f06ee8..ee7764ac6 100644 --- a/sphinx/locale/ca/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/ca/LC_MESSAGES/sphinx.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Catalan (http://www.transifex.com/sphinx-doc/sphinx-1/language/ca/)\n" @@ -2867,7 +2867,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2898,12 +2898,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/el/LC_MESSAGES/sphinx.mo b/sphinx/locale/el/LC_MESSAGES/sphinx.mo Binary files differindex ecfe239e2..b1818f164 100644 --- a/sphinx/locale/el/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/el/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/el/LC_MESSAGES/sphinx.po b/sphinx/locale/el/LC_MESSAGES/sphinx.po index 7d413baab..91b3ddadb 100644 --- a/sphinx/locale/el/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/el/LC_MESSAGES/sphinx.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Greek (http://www.transifex.com/sphinx-doc/sphinx-1/language/el/)\n" @@ -2869,7 +2869,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2900,12 +2900,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/et/LC_MESSAGES/sphinx.mo b/sphinx/locale/et/LC_MESSAGES/sphinx.mo Binary files differindex 6be71bb04..1c6bb4257 100644 --- a/sphinx/locale/et/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/et/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/et/LC_MESSAGES/sphinx.po b/sphinx/locale/et/LC_MESSAGES/sphinx.po index 415c298a8..f3b9e75fb 100644 --- a/sphinx/locale/et/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/et/LC_MESSAGES/sphinx.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Estonian (http://www.transifex.com/sphinx-doc/sphinx-1/language/et/)\n" @@ -2870,7 +2870,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2901,12 +2901,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/hr/LC_MESSAGES/sphinx.mo b/sphinx/locale/hr/LC_MESSAGES/sphinx.mo Binary files differindex 52c2453c1..5ecb9cee5 100644 --- a/sphinx/locale/hr/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/hr/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/hr/LC_MESSAGES/sphinx.po b/sphinx/locale/hr/LC_MESSAGES/sphinx.po index eeec09de2..3292cd9aa 100644 --- a/sphinx/locale/hr/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/hr/LC_MESSAGES/sphinx.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Croatian (http://www.transifex.com/sphinx-doc/sphinx-1/language/hr/)\n" @@ -2867,7 +2867,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2898,12 +2898,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/hu/LC_MESSAGES/sphinx.mo b/sphinx/locale/hu/LC_MESSAGES/sphinx.mo Binary files differindex c6eed34f9..b79fde0fd 100644 --- a/sphinx/locale/hu/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/hu/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/hu/LC_MESSAGES/sphinx.po b/sphinx/locale/hu/LC_MESSAGES/sphinx.po index a7aad89c8..979870f64 100644 --- a/sphinx/locale/hu/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/hu/LC_MESSAGES/sphinx.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Hungarian (http://www.transifex.com/sphinx-doc/sphinx-1/language/hu/)\n" @@ -2872,7 +2872,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2903,12 +2903,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/pl/LC_MESSAGES/sphinx.mo b/sphinx/locale/pl/LC_MESSAGES/sphinx.mo Binary files differindex 64bff6699..211236fd6 100644 --- a/sphinx/locale/pl/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/pl/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/pl/LC_MESSAGES/sphinx.po b/sphinx/locale/pl/LC_MESSAGES/sphinx.po index 4ba930cc1..f6338072e 100644 --- a/sphinx/locale/pl/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/pl/LC_MESSAGES/sphinx.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Polish (http://www.transifex.com/sphinx-doc/sphinx-1/language/pl/)\n" @@ -2870,7 +2870,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2901,12 +2901,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/sk/LC_MESSAGES/sphinx.mo b/sphinx/locale/sk/LC_MESSAGES/sphinx.mo Binary files differindex 1a09a1ad3..50f8968e7 100644 --- a/sphinx/locale/sk/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/sk/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/sk/LC_MESSAGES/sphinx.po b/sphinx/locale/sk/LC_MESSAGES/sphinx.po index 6e3b76407..00f5401e4 100644 --- a/sphinx/locale/sk/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/sk/LC_MESSAGES/sphinx.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Slovak (http://www.transifex.com/sphinx-doc/sphinx-1/language/sk/)\n" @@ -2869,7 +2869,7 @@ msgid "" msgstr "chýbajúci atribút spomenutý vo voľbe :members: : modul %s, atribút %s" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2900,12 +2900,12 @@ msgstr "alias pre TypeVar(%s)" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "Neplatné __slots__ nájdené v %s. Ignorované." -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/sl/LC_MESSAGES/sphinx.mo b/sphinx/locale/sl/LC_MESSAGES/sphinx.mo Binary files differindex 16c4ca479..c6b6d4c24 100644 --- a/sphinx/locale/sl/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/sl/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/sl/LC_MESSAGES/sphinx.po b/sphinx/locale/sl/LC_MESSAGES/sphinx.po index 09e1129a0..0ebe83c10 100644 --- a/sphinx/locale/sl/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/sl/LC_MESSAGES/sphinx.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Slovenian (http://www.transifex.com/sphinx-doc/sphinx-1/language/sl/)\n" @@ -2866,7 +2866,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2897,12 +2897,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/sphinx.pot b/sphinx/locale/sphinx.pot index 94c26f6bc..eb6ac784b 100644 --- a/sphinx/locale/sphinx.pot +++ b/sphinx/locale/sphinx.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx 4.3.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -2884,7 +2884,7 @@ msgid "missing attribute mentioned in :members: option: module %s, attribute %s" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2915,12 +2915,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of " "\"alphabetic\". Please update your setting." diff --git a/sphinx/locale/sq/LC_MESSAGES/sphinx.mo b/sphinx/locale/sq/LC_MESSAGES/sphinx.mo Binary files differindex 51486fd4a..eca45a5e8 100644 --- a/sphinx/locale/sq/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/sq/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/sq/LC_MESSAGES/sphinx.po b/sphinx/locale/sq/LC_MESSAGES/sphinx.po index 67ad6ed1d..4f7c11bd7 100644 --- a/sphinx/locale/sq/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/sq/LC_MESSAGES/sphinx.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Albanian (http://www.transifex.com/sphinx-doc/sphinx-1/language/sq/)\n" @@ -2867,7 +2867,7 @@ msgid "" msgstr "u përmend atribut që mungon në :members: mundësi: modul %s, atributi %s" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "S’u arrit të merret një nënshkrim funksioni për %s: %s" @@ -2898,12 +2898,12 @@ msgstr "alias për TypeVar(%s)" msgid "Failed to get a method signature for %s: %s" msgstr "S’u arrit të merre një nënshkrim metode për %s: %s" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "U gjet __slots__ i pavlefshëm në %s. U shpërfill." -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo b/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo Binary files differindex cb17b429c..14dff456e 100644 --- a/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.po b/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.po index c69fc1351..9707e5dbe 100644 --- a/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/sr_RS/LC_MESSAGES/sphinx.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Serbian (Serbia) (http://www.transifex.com/sphinx-doc/sphinx-1/language/sr_RS/)\n" @@ -2866,7 +2866,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2897,12 +2897,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/tr/LC_MESSAGES/sphinx.mo b/sphinx/locale/tr/LC_MESSAGES/sphinx.mo Binary files differindex 65366b33d..de9059a74 100644 --- a/sphinx/locale/tr/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/tr/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/tr/LC_MESSAGES/sphinx.po b/sphinx/locale/tr/LC_MESSAGES/sphinx.po index 5fc22ea17..86d03a182 100644 --- a/sphinx/locale/tr/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/tr/LC_MESSAGES/sphinx.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Turkish (http://www.transifex.com/sphinx-doc/sphinx-1/language/tr/)\n" @@ -2870,7 +2870,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2901,12 +2901,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/locale/yue/LC_MESSAGES/sphinx.mo b/sphinx/locale/yue/LC_MESSAGES/sphinx.mo Binary files differindex be69bc988..7e3c4d89d 100644 --- a/sphinx/locale/yue/LC_MESSAGES/sphinx.mo +++ b/sphinx/locale/yue/LC_MESSAGES/sphinx.mo diff --git a/sphinx/locale/yue/LC_MESSAGES/sphinx.po b/sphinx/locale/yue/LC_MESSAGES/sphinx.po index a7f376a5d..08d17aa01 100644 --- a/sphinx/locale/yue/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/yue/LC_MESSAGES/sphinx.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Sphinx\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-10-25 16:47+0000\n" +"POT-Creation-Date: 2021-10-31 00:10+0000\n" "PO-Revision-Date: 2021-10-10 00:10+0000\n" "Last-Translator: Komiya Takeshi <i.tkomiya@gmail.com>\n" "Language-Team: Cantonese (http://www.transifex.com/sphinx-doc/sphinx-1/language/yue/)\n" @@ -2866,7 +2866,7 @@ msgid "" msgstr "" #: sphinx/ext/autodoc/__init__.py:1304 sphinx/ext/autodoc/__init__.py:1378 -#: sphinx/ext/autodoc/__init__.py:2735 +#: sphinx/ext/autodoc/__init__.py:2743 #, python-format msgid "Failed to get a function signature for %s: %s" msgstr "" @@ -2897,12 +2897,12 @@ msgstr "" msgid "Failed to get a method signature for %s: %s" msgstr "" -#: sphinx/ext/autodoc/__init__.py:2349 +#: sphinx/ext/autodoc/__init__.py:2348 #, python-format msgid "Invalid __slots__ found on %s. Ignored." msgstr "" -#: sphinx/ext/autodoc/__init__.py:2778 +#: sphinx/ext/autodoc/__init__.py:2786 msgid "" "autodoc_member_order now accepts \"alphabetical\" instead of \"alphabetic\"." " Please update your setting." diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py_t index f1da41c4a..07a1aa867 100644 --- a/sphinx/templates/quickstart/conf.py_t +++ b/sphinx/templates/quickstart/conf.py_t @@ -108,6 +108,7 @@ html_static_path = ['{{ dot }}static'] intersphinx_mapping = { 'python': ('https://docs.python.org/3', None), } + {%- endif %} {%- if 'sphinx.ext.todo' in extensions %} diff --git a/sphinx/transforms/i18n.py b/sphinx/transforms/i18n.py index d0bc8af5d..8ef7987f9 100644 --- a/sphinx/transforms/i18n.py +++ b/sphinx/transforms/i18n.py @@ -296,9 +296,9 @@ class Locale(SphinxTransform): lst.append(new) is_autofootnote_ref = NodeMatcher(nodes.footnote_reference, auto=Any) - old_foot_refs: List[nodes.footnote_reference] = node.traverse(is_autofootnote_ref) - new_foot_refs: List[nodes.footnote_reference] = patch.traverse(is_autofootnote_ref) - if len(list(old_foot_refs)) != len(list(new_foot_refs)): + old_foot_refs: List[nodes.footnote_reference] = list(node.traverse(is_autofootnote_ref)) # NOQA + new_foot_refs: List[nodes.footnote_reference] = list(patch.traverse(is_autofootnote_ref)) # NOQA + if len(old_foot_refs) != len(new_foot_refs): old_foot_ref_rawsources = [ref.rawsource for ref in old_foot_refs] new_foot_ref_rawsources = [ref.rawsource for ref in new_foot_refs] logger.warning(__('inconsistent footnote references in translated message.' + @@ -339,9 +339,9 @@ class Locale(SphinxTransform): # * use translated refname for section refname. # * inline reference "`Python <...>`_" has no 'refname'. is_refnamed_ref = NodeMatcher(nodes.reference, refname=Any) - old_refs: List[nodes.reference] = node.traverse(is_refnamed_ref) - new_refs: List[nodes.reference] = patch.traverse(is_refnamed_ref) - if len(list(old_refs)) != len(list(new_refs)): + old_refs: List[nodes.reference] = list(node.traverse(is_refnamed_ref)) + new_refs: List[nodes.reference] = list(patch.traverse(is_refnamed_ref)) + if len(old_refs) != len(new_refs): old_ref_rawsources = [ref.rawsource for ref in old_refs] new_ref_rawsources = [ref.rawsource for ref in new_refs] logger.warning(__('inconsistent references in translated message.' + @@ -366,10 +366,10 @@ class Locale(SphinxTransform): # refnamed footnote should use original 'ids'. is_refnamed_footnote_ref = NodeMatcher(nodes.footnote_reference, refname=Any) - old_foot_refs = node.traverse(is_refnamed_footnote_ref) - new_foot_refs = patch.traverse(is_refnamed_footnote_ref) + old_foot_refs = list(node.traverse(is_refnamed_footnote_ref)) + new_foot_refs = list(patch.traverse(is_refnamed_footnote_ref)) refname_ids_map: Dict[str, List[str]] = {} - if len(list(old_foot_refs)) != len(list(new_foot_refs)): + if len(old_foot_refs) != len(new_foot_refs): old_foot_ref_rawsources = [ref.rawsource for ref in old_foot_refs] new_foot_ref_rawsources = [ref.rawsource for ref in new_foot_refs] logger.warning(__('inconsistent footnote references in translated message.' + @@ -385,10 +385,10 @@ class Locale(SphinxTransform): # citation should use original 'ids'. is_citation_ref = NodeMatcher(nodes.citation_reference, refname=Any) - old_cite_refs: List[nodes.citation_reference] = node.traverse(is_citation_ref) - new_cite_refs: List[nodes.citation_reference] = patch.traverse(is_citation_ref) + old_cite_refs: List[nodes.citation_reference] = list(node.traverse(is_citation_ref)) # NOQA + new_cite_refs: List[nodes.citation_reference] = list(patch.traverse(is_citation_ref)) # NOQA refname_ids_map = {} - if len(list(old_cite_refs)) != len(list(new_cite_refs)): + if len(old_cite_refs) != len(new_cite_refs): old_cite_ref_rawsources = [ref.rawsource for ref in old_cite_refs] new_cite_ref_rawsources = [ref.rawsource for ref in new_cite_refs] logger.warning(__('inconsistent citation references in translated message.' + @@ -405,10 +405,10 @@ class Locale(SphinxTransform): # Original pending_xref['reftarget'] contain not-translated # target name, new pending_xref must use original one. # This code restricts to change ref-targets in the translation. - old_xrefs = node.traverse(addnodes.pending_xref) - new_xrefs = patch.traverse(addnodes.pending_xref) + old_xrefs = list(node.traverse(addnodes.pending_xref)) + new_xrefs = list(patch.traverse(addnodes.pending_xref)) xref_reftarget_map = {} - if len(list(old_xrefs)) != len(list(new_xrefs)): + if len(old_xrefs) != len(new_xrefs): old_xref_rawsources = [xref.rawsource for xref in old_xrefs] new_xref_rawsources = [xref.rawsource for xref in new_xrefs] logger.warning(__('inconsistent term references in translated message.' + diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index e18d82469..bdf77dc07 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -171,6 +171,11 @@ class MemoryHandler(logging.handlers.BufferingHandler): def shouldFlush(self, record: logging.LogRecord) -> bool: return False # never flush + def flush(self) -> None: + # suppress any flushes triggered by importing packages that flush + # all handlers at initialization time + pass + def flushTo(self, logger: logging.Logger) -> None: self.acquire() try: @@ -364,8 +369,10 @@ def is_suppressed_warning(type: str, subtype: str, suppress_warnings: List[str]) target, subtarget = warning_type, None if target == type: - if (subtype is None or subtarget is None or - subtarget == subtype or subtarget == '*'): + if ((subtype is None and subtarget is None) or + subtarget is None or + subtarget == subtype or + subtarget == '*'): return True return False diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index a2ab5f931..e1972d86d 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -70,7 +70,8 @@ OptionSpec = Dict[str, Callable[[str], Any]] TitleGetter = Callable[[nodes.Node], str] # inventory data on memory -Inventory = Dict[str, Dict[str, Tuple[str, str, str, str]]] +InventoryItem = Tuple[str, str, str, str] +Inventory = Dict[str, Dict[str, InventoryItem]] def get_type_hints(obj: Any, globalns: Dict = None, localns: Dict = None) -> Dict[str, Any]: diff --git a/tests/test_domain_py.py b/tests/test_domain_py.py index 5ba63d0e3..e34218dfa 100644 --- a/tests/test_domain_py.py +++ b/tests/test_domain_py.py @@ -1110,6 +1110,42 @@ def test_info_field_list_piped_type(app): **{"py:module": "example", "py:class": "Class"}) +def test_info_field_list_Literal(app): + text = (".. py:module:: example\n" + ".. py:class:: Class\n" + "\n" + " :param age: blah blah\n" + " :type age: Literal['foo', 'bar', 'baz']\n") + doctree = restructuredtext.parse(app, text) + + assert_node(doctree, + (nodes.target, + addnodes.index, + addnodes.index, + [desc, ([desc_signature, ([desc_annotation, ("class", desc_sig_space)], + [desc_addname, "example."], + [desc_name, "Class"])], + [desc_content, nodes.field_list, nodes.field, (nodes.field_name, + nodes.field_body)])])) + assert_node(doctree[3][1][0][0][1], + ([nodes.paragraph, ([addnodes.literal_strong, "age"], + " (", + [pending_xref, addnodes.literal_emphasis, "Literal"], + [addnodes.literal_emphasis, "["], + [addnodes.literal_emphasis, "'foo'"], + [addnodes.literal_emphasis, ", "], + [addnodes.literal_emphasis, "'bar'"], + [addnodes.literal_emphasis, ", "], + [addnodes.literal_emphasis, "'baz'"], + [addnodes.literal_emphasis, "]"], + ")", + " -- ", + "blah blah")],)) + assert_node(doctree[3][1][0][0][1][0][2], pending_xref, + refdomain="py", reftype="class", reftarget="Literal", + **{"py:module": "example", "py:class": "Class"}) + + def test_info_field_list_var(app): text = (".. py:class:: Class\n" "\n" diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py index 28b5e63b1..e820730a1 100644 --- a/tests/test_ext_intersphinx.py +++ b/tests/test_ext_intersphinx.py @@ -42,6 +42,12 @@ def reference_check(app, *args, **kwds): return missing_reference(app, app.env, node, contnode) +def set_config(app, mapping): + app.config.intersphinx_mapping = mapping + app.config.intersphinx_cache_limit = 0 + app.config.intersphinx_disabled_reftypes = [] + + @mock.patch('sphinx.ext.intersphinx.InventoryFile') @mock.patch('sphinx.ext.intersphinx._read_from_url') def test_fetch_inventory_redirection(_read_from_url, InventoryFile, app, status, warning): @@ -90,13 +96,12 @@ def test_fetch_inventory_redirection(_read_from_url, InventoryFile, app, status, def test_missing_reference(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) - app.config.intersphinx_mapping = { + set_config(app, { 'https://docs.python.org/': inv_file, 'py3k': ('https://docs.python.org/py3k/', inv_file), 'py3krel': ('py3k', inv_file), # relative path 'py3krelparent': ('../../py3k', inv_file), # relative path, parent dir - } - app.config.intersphinx_cache_limit = 0 + }) # load the inventory and check if it's done correctly normalize_intersphinx_mapping(app, app.config) @@ -133,12 +138,12 @@ def test_missing_reference(tempdir, app, status, warning): refexplicit=True) assert rn[0].astext() == 'py3k:module2' - # prefix given, target not found and nonexplicit title: prefix is stripped + # prefix given, target not found and nonexplicit title: prefix is not stripped node, contnode = fake_node('py', 'mod', 'py3k:unknown', 'py3k:unknown', refexplicit=False) rn = missing_reference(app, app.env, node, contnode) assert rn is None - assert contnode[0].astext() == 'unknown' + assert contnode[0].astext() == 'py3k:unknown' # prefix given, target not found and explicit title: nothing is changed node, contnode = fake_node('py', 'mod', 'py3k:unknown', 'py3k:unknown', @@ -169,10 +174,9 @@ def test_missing_reference(tempdir, app, status, warning): def test_missing_reference_pydomain(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) - app.config.intersphinx_mapping = { + set_config(app, { 'https://docs.python.org/': inv_file, - } - app.config.intersphinx_cache_limit = 0 + }) # load the inventory and check if it's done correctly normalize_intersphinx_mapping(app, app.config) @@ -210,10 +214,9 @@ def test_missing_reference_pydomain(tempdir, app, status, warning): def test_missing_reference_stddomain(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) - app.config.intersphinx_mapping = { + set_config(app, { 'cmd': ('https://docs.python.org/', inv_file), - } - app.config.intersphinx_cache_limit = 0 + }) # load the inventory and check if it's done correctly normalize_intersphinx_mapping(app, app.config) @@ -242,10 +245,9 @@ def test_missing_reference_stddomain(tempdir, app, status, warning): def test_missing_reference_cppdomain(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) - app.config.intersphinx_mapping = { + set_config(app, { 'https://docs.python.org/': inv_file, - } - app.config.intersphinx_cache_limit = 0 + }) # load the inventory and check if it's done correctly normalize_intersphinx_mapping(app, app.config) @@ -269,10 +271,9 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning): def test_missing_reference_jsdomain(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) - app.config.intersphinx_mapping = { + set_config(app, { 'https://docs.python.org/': inv_file, - } - app.config.intersphinx_cache_limit = 0 + }) # load the inventory and check if it's done correctly normalize_intersphinx_mapping(app, app.config) @@ -291,14 +292,75 @@ def test_missing_reference_jsdomain(tempdir, app, status, warning): assert rn.astext() == 'baz()' +def test_missing_reference_disabled_domain(tempdir, app, status, warning): + inv_file = tempdir / 'inventory' + inv_file.write_bytes(inventory_v2) + set_config(app, { + 'inv': ('https://docs.python.org/', inv_file), + }) + + # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) + load_mappings(app) + + def case(*, term, doc, py): + def assert_(rn, expected): + if expected is None: + assert rn is None + else: + assert rn.astext() == expected + + kwargs = {} + + node, contnode = fake_node('std', 'term', 'a term', 'a term', **kwargs) + rn = missing_reference(app, app.env, node, contnode) + assert_(rn, 'a term' if term else None) + + node, contnode = fake_node('std', 'term', 'inv:a term', 'a term', **kwargs) + rn = missing_reference(app, app.env, node, contnode) + assert_(rn, 'a term') + + node, contnode = fake_node('std', 'doc', 'docname', 'docname', **kwargs) + rn = missing_reference(app, app.env, node, contnode) + assert_(rn, 'docname' if doc else None) + + node, contnode = fake_node('std', 'doc', 'inv:docname', 'docname', **kwargs) + rn = missing_reference(app, app.env, node, contnode) + assert_(rn, 'docname') + + # an arbitrary ref in another domain + node, contnode = fake_node('py', 'func', 'module1.func', 'func()', **kwargs) + rn = missing_reference(app, app.env, node, contnode) + assert_(rn, 'func()' if py else None) + + node, contnode = fake_node('py', 'func', 'inv:module1.func', 'func()', **kwargs) + rn = missing_reference(app, app.env, node, contnode) + assert_(rn, 'func()') + + # the base case, everything should resolve + assert app.config.intersphinx_disabled_reftypes == [] + case(term=True, doc=True, py=True) + + # disabled a single ref type + app.config.intersphinx_disabled_reftypes = ['std:doc'] + case(term=True, doc=False, py=True) + + # disabled a whole domain + app.config.intersphinx_disabled_reftypes = ['std:*'] + case(term=False, doc=False, py=True) + + # disabled all domains + app.config.intersphinx_disabled_reftypes = ['*'] + case(term=False, doc=False, py=False) + + @pytest.mark.xfail(os.name != 'posix', reason="Path separator mismatch issue") def test_inventory_not_having_version(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2_not_having_version) - app.config.intersphinx_mapping = { + set_config(app, { 'https://docs.python.org/': inv_file, - } - app.config.intersphinx_cache_limit = 0 + }) # load the inventory and check if it's done correctly normalize_intersphinx_mapping(app, app.config) @@ -318,16 +380,15 @@ def test_load_mappings_warnings(tempdir, app, status, warning): """ inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) - app.config.intersphinx_mapping = { + set_config(app, { 'https://docs.python.org/': inv_file, 'py3k': ('https://docs.python.org/py3k/', inv_file), 'repoze.workflow': ('http://docs.repoze.org/workflow/', inv_file), 'django-taggit': ('http://django-taggit.readthedocs.org/en/latest/', inv_file), 12345: ('http://www.sphinx-doc.org/en/stable/', inv_file), - } + }) - app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly normalize_intersphinx_mapping(app, app.config) load_mappings(app) @@ -337,7 +398,7 @@ def test_load_mappings_warnings(tempdir, app, status, warning): def test_load_mappings_fallback(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) - app.config.intersphinx_cache_limit = 0 + set_config(app, {}) # connect to invalid path app.config.intersphinx_mapping = { diff --git a/tests/test_util_logging.py b/tests/test_util_logging.py index a03f62b01..5abcd02ef 100644 --- a/tests/test_util_logging.py +++ b/tests/test_util_logging.py @@ -131,6 +131,7 @@ def test_is_suppressed_warning(): assert is_suppressed_warning("ref", "option", suppress_warnings) is True assert is_suppressed_warning("files", "image", suppress_warnings) is True assert is_suppressed_warning("files", "stylesheet", suppress_warnings) is True + assert is_suppressed_warning("rest", None, suppress_warnings) is False assert is_suppressed_warning("rest", "syntax", suppress_warnings) is False assert is_suppressed_warning("rest", "duplicated_labels", suppress_warnings) is True @@ -143,33 +144,39 @@ def test_suppress_warnings(app, status, warning): app.config.suppress_warnings = [] warning.truncate(0) + logger.warning('message0', type='test') logger.warning('message1', type='test', subtype='logging') logger.warning('message2', type='test', subtype='crash') logger.warning('message3', type='actual', subtype='logging') + assert 'message0' in warning.getvalue() assert 'message1' in warning.getvalue() assert 'message2' in warning.getvalue() assert 'message3' in warning.getvalue() - assert app._warncount == 3 + assert app._warncount == 4 app.config.suppress_warnings = ['test'] warning.truncate(0) + logger.warning('message0', type='test') logger.warning('message1', type='test', subtype='logging') logger.warning('message2', type='test', subtype='crash') logger.warning('message3', type='actual', subtype='logging') + assert 'message0' not in warning.getvalue() assert 'message1' not in warning.getvalue() assert 'message2' not in warning.getvalue() assert 'message3' in warning.getvalue() - assert app._warncount == 4 + assert app._warncount == 5 app.config.suppress_warnings = ['test.logging'] warning.truncate(0) + logger.warning('message0', type='test') logger.warning('message1', type='test', subtype='logging') logger.warning('message2', type='test', subtype='crash') logger.warning('message3', type='actual', subtype='logging') + assert 'message0' in warning.getvalue() assert 'message1' not in warning.getvalue() assert 'message2' in warning.getvalue() assert 'message3' in warning.getvalue() - assert app._warncount == 6 + assert app._warncount == 8 def test_warningiserror(app, status, warning): |