mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Improve static typing in `intersphinx
` et al
This commit is contained in:
parent
ae9008b128
commit
3d2114214b
@ -29,26 +29,32 @@ from typing import IO, TYPE_CHECKING, Any, cast
|
||||
from urllib.parse import urlsplit, urlunsplit
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Element, Node, TextElement, system_message
|
||||
from docutils.utils import Reporter, relative_path
|
||||
from docutils.utils import relative_path
|
||||
|
||||
import sphinx
|
||||
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.errors import ExtensionError
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.transforms.post_transforms import ReferencesResolver
|
||||
from sphinx.util import logging, requests
|
||||
from sphinx.util.docutils import CustomReSTDispatcher, SphinxRole
|
||||
from sphinx.util.inventory import InventoryFile
|
||||
from sphinx.util.typing import Inventory, InventoryItem, RoleFunction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from types import ModuleType
|
||||
from typing import Tuple, Union
|
||||
|
||||
from docutils.nodes import Node, TextElement, system_message
|
||||
from docutils.utils import Reporter
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.config import Config
|
||||
from sphinx.domains import Domain
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.util.typing import Inventory, InventoryItem, RoleFunction
|
||||
|
||||
InventoryCacheEntry = Tuple[Union[str, None], int, Inventory]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -60,12 +66,22 @@ class InventoryAdapter:
|
||||
self.env = env
|
||||
|
||||
if not hasattr(env, 'intersphinx_cache'):
|
||||
# initial storage when fetching inventories before processing
|
||||
self.env.intersphinx_cache = {} # type: ignore
|
||||
|
||||
self.env.intersphinx_inventory = {} # type: ignore
|
||||
self.env.intersphinx_named_inventory = {} # type: ignore
|
||||
|
||||
@property
|
||||
def cache(self) -> dict[str, tuple[str, int, Inventory]]:
|
||||
def cache(self) -> dict[str, InventoryCacheEntry]:
|
||||
"""Intersphinx cache.
|
||||
|
||||
- Key is the URI of the remote inventory
|
||||
- Element one is the key given in the Sphinx intersphinx_mapping
|
||||
configuration value
|
||||
- Element two is a time value for cache invalidation, a float
|
||||
- Element three is the loaded remote inventory, type Inventory
|
||||
"""
|
||||
return self.env.intersphinx_cache # type: ignore
|
||||
|
||||
@property
|
||||
@ -152,7 +168,7 @@ def _get_safe_url(url: str) -> str:
|
||||
return urlunsplit(frags)
|
||||
|
||||
|
||||
def fetch_inventory(app: Sphinx, uri: str, inv: Any) -> Any:
|
||||
def fetch_inventory(app: Sphinx, uri: str, inv: str) -> Inventory:
|
||||
"""Fetch, parse and return an intersphinx inventory file."""
|
||||
# both *uri* (base URI of the links to generate) and *inv* (actual
|
||||
# location of the inventory file) can be local or remote URIs
|
||||
@ -192,7 +208,12 @@ def fetch_inventory(app: Sphinx, uri: str, inv: Any) -> Any:
|
||||
|
||||
|
||||
def fetch_inventory_group(
|
||||
name: str, uri: str, invs: Any, cache: Any, app: Any, now: float,
|
||||
name: str | None,
|
||||
uri: str,
|
||||
invs: tuple[str | None, ...],
|
||||
cache: dict[str, InventoryCacheEntry],
|
||||
app: Sphinx,
|
||||
now: int,
|
||||
) -> bool:
|
||||
cache_time = now - app.config.intersphinx_cache_limit * 86400
|
||||
failures = []
|
||||
@ -211,7 +232,7 @@ def fetch_inventory_group(
|
||||
failures.append(err.args)
|
||||
continue
|
||||
if invdata:
|
||||
cache[uri] = (name, now, invdata)
|
||||
cache[uri] = name, now, invdata
|
||||
return True
|
||||
return False
|
||||
finally:
|
||||
@ -235,6 +256,9 @@ def load_mappings(app: Sphinx) -> None:
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor() as pool:
|
||||
futures = []
|
||||
name: str | None
|
||||
uri: str
|
||||
invs: tuple[str | None, ...]
|
||||
for name, (uri, invs) in app.config.intersphinx_mapping.values():
|
||||
futures.append(pool.submit(
|
||||
fetch_inventory_group, name, uri, invs, inventories.cache, app, now,
|
||||
@ -263,7 +287,7 @@ def load_mappings(app: Sphinx) -> None:
|
||||
|
||||
def _create_element_from_result(domain: Domain, inv_name: str | None,
|
||||
data: InventoryItem,
|
||||
node: pending_xref, contnode: TextElement) -> Element:
|
||||
node: pending_xref, contnode: TextElement) -> nodes.reference:
|
||||
proj, version, uri, dispname = data
|
||||
if '://' not in uri and node.get('refdoc'):
|
||||
# get correct path in case of subdirectories
|
||||
@ -295,7 +319,7 @@ def _resolve_reference_in_domain_by_target(
|
||||
inv_name: str | None, inventory: Inventory,
|
||||
domain: Domain, objtypes: list[str],
|
||||
target: str,
|
||||
node: pending_xref, contnode: TextElement) -> Element | None:
|
||||
node: pending_xref, contnode: TextElement) -> nodes.reference | None:
|
||||
for objtype in objtypes:
|
||||
if objtype not in inventory:
|
||||
# Continue if there's nothing of this kind in the inventory
|
||||
@ -328,7 +352,7 @@ def _resolve_reference_in_domain(env: BuildEnvironment,
|
||||
honor_disabled_refs: bool,
|
||||
domain: Domain, objtypes: list[str],
|
||||
node: pending_xref, contnode: TextElement,
|
||||
) -> Element | None:
|
||||
) -> nodes.reference | None:
|
||||
# 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
|
||||
@ -361,7 +385,7 @@ def _resolve_reference_in_domain(env: BuildEnvironment,
|
||||
|
||||
def _resolve_reference(env: BuildEnvironment, inv_name: str | None, inventory: Inventory,
|
||||
honor_disabled_refs: bool,
|
||||
node: pending_xref, contnode: TextElement) -> Element | None:
|
||||
node: pending_xref, contnode: TextElement) -> nodes.reference | None:
|
||||
# disabling should only be done if no inventory is given
|
||||
honor_disabled_refs = honor_disabled_refs and inv_name is None
|
||||
|
||||
@ -407,7 +431,7 @@ def inventory_exists(env: BuildEnvironment, inv_name: str) -> bool:
|
||||
def resolve_reference_in_inventory(env: BuildEnvironment,
|
||||
inv_name: str,
|
||||
node: pending_xref, contnode: TextElement,
|
||||
) -> Element | None:
|
||||
) -> nodes.reference | None:
|
||||
"""Attempt to resolve a missing reference via intersphinx references.
|
||||
|
||||
Resolution is tried in the given inventory with the target as is.
|
||||
@ -422,7 +446,7 @@ def resolve_reference_in_inventory(env: BuildEnvironment,
|
||||
def resolve_reference_any_inventory(env: BuildEnvironment,
|
||||
honor_disabled_refs: bool,
|
||||
node: pending_xref, contnode: TextElement,
|
||||
) -> Element | None:
|
||||
) -> nodes.reference | None:
|
||||
"""Attempt to resolve a missing reference via intersphinx references.
|
||||
|
||||
Resolution is tried with the target as is in any inventory.
|
||||
@ -434,7 +458,7 @@ def resolve_reference_any_inventory(env: BuildEnvironment,
|
||||
|
||||
def resolve_reference_detect_inventory(env: BuildEnvironment,
|
||||
node: pending_xref, contnode: TextElement,
|
||||
) -> Element | None:
|
||||
) -> nodes.reference | None:
|
||||
"""Attempt to resolve a missing reference via intersphinx references.
|
||||
|
||||
Resolution is tried first with the target as is in any inventory.
|
||||
@ -462,7 +486,7 @@ def resolve_reference_detect_inventory(env: BuildEnvironment,
|
||||
|
||||
|
||||
def missing_reference(app: Sphinx, env: BuildEnvironment, node: pending_xref,
|
||||
contnode: TextElement) -> Element | None:
|
||||
contnode: TextElement) -> nodes.reference | None:
|
||||
"""Attempt to resolve a missing reference via intersphinx references."""
|
||||
|
||||
return resolve_reference_detect_inventory(env, node, contnode)
|
||||
|
@ -7,7 +7,7 @@ import zlib
|
||||
from typing import IO, TYPE_CHECKING, Callable, Iterator
|
||||
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.typing import Inventory
|
||||
from sphinx.util.typing import Inventory, InventoryItem
|
||||
|
||||
BUFSIZE = 16 * 1024
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -133,8 +133,8 @@ class InventoryFile:
|
||||
if location.endswith('$'):
|
||||
location = location[:-1] + name
|
||||
location = join(uri, location)
|
||||
invdata.setdefault(type, {})[name] = (projname, version,
|
||||
location, dispname)
|
||||
inv_item: InventoryItem = projname, version, location, dispname
|
||||
invdata.setdefault(type, {})[name] = inv_item
|
||||
return invdata
|
||||
|
||||
@classmethod
|
||||
|
@ -51,7 +51,12 @@ OptionSpec = Dict[str, Callable[[str], Any]]
|
||||
TitleGetter = Callable[[nodes.Node], str]
|
||||
|
||||
# inventory data on memory
|
||||
InventoryItem = Tuple[str, str, str, str]
|
||||
InventoryItem = Tuple[
|
||||
str, # project name
|
||||
str, # project version
|
||||
str, # URL
|
||||
str, # display name
|
||||
]
|
||||
Inventory = Dict[str, Dict[str, InventoryItem]]
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@ import posixpath
|
||||
import zlib
|
||||
from io import BytesIO
|
||||
|
||||
from sphinx.ext.intersphinx import InventoryFile
|
||||
from sphinx.util.inventory import InventoryFile
|
||||
|
||||
inventory_v1 = b'''\
|
||||
# Sphinx inventory version 1
|
||||
|
Loading…
Reference in New Issue
Block a user