summaryrefslogtreecommitdiff
path: root/sphinx
diff options
context:
space:
mode:
authorAdam Turner <9087854+aa-turner@users.noreply.github.com>2023-03-17 17:39:44 +0000
committerAdam Turner <9087854+aa-turner@users.noreply.github.com>2023-03-17 17:43:23 +0000
commit3d2114214b512a6cce7eabbfd8d4fb3ac8c448f3 (patch)
tree90d5454ce8a6ea979c05783cce71254a4f050fd7 /sphinx
parentae9008b1282278ae9ab7e53fa0d87e1a7be19e12 (diff)
downloadsphinx-git-3d2114214b512a6cce7eabbfd8d4fb3ac8c448f3.tar.gz
Improve static typing in ``intersphinx`` et al
Diffstat (limited to 'sphinx')
-rw-r--r--sphinx/ext/intersphinx.py62
-rw-r--r--sphinx/util/inventory.py6
-rw-r--r--sphinx/util/typing.py7
3 files changed, 52 insertions, 23 deletions
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index f6e6d7964..95410c0c4 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -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)
diff --git a/sphinx/util/inventory.py b/sphinx/util/inventory.py
index a879a17dd..123a86d25 100644
--- a/sphinx/util/inventory.py
+++ b/sphinx/util/inventory.py
@@ -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
diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py
index 3f2acb822..d4e87ef1d 100644
--- a/sphinx/util/typing.py
+++ b/sphinx/util/typing.py
@@ -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]]