Add the `intersphinx_resolve_self` option (#13291)

Co-authored-by: Jakob Lykke Andersen <Jakob@caput.dk>
This commit is contained in:
Adam Turner 2025-02-03 17:50:46 +00:00 committed by GitHub
parent 766900e416
commit 758dc81303
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 9 deletions

View File

@ -101,6 +101,9 @@ Features added
* #13105: Introduce the :rst:role:`py:deco` role to cross-reference decorator * #13105: Introduce the :rst:role:`py:deco` role to cross-reference decorator
functions and methods in the Python domain. functions and methods in the Python domain.
Patch by Adam Turner. Patch by Adam Turner.
* #9169: Add the :confval:`intersphinx_resolve_self` option
to resolve an intersphinx reference to the current project.
Patch by Jakob Lykke Andersen and Adam Turner.
Bugs fixed Bugs fixed
---------- ----------

View File

@ -133,6 +133,33 @@ linking:
('../../otherbook/build/html/objects.inv', None)), ('../../otherbook/build/html/objects.inv', None)),
} }
.. confval:: intersphinx_resolve_self
:type: :code-py:`str`
:default: :code-py:`''`
If provided, :confval:`!intersphinx_resolve_self` overrides intersphinx's
resolution mechanism to resolve all references to the current project,
rather than an external reference.
This is useful when documentation is shared between projects,
with the 'upstream' or 'parent' project using intersphinx-style references
in its documentation.
For example, a project such as *Astropy* might set:
.. code-block:: python
intersphinx_resolve_self = 'astropy'
Projects re-using *Astropy*'s documentation or inheriting their docstrings
would then configure their :confval:`!intersphinx_mapping` with
an :code-py:`'astropy'` key, pointing to *astropy*'s :file:`objects.inv`.
For example:
.. code-block:: python
intersphinx_mapping = {
'astropy': ('https://docs.astropy.org/en/stable/', None),
}
.. confval:: intersphinx_cache_limit .. confval:: intersphinx_cache_limit
:type: :code-py:`int` :type: :code-py:`int`
:default: :code-py:`5` (five days) :default: :code-py:`5` (five days)

View File

@ -64,6 +64,7 @@ if TYPE_CHECKING:
def setup(app: Sphinx) -> ExtensionMetadata: def setup(app: Sphinx) -> ExtensionMetadata:
app.add_config_value('intersphinx_mapping', {}, 'env', types=frozenset({dict})) app.add_config_value('intersphinx_mapping', {}, 'env', types=frozenset({dict}))
app.add_config_value('intersphinx_resolve_self', '', 'env', types=frozenset({str}))
app.add_config_value('intersphinx_cache_limit', 5, '', types=frozenset({int})) app.add_config_value('intersphinx_cache_limit', 5, '', types=frozenset({int}))
app.add_config_value( app.add_config_value(
'intersphinx_timeout', None, '', types=frozenset({int, float, type(None)}) 'intersphinx_timeout', None, '', types=frozenset({int, float, type(None)})

View File

@ -364,11 +364,16 @@ class IntersphinxRole(SphinxRole):
def run(self) -> tuple[list[Node], list[system_message]]: def run(self) -> tuple[list[Node], list[system_message]]:
assert self.name == self.orig_name.lower() assert self.name == self.orig_name.lower()
inventory, name_suffix = self.get_inventory_and_name_suffix(self.orig_name) inventory, name_suffix = self.get_inventory_and_name_suffix(self.orig_name)
if inventory and not inventory_exists(self.env, inventory): resolve_self = self.env.config.intersphinx_resolve_self
self._emit_warning( self_referential = bool(resolve_self) and resolve_self == inventory
__('inventory for external cross-reference not found: %r'), inventory
) if not self_referential:
return [], [] if inventory and not inventory_exists(self.env, inventory):
self._emit_warning(
__('inventory for external cross-reference not found: %r'),
inventory,
)
return [], []
domain_name, role_name = self._get_domain_role(name_suffix) domain_name, role_name = self._get_domain_role(name_suffix)
@ -453,10 +458,14 @@ class IntersphinxRole(SphinxRole):
self.content, self.content,
) )
for node in result: if not self_referential:
if isinstance(node, pending_xref): # We do the intersphinx resolution by inserting our
node['intersphinx'] = True # 'intersphinx' and 'inventory' attributes into the nodes.
node['inventory'] = inventory # Only do this when it is an external reference.
for node in result:
if isinstance(node, pending_xref):
node['intersphinx'] = True
node['inventory'] = inventory
return result, messages return result, messages