From 303a5895d13a2c3e8fca0ff332ca7924ee00b484 Mon Sep 17 00:00:00 2001
From: Duncan Macleod <macleoddm@cardiff.ac.uk>
Date: Mon, 13 Jan 2025 17:32:26 +0000
Subject: [PATCH] docs: add linkcode and gitlab footer link

closes #38
---
 docs/conf.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 90 insertions(+), 5 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index 9caffa6..6095bb5 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,16 +1,20 @@
 # dqsegdb2 documentation build configuration file
 
+import inspect
 import re
+import sys
+from os import getenv
+from pathlib import Path
 
-from gwdatafind import __version__ as gwdatafind_version
+import gwdatafind
 
-# -- metadta
+# -- metadata
 
 project = "gwdatafind"
 copyright = "2018-2025, Cardiff University"
 author = "Duncan Macleod"
-release = gwdatafind_version
-version = re.split(r'[\w-]', gwdatafind_version)[0]
+release = gwdatafind.__version__
+version = re.split(r'[\w-]', gwdatafind.__version__)[0]
 
 # -- config
 
@@ -22,14 +26,31 @@ default_role = 'obj'
 # -- theme
 
 html_theme = "furo"
-pygments_dark_style = "monokai"
 
+html_theme_options = {
+    "footer_icons": [
+        {
+            "name": "GitLab",
+            "url": "https://git.ligo.org/computing/gwdatafind/client",
+            "class": "fa-brands fa-gitlab",
+        },
+    ],
+}
+
+html_css_files = [
+    "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/fontawesome.min.css",
+    "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/solid.min.css",
+    "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/brands.min.css",
+]
+
+pygments_dark_style = "monokai"
 
 # -- extensions
 
 extensions = [
     "sphinx.ext.intersphinx",
     "sphinx.ext.napoleon",
+    "sphinx.ext.linkcode",
     "sphinx_automodapi.automodapi",
     "sphinx_copybutton",
     "sphinxarg.ext",
@@ -64,3 +85,67 @@ intersphinx_mapping = {
 
 # napoleon
 napoleon_use_rtype = False
+
+
+# -- linkcode
+
+def _project_git_ref(version, prefix="v"):
+    """Returns the git reference for the given full release version.
+    """
+    _setuptools_scm_version_regex = re.compile(
+        r"\+g(\w+)(?:\Z|\.)",
+    )
+    if match := _setuptools_scm_version_regex.search(version):
+        return match.groups()[0]
+    return f"{prefix}{version}"
+
+
+PROJECT_GIT_REF = _project_git_ref(release, prefix="")
+PROJECT_PATH = Path(gwdatafind.__file__).parent
+PROJECT_URL = getenv(
+    "CI_PROJECT_URL",
+    "https://git.ligo.org/computing/gwdatafind/client",
+)
+PROJECT_BLOB_URL = f"{PROJECT_URL}/-/blob/{PROJECT_GIT_REF}/{PROJECT_PATH.name}"
+
+
+def linkcode_resolve(domain, info):
+    """Determine the URL corresponding to Python object.
+    """
+    if domain != "py" or not info["module"]:
+        return None
+
+    def find_source(module, fullname):
+        """Construct a source file reference for an object reference.
+        """
+        # resolve object
+        obj = sys.modules[module]
+        for part in fullname.split("."):
+            obj = getattr(obj, part)
+        # get filename relative to project
+        filename = Path(
+            inspect.getsourcefile(obj),  # type: ignore [arg-type]
+        ).relative_to(PROJECT_PATH).as_posix()
+        # get line numbers of this object
+        lines, lineno = inspect.findsource(obj)
+        if lineno:
+            start = lineno + 1  # 0-index
+            end = lineno + len(inspect.getblock(lines[lineno:]))
+        else:
+            start = end = 0
+        return filename, start, end
+
+    try:
+        path, start, end = find_source(info["module"], info["fullname"])
+    except (
+        AttributeError,  # object not found
+        OSError,  # file not found
+        TypeError,  # source for object not found
+        ValueError,  # file not from this project
+    ):
+        return None
+
+    url = f"{PROJECT_BLOB_URL}/{path}"
+    if start:
+        url += f"#L{start}-L{end}"
+    return url
-- 
GitLab