|
6 | 6 | # http://www.sphinx-doc.org/en/master/config |
7 | 7 |
|
8 | 8 | from datetime import datetime |
| 9 | +from urllib.parse import urljoin |
9 | 10 |
|
10 | 11 | from sphinx.ext.autodoc import FunctionDocumenter |
11 | 12 | from sphinx.ext.napoleon import NumpyDocstring, docstring |
@@ -231,6 +232,9 @@ def _can_document_member(member, *args, **kwargs): |
231 | 232 |
|
232 | 233 | autosummary_generate = True |
233 | 234 |
|
| 235 | +_DPCTL_021_BASE = "https://intelpython.github.io/dpctl/0.21.1/" |
| 236 | +_DPCTL_021_INV = urljoin(_DPCTL_021_BASE, "objects.inv") |
| 237 | + |
234 | 238 | intersphinx_mapping = { |
235 | 239 | "python": ("https://docs.python.org/3/", None), |
236 | 240 | "numpy": ("https://numpy.org/doc/stable/", None), |
@@ -302,3 +306,65 @@ def _parse_returns_section_patched(self, section: str) -> list[str]: |
302 | 306 |
|
303 | 307 |
|
304 | 308 | NumpyDocstring._parse_returns_section = _parse_returns_section_patched |
| 309 | + |
| 310 | + |
| 311 | +# TODO: Remove once dpnp.tensor docs are generated in dpnp |
| 312 | +def _load_dpctl_tensor_inventory(app): |
| 313 | + """Load dpctl 0.21.1 inventory for dpnp.tensor fallback only.""" |
| 314 | + from sphinx.ext.intersphinx import fetch_inventory |
| 315 | + from sphinx.util import logging |
| 316 | + |
| 317 | + logger = logging.getLogger(__name__) |
| 318 | + |
| 319 | + try: |
| 320 | + inv = fetch_inventory(app, _DPCTL_021_BASE, _DPCTL_021_INV) |
| 321 | + except Exception as exc: |
| 322 | + logger.warning( |
| 323 | + "Failed to load dpctl 0.21.1 inventory from %s: %s", |
| 324 | + _DPCTL_021_INV, |
| 325 | + exc, |
| 326 | + ) |
| 327 | + inv = {} |
| 328 | + |
| 329 | + app.builder.env._dpctl_tensor_021_inventory = inv |
| 330 | + |
| 331 | + |
| 332 | +# TODO: Remove once dpnp.tensor docs are generated in dpnp |
| 333 | +def _resolve_dpnp_tensor_refs(app, env, node, contnode): |
| 334 | + """Resolve dpnp.tensor.* references to dpctl 0.21.1 documentation. |
| 335 | +
|
| 336 | + This temporary workaround is needed because dpnp.tensor documentation |
| 337 | + is not generated yet, while the corresponding API is still documented |
| 338 | + in dpctl 0.21.1. |
| 339 | + """ |
| 340 | + from docutils import nodes as docutils_nodes |
| 341 | + |
| 342 | + target = node.get("reftarget", "") |
| 343 | + if not target.startswith("dpnp.tensor"): |
| 344 | + return None |
| 345 | + |
| 346 | + dpctl_target = target.replace("dpnp.tensor", "dpctl.tensor", 1) |
| 347 | + dpctl_tensor_inv = getattr(env, "_dpctl_tensor_021_inventory", {}) |
| 348 | + |
| 349 | + for _objtype, objects in dpctl_tensor_inv.items(): |
| 350 | + if dpctl_target not in objects: |
| 351 | + continue |
| 352 | + |
| 353 | + item = objects[dpctl_target] |
| 354 | + location = item.uri |
| 355 | + if location.endswith("$"): |
| 356 | + location = location[:-1] + dpctl_target |
| 357 | + |
| 358 | + refuri = urljoin(_DPCTL_021_BASE, location) |
| 359 | + newnode = docutils_nodes.reference( |
| 360 | + "", "", internal=False, refuri=refuri |
| 361 | + ) |
| 362 | + newnode += contnode.deepcopy() |
| 363 | + return newnode |
| 364 | + |
| 365 | + return None |
| 366 | + |
| 367 | + |
| 368 | +def setup(app): |
| 369 | + app.connect("builder-inited", _load_dpctl_tensor_inventory, priority=400) |
| 370 | + app.connect("missing-reference", _resolve_dpnp_tensor_refs, priority=400) |
0 commit comments