mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Enable automatic formatting for `sphinx/ext/intersphinx/
` (#12970)
This commit is contained in:
parent
a404f3e66c
commit
3a066f2bbc
@ -468,7 +468,6 @@ exclude = [
|
|||||||
"sphinx/ext/imgconverter.py",
|
"sphinx/ext/imgconverter.py",
|
||||||
"sphinx/ext/imgmath.py",
|
"sphinx/ext/imgmath.py",
|
||||||
"sphinx/ext/inheritance_diagram.py",
|
"sphinx/ext/inheritance_diagram.py",
|
||||||
"sphinx/ext/intersphinx/*",
|
|
||||||
"sphinx/ext/linkcode.py",
|
"sphinx/ext/linkcode.py",
|
||||||
"sphinx/ext/mathjax.py",
|
"sphinx/ext/mathjax.py",
|
||||||
"sphinx/ext/napoleon/__init__.py",
|
"sphinx/ext/napoleon/__init__.py",
|
||||||
|
@ -10,9 +10,11 @@ from sphinx.ext.intersphinx._load import _fetch_inventory
|
|||||||
def inspect_main(argv: list[str], /) -> int:
|
def inspect_main(argv: list[str], /) -> int:
|
||||||
"""Debug functionality to print out an inventory"""
|
"""Debug functionality to print out an inventory"""
|
||||||
if len(argv) < 1:
|
if len(argv) < 1:
|
||||||
print('Print out an inventory file.\n'
|
print(
|
||||||
|
'Print out an inventory file.\n'
|
||||||
'Error: must specify local path or URL to an inventory file.',
|
'Error: must specify local path or URL to an inventory file.',
|
||||||
file=sys.stderr)
|
file=sys.stderr,
|
||||||
|
)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
class MockConfig:
|
class MockConfig:
|
||||||
@ -27,7 +29,7 @@ def inspect_main(argv: list[str], /) -> int:
|
|||||||
target_uri='',
|
target_uri='',
|
||||||
inv_location=filename,
|
inv_location=filename,
|
||||||
config=MockConfig(), # type: ignore[arg-type]
|
config=MockConfig(), # type: ignore[arg-type]
|
||||||
srcdir='' # type: ignore[arg-type]
|
srcdir='', # type: ignore[arg-type]
|
||||||
)
|
)
|
||||||
for key in sorted(inv_data or {}):
|
for key in sorted(inv_data or {}):
|
||||||
print(key)
|
print(key)
|
||||||
|
@ -89,8 +89,10 @@ def validate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
|
|||||||
# ensure target URIs are non-empty and unique
|
# ensure target URIs are non-empty and unique
|
||||||
if not uri or not isinstance(uri, str):
|
if not uri or not isinstance(uri, str):
|
||||||
errors += 1
|
errors += 1
|
||||||
msg = __('Invalid target URI value `%r` in intersphinx_mapping[%r][0]. '
|
msg = __(
|
||||||
'Target URIs must be unique non-empty strings.')
|
'Invalid target URI value `%r` in intersphinx_mapping[%r][0]. '
|
||||||
|
'Target URIs must be unique non-empty strings.'
|
||||||
|
)
|
||||||
LOGGER.error(msg, uri, name)
|
LOGGER.error(msg, uri, name)
|
||||||
del config.intersphinx_mapping[name]
|
del config.intersphinx_mapping[name]
|
||||||
continue
|
continue
|
||||||
@ -105,9 +107,12 @@ def validate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
|
|||||||
continue
|
continue
|
||||||
seen[uri] = name
|
seen[uri] = name
|
||||||
|
|
||||||
|
if not isinstance(inv, tuple | list):
|
||||||
|
inv = (inv,)
|
||||||
|
|
||||||
# ensure inventory locations are None or non-empty
|
# ensure inventory locations are None or non-empty
|
||||||
targets: list[InventoryLocation] = []
|
targets: list[InventoryLocation] = []
|
||||||
for target in (inv if isinstance(inv, (tuple | list)) else (inv,)):
|
for target in inv:
|
||||||
if target is None or target and isinstance(target, str):
|
if target is None or target and isinstance(target, str):
|
||||||
targets.append(target)
|
targets.append(target)
|
||||||
else:
|
else:
|
||||||
@ -143,9 +148,13 @@ def load_mappings(app: Sphinx) -> None:
|
|||||||
projects = []
|
projects = []
|
||||||
for name, (uri, locations) in intersphinx_mapping.values():
|
for name, (uri, locations) in intersphinx_mapping.values():
|
||||||
try:
|
try:
|
||||||
project = _IntersphinxProject(name=name, target_uri=uri, locations=locations)
|
project = _IntersphinxProject(
|
||||||
|
name=name, target_uri=uri, locations=locations
|
||||||
|
)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
msg = __('An invalid intersphinx_mapping entry was added after normalisation.')
|
msg = __(
|
||||||
|
'An invalid intersphinx_mapping entry was added after normalisation.'
|
||||||
|
)
|
||||||
raise ConfigError(msg) from err
|
raise ConfigError(msg) from err
|
||||||
else:
|
else:
|
||||||
projects.append(project)
|
projects.append(project)
|
||||||
@ -223,8 +232,11 @@ def _fetch_inventory_group(
|
|||||||
or project.target_uri not in cache
|
or project.target_uri not in cache
|
||||||
or cache[project.target_uri][1] < cache_time
|
or cache[project.target_uri][1] < cache_time
|
||||||
):
|
):
|
||||||
LOGGER.info(__("loading intersphinx inventory '%s' from %s ..."),
|
LOGGER.info(
|
||||||
project.name, _get_safe_url(inv))
|
__("loading intersphinx inventory '%s' from %s ..."),
|
||||||
|
project.name,
|
||||||
|
_get_safe_url(inv),
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
invdata = _fetch_inventory(
|
invdata = _fetch_inventory(
|
||||||
@ -245,14 +257,21 @@ def _fetch_inventory_group(
|
|||||||
if not failures:
|
if not failures:
|
||||||
pass
|
pass
|
||||||
elif len(failures) < len(project.locations):
|
elif len(failures) < len(project.locations):
|
||||||
LOGGER.info(__('encountered some issues with some of the inventories,'
|
LOGGER.info(
|
||||||
' but they had working alternatives:'))
|
__(
|
||||||
|
'encountered some issues with some of the inventories,'
|
||||||
|
' but they had working alternatives:'
|
||||||
|
)
|
||||||
|
)
|
||||||
for fail in failures:
|
for fail in failures:
|
||||||
LOGGER.info(*fail)
|
LOGGER.info(*fail)
|
||||||
else:
|
else:
|
||||||
issues = '\n'.join(f[0] % f[1:] for f in failures)
|
issues = '\n'.join(f[0] % f[1:] for f in failures)
|
||||||
LOGGER.warning(__('failed to reach any of the inventories '
|
LOGGER.warning(
|
||||||
'with the following issues:') + '\n' + issues)
|
__('failed to reach any of the inventories ' 'with the following issues:')
|
||||||
|
+ '\n'
|
||||||
|
+ issues
|
||||||
|
)
|
||||||
return updated
|
return updated
|
||||||
|
|
||||||
|
|
||||||
@ -267,7 +286,7 @@ def fetch_inventory(app: Sphinx, uri: InventoryURI, inv: str) -> Inventory:
|
|||||||
|
|
||||||
|
|
||||||
def _fetch_inventory(
|
def _fetch_inventory(
|
||||||
*, target_uri: InventoryURI, inv_location: str, config: Config, srcdir: Path,
|
*, target_uri: InventoryURI, inv_location: str, config: Config, srcdir: Path
|
||||||
) -> Inventory:
|
) -> Inventory:
|
||||||
"""Fetch, parse and return an intersphinx inventory file."""
|
"""Fetch, parse and return an intersphinx inventory file."""
|
||||||
# both *target_uri* (base URI of the links to generate)
|
# both *target_uri* (base URI of the links to generate)
|
||||||
@ -282,8 +301,12 @@ def _fetch_inventory(
|
|||||||
else:
|
else:
|
||||||
f = open(path.join(srcdir, inv_location), 'rb') # NoQA: SIM115
|
f = open(path.join(srcdir, inv_location), 'rb') # NoQA: SIM115
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
err.args = ('intersphinx inventory %r not fetchable due to %s: %s',
|
err.args = (
|
||||||
inv_location, err.__class__, str(err))
|
'intersphinx inventory %r not fetchable due to %s: %s',
|
||||||
|
inv_location,
|
||||||
|
err.__class__,
|
||||||
|
str(err),
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
try:
|
try:
|
||||||
if hasattr(f, 'url'):
|
if hasattr(f, 'url'):
|
||||||
@ -295,17 +318,22 @@ def _fetch_inventory(
|
|||||||
if target_uri in {
|
if target_uri in {
|
||||||
inv_location,
|
inv_location,
|
||||||
path.dirname(inv_location),
|
path.dirname(inv_location),
|
||||||
path.dirname(inv_location) + '/'
|
path.dirname(inv_location) + '/',
|
||||||
}:
|
}:
|
||||||
target_uri = path.dirname(new_inv_location)
|
target_uri = path.dirname(new_inv_location)
|
||||||
with f:
|
with f:
|
||||||
try:
|
try:
|
||||||
invdata = InventoryFile.load(f, target_uri, posixpath.join)
|
invdata = InventoryFile.load(f, target_uri, posixpath.join)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
raise ValueError('unknown or unsupported inventory version: %r' % exc) from exc
|
msg = f'unknown or unsupported inventory version: {exc!r}'
|
||||||
|
raise ValueError(msg) from exc
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
err.args = ('intersphinx inventory %r not readable due to %s: %s',
|
err.args = (
|
||||||
inv_location, err.__class__.__name__, str(err))
|
'intersphinx inventory %r not readable due to %s: %s',
|
||||||
|
inv_location,
|
||||||
|
err.__class__.__name__,
|
||||||
|
str(err),
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
return invdata
|
return invdata
|
||||||
@ -373,9 +401,13 @@ def _read_from_url(url: str, *, config: Config) -> HTTPResponse:
|
|||||||
:return: data read from resource described by *url*
|
:return: data read from resource described by *url*
|
||||||
:rtype: ``file``-like object
|
:rtype: ``file``-like object
|
||||||
"""
|
"""
|
||||||
r = requests.get(url, stream=True, timeout=config.intersphinx_timeout,
|
r = requests.get(
|
||||||
|
url,
|
||||||
|
stream=True,
|
||||||
|
timeout=config.intersphinx_timeout,
|
||||||
_user_agent=config.user_agent,
|
_user_agent=config.user_agent,
|
||||||
_tls_info=(config.tls_verify, config.tls_cacerts))
|
_tls_info=(config.tls_verify, config.tls_cacerts),
|
||||||
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
# For inv_location / new_inv_location
|
# For inv_location / new_inv_location
|
||||||
|
@ -32,9 +32,13 @@ if TYPE_CHECKING:
|
|||||||
from sphinx.util.typing import Inventory, InventoryItem, RoleFunction
|
from sphinx.util.typing import Inventory, InventoryItem, RoleFunction
|
||||||
|
|
||||||
|
|
||||||
def _create_element_from_result(domain: Domain, inv_name: InventoryName | None,
|
def _create_element_from_result(
|
||||||
|
domain: Domain,
|
||||||
|
inv_name: InventoryName | None,
|
||||||
data: InventoryItem,
|
data: InventoryItem,
|
||||||
node: pending_xref, contnode: TextElement) -> nodes.reference:
|
node: pending_xref,
|
||||||
|
contnode: TextElement,
|
||||||
|
) -> nodes.reference:
|
||||||
proj, version, uri, dispname = data
|
proj, version, uri, dispname = data
|
||||||
if '://' not in uri and node.get('refdoc'):
|
if '://' not in uri and node.get('refdoc'):
|
||||||
# get correct path in case of subdirectories
|
# get correct path in case of subdirectories
|
||||||
@ -51,8 +55,11 @@ def _create_element_from_result(domain: Domain, inv_name: InventoryName | None,
|
|||||||
# use whatever title was given, but strip prefix
|
# use whatever title was given, but strip prefix
|
||||||
title = contnode.astext()
|
title = contnode.astext()
|
||||||
if inv_name is not None and title.startswith(inv_name + ':'):
|
if inv_name is not None and title.startswith(inv_name + ':'):
|
||||||
newnode.append(contnode.__class__(title[len(inv_name) + 1:],
|
newnode.append(
|
||||||
title[len(inv_name) + 1:]))
|
contnode.__class__(
|
||||||
|
title[len(inv_name) + 1 :], title[len(inv_name) + 1 :]
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
newnode.append(contnode)
|
newnode.append(contnode)
|
||||||
else:
|
else:
|
||||||
@ -62,10 +69,14 @@ def _create_element_from_result(domain: Domain, inv_name: InventoryName | None,
|
|||||||
|
|
||||||
|
|
||||||
def _resolve_reference_in_domain_by_target(
|
def _resolve_reference_in_domain_by_target(
|
||||||
inv_name: InventoryName | None, inventory: Inventory,
|
inv_name: InventoryName | None,
|
||||||
domain: Domain, objtypes: Iterable[str],
|
inventory: Inventory,
|
||||||
|
domain: Domain,
|
||||||
|
objtypes: Iterable[str],
|
||||||
target: str,
|
target: str,
|
||||||
node: pending_xref, contnode: TextElement) -> nodes.reference | None:
|
node: pending_xref,
|
||||||
|
contnode: TextElement,
|
||||||
|
) -> nodes.reference | None:
|
||||||
for objtype in objtypes:
|
for objtype in objtypes:
|
||||||
if objtype not in inventory:
|
if objtype not in inventory:
|
||||||
# Continue if there's nothing of this kind in the inventory
|
# Continue if there's nothing of this kind in the inventory
|
||||||
@ -79,19 +90,34 @@ def _resolve_reference_in_domain_by_target(
|
|||||||
# * 'term': https://github.com/sphinx-doc/sphinx/issues/9291
|
# * 'term': https://github.com/sphinx-doc/sphinx/issues/9291
|
||||||
# * 'label': https://github.com/sphinx-doc/sphinx/issues/12008
|
# * 'label': https://github.com/sphinx-doc/sphinx/issues/12008
|
||||||
target_lower = target.lower()
|
target_lower = target.lower()
|
||||||
insensitive_matches = list(filter(lambda k: k.lower() == target_lower,
|
insensitive_matches = list(
|
||||||
inventory[objtype].keys()))
|
filter(lambda k: k.lower() == target_lower, inventory[objtype].keys())
|
||||||
|
)
|
||||||
if len(insensitive_matches) > 1:
|
if len(insensitive_matches) > 1:
|
||||||
data_items = {inventory[objtype][match] for match in insensitive_matches}
|
data_items = {
|
||||||
|
inventory[objtype][match] for match in insensitive_matches
|
||||||
|
}
|
||||||
inv_descriptor = inv_name or 'main_inventory'
|
inv_descriptor = inv_name or 'main_inventory'
|
||||||
if len(data_items) == 1: # these are duplicates; relatively innocuous
|
if len(data_items) == 1: # these are duplicates; relatively innocuous
|
||||||
LOGGER.debug(__("inventory '%s': duplicate matches found for %s:%s"),
|
LOGGER.debug(
|
||||||
inv_descriptor, objtype, target,
|
__("inventory '%s': duplicate matches found for %s:%s"),
|
||||||
type='intersphinx', subtype='external', location=node)
|
inv_descriptor,
|
||||||
|
objtype,
|
||||||
|
target,
|
||||||
|
type='intersphinx',
|
||||||
|
subtype='external',
|
||||||
|
location=node,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
LOGGER.warning(__("inventory '%s': multiple matches found for %s:%s"),
|
LOGGER.warning(
|
||||||
inv_descriptor, objtype, target,
|
__("inventory '%s': multiple matches found for %s:%s"),
|
||||||
type='intersphinx', subtype='external', location=node)
|
inv_descriptor,
|
||||||
|
objtype,
|
||||||
|
target,
|
||||||
|
type='intersphinx',
|
||||||
|
subtype='external',
|
||||||
|
location=node,
|
||||||
|
)
|
||||||
if insensitive_matches:
|
if insensitive_matches:
|
||||||
data = inventory[objtype][insensitive_matches[0]]
|
data = inventory[objtype][insensitive_matches[0]]
|
||||||
else:
|
else:
|
||||||
@ -106,11 +132,15 @@ def _resolve_reference_in_domain_by_target(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _resolve_reference_in_domain(env: BuildEnvironment,
|
def _resolve_reference_in_domain(
|
||||||
inv_name: InventoryName | None, inventory: Inventory,
|
env: BuildEnvironment,
|
||||||
|
inv_name: InventoryName | None,
|
||||||
|
inventory: Inventory,
|
||||||
honor_disabled_refs: bool,
|
honor_disabled_refs: bool,
|
||||||
domain: Domain, objtypes: Iterable[str],
|
domain: Domain,
|
||||||
node: pending_xref, contnode: TextElement,
|
objtypes: Iterable[str],
|
||||||
|
node: pending_xref,
|
||||||
|
contnode: TextElement,
|
||||||
) -> nodes.reference | None:
|
) -> nodes.reference | None:
|
||||||
obj_types: dict[str, None] = {}.fromkeys(objtypes)
|
obj_types: dict[str, None] = {}.fromkeys(objtypes)
|
||||||
|
|
||||||
@ -129,15 +159,16 @@ def _resolve_reference_in_domain(env: BuildEnvironment,
|
|||||||
# now that the objtypes list is complete we can remove the disabled ones
|
# now that the objtypes list is complete we can remove the disabled ones
|
||||||
if honor_disabled_refs:
|
if honor_disabled_refs:
|
||||||
disabled = set(env.config.intersphinx_disabled_reftypes)
|
disabled = set(env.config.intersphinx_disabled_reftypes)
|
||||||
obj_types = {obj_type: None
|
obj_types = {
|
||||||
for obj_type in obj_types
|
obj_type: None for obj_type in obj_types if obj_type not in disabled
|
||||||
if obj_type not in disabled}
|
}
|
||||||
|
|
||||||
objtypes = [*obj_types.keys()]
|
objtypes = [*obj_types.keys()]
|
||||||
|
|
||||||
# without qualification
|
# without qualification
|
||||||
res = _resolve_reference_in_domain_by_target(inv_name, inventory, domain, objtypes,
|
res = _resolve_reference_in_domain_by_target(
|
||||||
node['reftarget'], node, contnode)
|
inv_name, inventory, domain, objtypes, node['reftarget'], node, contnode
|
||||||
|
)
|
||||||
if res is not None:
|
if res is not None:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@ -145,14 +176,19 @@ def _resolve_reference_in_domain(env: BuildEnvironment,
|
|||||||
full_qualified_name = domain.get_full_qualified_name(node)
|
full_qualified_name = domain.get_full_qualified_name(node)
|
||||||
if full_qualified_name is None:
|
if full_qualified_name is None:
|
||||||
return None
|
return None
|
||||||
return _resolve_reference_in_domain_by_target(inv_name, inventory, domain, objtypes,
|
return _resolve_reference_in_domain_by_target(
|
||||||
full_qualified_name, node, contnode)
|
inv_name, inventory, domain, objtypes, full_qualified_name, node, contnode
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _resolve_reference(env: BuildEnvironment,
|
def _resolve_reference(
|
||||||
inv_name: InventoryName | None, inventory: Inventory,
|
env: BuildEnvironment,
|
||||||
|
inv_name: InventoryName | None,
|
||||||
|
inventory: Inventory,
|
||||||
honor_disabled_refs: bool,
|
honor_disabled_refs: bool,
|
||||||
node: pending_xref, contnode: TextElement) -> nodes.reference | None:
|
node: pending_xref,
|
||||||
|
contnode: TextElement,
|
||||||
|
) -> nodes.reference | None:
|
||||||
# disabling should only be done if no inventory is given
|
# disabling should only be done if no inventory is given
|
||||||
honor_disabled_refs = honor_disabled_refs and inv_name is None
|
honor_disabled_refs = honor_disabled_refs and inv_name is None
|
||||||
intersphinx_disabled_reftypes = env.config.intersphinx_disabled_reftypes
|
intersphinx_disabled_reftypes = env.config.intersphinx_disabled_reftypes
|
||||||
@ -163,13 +199,22 @@ def _resolve_reference(env: BuildEnvironment,
|
|||||||
typ = node['reftype']
|
typ = node['reftype']
|
||||||
if typ == 'any':
|
if typ == 'any':
|
||||||
for domain in env.domains.sorted():
|
for domain in env.domains.sorted():
|
||||||
if honor_disabled_refs and f'{domain.name}:*' in intersphinx_disabled_reftypes:
|
if (
|
||||||
|
honor_disabled_refs
|
||||||
|
and f'{domain.name}:*' in intersphinx_disabled_reftypes
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
objtypes: Iterable[str] = domain.object_types.keys()
|
objtypes: Iterable[str] = domain.object_types.keys()
|
||||||
res = _resolve_reference_in_domain(env, inv_name, inventory,
|
res = _resolve_reference_in_domain(
|
||||||
|
env,
|
||||||
|
inv_name,
|
||||||
|
inventory,
|
||||||
honor_disabled_refs,
|
honor_disabled_refs,
|
||||||
domain, objtypes,
|
domain,
|
||||||
node, contnode)
|
objtypes,
|
||||||
|
node,
|
||||||
|
contnode,
|
||||||
|
)
|
||||||
if res is not None:
|
if res is not None:
|
||||||
return res
|
return res
|
||||||
return None
|
return None
|
||||||
@ -184,19 +229,27 @@ def _resolve_reference(env: BuildEnvironment,
|
|||||||
objtypes = domain.objtypes_for_role(typ) or ()
|
objtypes = domain.objtypes_for_role(typ) or ()
|
||||||
if not objtypes:
|
if not objtypes:
|
||||||
return None
|
return None
|
||||||
return _resolve_reference_in_domain(env, inv_name, inventory,
|
return _resolve_reference_in_domain(
|
||||||
|
env,
|
||||||
|
inv_name,
|
||||||
|
inventory,
|
||||||
honor_disabled_refs,
|
honor_disabled_refs,
|
||||||
domain, objtypes,
|
domain,
|
||||||
node, contnode)
|
objtypes,
|
||||||
|
node,
|
||||||
|
contnode,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def inventory_exists(env: BuildEnvironment, inv_name: InventoryName) -> bool:
|
def inventory_exists(env: BuildEnvironment, inv_name: InventoryName) -> bool:
|
||||||
return inv_name in InventoryAdapter(env).named_inventory
|
return inv_name in InventoryAdapter(env).named_inventory
|
||||||
|
|
||||||
|
|
||||||
def resolve_reference_in_inventory(env: BuildEnvironment,
|
def resolve_reference_in_inventory(
|
||||||
|
env: BuildEnvironment,
|
||||||
inv_name: InventoryName,
|
inv_name: InventoryName,
|
||||||
node: pending_xref, contnode: TextElement,
|
node: pending_xref,
|
||||||
|
contnode: TextElement,
|
||||||
) -> nodes.reference | None:
|
) -> nodes.reference | None:
|
||||||
"""Attempt to resolve a missing reference via intersphinx references.
|
"""Attempt to resolve a missing reference via intersphinx references.
|
||||||
|
|
||||||
@ -205,25 +258,38 @@ def resolve_reference_in_inventory(env: BuildEnvironment,
|
|||||||
Requires ``inventory_exists(env, inv_name)``.
|
Requires ``inventory_exists(env, inv_name)``.
|
||||||
"""
|
"""
|
||||||
assert inventory_exists(env, inv_name)
|
assert inventory_exists(env, inv_name)
|
||||||
return _resolve_reference(env, inv_name, InventoryAdapter(env).named_inventory[inv_name],
|
return _resolve_reference(
|
||||||
False, node, contnode)
|
env,
|
||||||
|
inv_name,
|
||||||
|
InventoryAdapter(env).named_inventory[inv_name],
|
||||||
|
False,
|
||||||
|
node,
|
||||||
|
contnode,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def resolve_reference_any_inventory(env: BuildEnvironment,
|
def resolve_reference_any_inventory(
|
||||||
|
env: BuildEnvironment,
|
||||||
honor_disabled_refs: bool,
|
honor_disabled_refs: bool,
|
||||||
node: pending_xref, contnode: TextElement,
|
node: pending_xref,
|
||||||
|
contnode: TextElement,
|
||||||
) -> nodes.reference | None:
|
) -> nodes.reference | None:
|
||||||
"""Attempt to resolve a missing reference via intersphinx references.
|
"""Attempt to resolve a missing reference via intersphinx references.
|
||||||
|
|
||||||
Resolution is tried with the target as is in any inventory.
|
Resolution is tried with the target as is in any inventory.
|
||||||
"""
|
"""
|
||||||
return _resolve_reference(env, None, InventoryAdapter(env).main_inventory,
|
return _resolve_reference(
|
||||||
|
env,
|
||||||
|
None,
|
||||||
|
InventoryAdapter(env).main_inventory,
|
||||||
honor_disabled_refs,
|
honor_disabled_refs,
|
||||||
node, contnode)
|
node,
|
||||||
|
contnode,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def resolve_reference_detect_inventory(env: BuildEnvironment,
|
def resolve_reference_detect_inventory(
|
||||||
node: pending_xref, contnode: TextElement,
|
env: BuildEnvironment, node: pending_xref, contnode: TextElement
|
||||||
) -> nodes.reference | None:
|
) -> nodes.reference | None:
|
||||||
"""Attempt to resolve a missing reference via intersphinx references.
|
"""Attempt to resolve a missing reference via intersphinx references.
|
||||||
|
|
||||||
@ -250,8 +316,9 @@ def resolve_reference_detect_inventory(env: BuildEnvironment,
|
|||||||
return res_inv
|
return res_inv
|
||||||
|
|
||||||
|
|
||||||
def missing_reference(app: Sphinx, env: BuildEnvironment, node: pending_xref,
|
def missing_reference(
|
||||||
contnode: TextElement) -> nodes.reference | None:
|
app: Sphinx, env: BuildEnvironment, node: pending_xref, contnode: TextElement
|
||||||
|
) -> nodes.reference | None:
|
||||||
"""Attempt to resolve a missing reference via intersphinx references."""
|
"""Attempt to resolve a missing reference via intersphinx references."""
|
||||||
return resolve_reference_detect_inventory(env, node, contnode)
|
return resolve_reference_detect_inventory(env, node, contnode)
|
||||||
|
|
||||||
@ -263,7 +330,11 @@ class IntersphinxDispatcher(CustomReSTDispatcher):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def role(
|
def role(
|
||||||
self, role_name: str, language_module: ModuleType, lineno: int, reporter: Reporter,
|
self,
|
||||||
|
role_name: str,
|
||||||
|
language_module: ModuleType,
|
||||||
|
lineno: int,
|
||||||
|
reporter: Reporter,
|
||||||
) -> tuple[RoleFunction, list[system_message]]:
|
) -> tuple[RoleFunction, list[system_message]]:
|
||||||
if len(role_name) > 9 and role_name.startswith(('external:', 'external+')):
|
if len(role_name) > 9 and role_name.startswith(('external:', 'external+')):
|
||||||
return IntersphinxRole(role_name), []
|
return IntersphinxRole(role_name), []
|
||||||
@ -461,7 +532,9 @@ class IntersphinxRole(SphinxRole):
|
|||||||
except ExtensionError:
|
except ExtensionError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def invoke_role(self, role: tuple[str, str]) -> tuple[list[Node], list[system_message]]:
|
def invoke_role(
|
||||||
|
self, role: tuple[str, str]
|
||||||
|
) -> tuple[list[Node], list[system_message]]:
|
||||||
"""Invoke the role described by a ``(domain, role name)`` pair."""
|
"""Invoke the role described by a ``(domain, role name)`` pair."""
|
||||||
_deprecation_warning(
|
_deprecation_warning(
|
||||||
__name__, f'{self.__class__.__name__}.invoke_role', '', remove=(9, 0)
|
__name__, f'{self.__class__.__name__}.invoke_role', '', remove=(9, 0)
|
||||||
@ -471,8 +544,15 @@ class IntersphinxRole(SphinxRole):
|
|||||||
role_func = domain.role(role[1])
|
role_func = domain.role(role[1])
|
||||||
assert role_func is not None
|
assert role_func is not None
|
||||||
|
|
||||||
return role_func(':'.join(role), self.rawtext, self.text, self.lineno,
|
return role_func(
|
||||||
self.inliner, self.options, self.content)
|
':'.join(role),
|
||||||
|
self.rawtext,
|
||||||
|
self.text,
|
||||||
|
self.lineno,
|
||||||
|
self.inliner,
|
||||||
|
self.options,
|
||||||
|
self.content,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return [], []
|
return [], []
|
||||||
|
|
||||||
@ -493,13 +573,20 @@ class IntersphinxRoleResolver(ReferencesResolver):
|
|||||||
inv_name = node['inventory']
|
inv_name = node['inventory']
|
||||||
if inv_name is not None:
|
if inv_name is not None:
|
||||||
assert inventory_exists(self.env, inv_name)
|
assert inventory_exists(self.env, inv_name)
|
||||||
newnode = resolve_reference_in_inventory(self.env, inv_name, node, contnode)
|
newnode = resolve_reference_in_inventory(
|
||||||
|
self.env, inv_name, node, contnode
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
newnode = resolve_reference_any_inventory(self.env, False, node, contnode)
|
newnode = resolve_reference_any_inventory(
|
||||||
|
self.env, False, node, contnode
|
||||||
|
)
|
||||||
if newnode is None:
|
if newnode is None:
|
||||||
typ = node['reftype']
|
typ = node['reftype']
|
||||||
msg = (__('external %s:%s reference target not found: %s') %
|
msg = __('external %s:%s reference target not found: %s') % (
|
||||||
(node['refdomain'], typ, node['reftarget']))
|
node['refdomain'],
|
||||||
|
typ,
|
||||||
|
node['reftarget'],
|
||||||
|
)
|
||||||
LOGGER.warning(msg, location=node, type='ref', subtype=typ)
|
LOGGER.warning(msg, location=node, type='ref', subtype=typ)
|
||||||
node.replace_self(contnode)
|
node.replace_self(contnode)
|
||||||
else:
|
else:
|
||||||
|
@ -54,7 +54,7 @@ class _IntersphinxProject:
|
|||||||
'locations': 'A tuple of local or remote targets containing '
|
'locations': 'A tuple of local or remote targets containing '
|
||||||
'the inventory data to fetch. '
|
'the inventory data to fetch. '
|
||||||
'None indicates the default inventory file name.',
|
'None indicates the default inventory file name.',
|
||||||
}
|
} # fmt: skip
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -83,10 +83,12 @@ class _IntersphinxProject:
|
|||||||
object.__setattr__(self, 'locations', tuple(locations))
|
object.__setattr__(self, 'locations', tuple(locations))
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (f'{self.__class__.__name__}('
|
return (
|
||||||
|
f'{self.__class__.__name__}('
|
||||||
f'name={self.name!r}, '
|
f'name={self.name!r}, '
|
||||||
f'target_uri={self.target_uri!r}, '
|
f'target_uri={self.target_uri!r}, '
|
||||||
f'locations={self.locations!r})')
|
f'locations={self.locations!r})'
|
||||||
|
)
|
||||||
|
|
||||||
def __eq__(self, other: object) -> bool:
|
def __eq__(self, other: object) -> bool:
|
||||||
if not isinstance(other, _IntersphinxProject):
|
if not isinstance(other, _IntersphinxProject):
|
||||||
|
Loading…
Reference in New Issue
Block a user