Automatic links from code examples to reference documentation.
System for resolving code names and imports to their documentation locations using Sphinx inventory data and intersphinx references. This component maps parsed code names to their actual documentation URLs, enabling the generation of clickable links.
Primary functions for resolving name chains to documentation locations.
def resolve_location(chain: Name, inventory: dict) -> str:
"""
Resolve a name chain to its final documented location.
Takes a parsed name (like 'numpy.array' or 'os.path.join') and follows
its import chain through the inventory to find the final documentation
location. Handles attribute access, method calls, and complex import patterns.
Parameters:
- chain: Name object containing import components and access pattern
- inventory: Dictionary mapping object names to documentation URLs
Returns:
- str: Final resolved location key for inventory lookup
Raises:
- CouldNotResolve: When the name chain cannot be resolved to a location
"""Exceptions raised during the resolution process.
class CouldNotResolve(Exception):
"""
Exception raised when name resolution fails.
Indicates that a name chain could not be traced to a documented
location, either due to missing inventory entries, complex import
patterns, or dynamically created objects.
"""Internal classes that support the resolution process.
class Cursor:
"""
Cursor for following imports, attributes and calls to final types.
Represents the current position when traversing a name chain,
tracking the object location, current value, and whether we're
dealing with an instance or class.
"""
location: str # Current documentation location
value: Any # Current object value (if available)
instance: bool # Whether this is an instance vs class accessFunctions for working with Sphinx inventory data and intersphinx references.
def transpose_inventory(inv: dict, relative_to: str, *, use_tuple: bool = False) -> dict[str, str]:
"""
Transpose Sphinx inventory from {type: {name: (..., location)}} to {name: location}.
Converts Sphinx's nested inventory format to a flat mapping suitable
for efficient name resolution. Filters to Python domain objects only
and handles both local and intersphinx inventories.
Parameters:
- inv: Sphinx inventory in nested format
- relative_to: Directory to make file paths relative to
- use_tuple: Force using tuple interface for compatibility
Returns:
- dict[str, str]: Flat mapping from object names to documentation URLs
"""
# Inventory creation from Sphinx data
def make_inventory(app) -> dict[str, str]:
"""
Create object inventory from local info and intersphinx.
Combines local Sphinx domain objects with intersphinx inventories
to create a complete mapping of available documentation targets.
Parameters:
- app: Sphinx application instance
Returns:
- dict: Combined inventory mapping names to locations
"""Classes for managing resolution data across builds.
class DataCache:
"""
Manages caching of transform data between builds.
Stores and retrieves source transformations to avoid re-parsing
unchanged documents, improving build performance.
"""
transforms: dict[str, list[SourceTransform]]
def __init__(self, doctree_dir: str, source_dir: str): ...
def read(self) -> None:
"""Load cached transform data from disk."""
def write(self) -> None:
"""Save current transform data to disk."""The resolution process follows these steps:
The resolver handles various import patterns:
# Direct imports
import os
os.path.join() # Resolves to: os.path.join
# From imports
from os.path import join
join() # Resolves to: os.path.join
# Aliased imports
import numpy as np
np.array() # Resolves to: numpy.array
# Attribute chains
import matplotlib.pyplot as plt
plt.figure().add_subplot() # Resolves to: matplotlib.figure.Figure.add_subplot
# Complex patterns
from package.submodule import Class
instance = Class()
instance.method() # Resolves to: package.submodule.Class.methodRedirect or alias inventory locations:
# conf.py
codeautolink_inventory_map = {
# Redirect deprecated names
'old.module.function': 'new.module.function',
# Handle moved classes
'package.OldClass': 'package.submodule.NewClass',
# Map aliases to canonical names
'np.array': 'numpy.array',
'plt.figure': 'matplotlib.pyplot.figure'
}Configure warnings for resolution issues:
# conf.py - Enable detailed resolution warnings
codeautolink_warn_on_failed_resolve = True
codeautolink_warn_on_missing_inventory = True
# Example warning output:
# WARNING: Could not resolve `np.array` on line 42
# using path `numpy.array`.
# AttributeError: module 'numpy' has no attribute 'array'
#
# WARNING: Inventory missing `scipy.stats.norm.pdf`
# when resolving `norm.pdf` on line 18.
# Possibly missing documentation entry entirely,
# or the object has been relocated from the source file.The resolver handles sophisticated patterns:
# Method chaining
df.groupby('column').mean().plot()
# Resolves each step: pandas.DataFrame.groupby -> groupby.mean -> Series.plot
# Context managers
with open('file.txt') as f:
f.read()
# Resolves: builtins.open (context manager) -> TextIOWrapper.read
# Decorators
@property
def value(self):
return self._value
# Tracks decorator application and property creation
# Dynamic attribute access
getattr(obj, 'method_name')()
# Limited resolution - tracks what's statically analyzableThe system integrates with Sphinx's inventory system:
# Automatic inventory sources:
# - Local Sphinx domain objects (from autodoc, etc.)
# - Intersphinx inventories from external projects
# - Custom inventory mappings from configuration
# Example inventory entries:
inventory = {
'numpy.array': 'https://numpy.org/doc/stable/reference/generated/numpy.array.html',
'os.path.join': 'https://docs.python.org/3/library/os.path.html#os.path.join',
'matplotlib.pyplot.figure': 'https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.figure.html'
}The resolution system includes several optimizations:
# Caching strategies:
# - Transform cache: Avoid re-parsing unchanged documents
# - Inventory cache: Reuse resolved inventory between builds
# - Name cache: Cache successful resolutions within a build
# Parallel processing support:
# - Thread-safe inventory access
# - Parallel document processing
# - Merge cached data from parallel workersWhen resolution fails, the system provides fallback strategies:
# Graceful degradation:
# 1. Try exact name match in inventory
# 2. Try parent module/class lookup
# 3. Try common alias mappings
# 4. Generate warning if configured
# 5. Skip link generation for unresolved names
# Partial resolution:
# Even if full chain fails, successfully resolved prefixes
# may still generate useful links (e.g., 'numpy.array.shape'
# may link 'numpy.array' even if 'shape' resolution fails)Install with Tessl CLI
npx tessl i tessl/pypi-sphinx-codeautolink