Skip to content

Commit

Permalink
link from reference API to source code on GitHub (#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
droumis authored Dec 26, 2023
1 parent 529ab6b commit 4a8cbf2
Showing 1 changed file with 67 additions and 1 deletion.
68 changes: 67 additions & 1 deletion nbsite/shared_conf.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-

import datetime
import importlib
import inspect
import os
import pathlib as _pathlib
import subprocess
import sys

import nbsite as _nbsite

Expand Down Expand Up @@ -47,7 +51,7 @@ def remove_mystnb_static(app):
'sphinx.ext.coverage',
'sphinx.ext.mathjax',
'sphinx.ext.ifconfig',
'sphinx.ext.viewcode',
'sphinx.ext.linkcode',
'sphinx.ext.inheritance_diagram',
'sphinx_copybutton',
]
Expand Down Expand Up @@ -127,3 +131,65 @@ def remove_mystnb_static(app):
# Ignores: skipping unknown output mime type: application/vnd.holoviews_exec.v0+json
"mystnb.unknown_mime_type"
]

GIT_ROOT_CMD = "git rev-parse --show-toplevel"
GITHUB_BASE_URL = "https://github.com/holoviz/"

def get_module_object(modname, fullname):
"""Retrieve the Python object based on its module and fullname."""
submod = sys.modules.get(modname)
if submod is None:
return None
obj = submod
for part in fullname.split("."):
obj = getattr(obj, part, None)
if obj is None:
return None
return obj

def get_source_info(obj):
"""Get the source file and line numbers for a Python object."""
try:
fn = inspect.getsourcefile(inspect.unwrap(obj))
source, lineno = inspect.getsourcelines(obj)
except (TypeError, OSError):
return None, None, None
return fn, source, lineno

def get_repo_dir():
"""Get the root directory of the current Git repository."""
try:
output = subprocess.check_output(GIT_ROOT_CMD.split(" ")).strip().decode('utf-8')
return _pathlib.Path(output).name
except subprocess.CalledProcessError:
raise RuntimeError("Unable to determine the repository directory")

def linkcode_resolve(domain, info):
"""Resolve the link to the source code for a given Python object in documentation."""
if domain != "py":
return None

modname = info["module"]
fullname = info["fullname"]

obj = get_module_object(modname, fullname)
if obj is None:
return None

fn, source, lineno = get_source_info(obj)
if not fn:
return None

linespec = f"#L{lineno}-L{lineno + len(source) - 1}" if lineno else ""

package = get_repo_dir()

ppath = importlib.__import__(package).__file__
pver = importlib.__import__(package).__version__

fn = os.path.relpath(fn, start=os.path.dirname(ppath))

if "+" in pver:
return f"{GITHUB_BASE_URL}{package}/blob/main/{package}/{fn}{linespec}"
else:
return f"{GITHUB_BASE_URL}{package}/blob/v{pver}/{package}/{fn}{linespec}"

0 comments on commit 4a8cbf2

Please sign in to comment.