diff --git a/docs/sphinx/source/_templates/breadcrumbs.html b/docs/sphinx/source/_templates/breadcrumbs.html
new file mode 100644
index 000000000..a64442833
--- /dev/null
+++ b/docs/sphinx/source/_templates/breadcrumbs.html
@@ -0,0 +1,32 @@
+{#
+
+Modify the "Edit on Github" links to handle auto-generated pages in the
+API reference listings. The GH links that sphinx generates by default make
+the assumption that an HTML file comes from an RST file with the same
+filepath, which isn't the case for autogenerated files.
+
+We need to generate the target URL differently based on the type
+of page. We use the built-in `pagename` variable to determine what
+kind of page this is. `pagename` is the path at the end of the
+URL, without the extension. For instance,
+https://rdtools.rtfd.io/en/latest/generated/rdtools.soiling.soiling_srr.html
+will have pagename = "generated/rdtools.soiling.soiling_srr".
+
+Note: make_github_url is defined in conf.py
+#}
+
+{% extends "!breadcrumbs.html" %}
+{% block breadcrumbs_aside %}
+ {# Get the appropriate GH link based on this page's name: #}
+ {% set link_info = make_github_url(pagename) %}
+
+ {# Create the HTML element with our custom GH link, unless it couldn't
+ be determined. Note that None is lowercase in templates. #}
+ {% if link_info is not none %}
+
+
+ {{ link_info['text'] }}
+
+
+ {% endif %}
+{% endblock %}
\ No newline at end of file
diff --git a/docs/sphinx/source/conf.py b/docs/sphinx/source/conf.py
index 7037d373c..87e99633e 100644
--- a/docs/sphinx/source/conf.py
+++ b/docs/sphinx/source/conf.py
@@ -15,6 +15,7 @@
# prefer local rdtools folder to one installed in a venv or site-packages:
import os
import sys
+import inspect
sys.path.insert(0, os.path.abspath('../../..'))
@@ -84,4 +85,114 @@
master_doc = 'index'
# A workaround for the responsive tables always having annoying scrollbars.
def setup(app):
- app.add_stylesheet("no_scrollbars.css")
\ No newline at end of file
+ app.add_stylesheet("no_scrollbars.css")
+
+
+# %% helper functions for intelligent "View on Github" linking
+# based on
+# https://gist.github.com/flying-sheep/b65875c0ce965fbdd1d9e5d0b9851ef1
+
+def get_obj_module(qualname):
+ """
+ Get a module/class/attribute and its original module by qualname.
+ Useful for looking up the original location when a function is imported
+ into an __init__.py
+
+ Examples
+ --------
+ >>> func, mod = get_obj_module("rdtools.degradation_ols")
+ >>> mod.__name__
+ 'rdtools.degradation'
+ """
+ modname = qualname
+ classname = None
+ attrname = None
+ while modname not in sys.modules:
+ attrname = classname
+ modname, classname = modname.rsplit('.', 1)
+
+ # retrieve object and find original module name
+ if classname:
+ cls = getattr(sys.modules[modname], classname)
+ modname = cls.__module__
+ obj = getattr(cls, attrname) if attrname else cls
+ else:
+ obj = None
+
+ return obj, sys.modules[modname]
+
+
+def get_linenos(obj):
+ """Get an object’s line numbers in its source code file"""
+ try:
+ lines, start = inspect.getsourcelines(obj)
+ except TypeError: # obj is an attribute or None
+ return None, None
+ else:
+ return start, start + len(lines) - 1
+
+
+def make_github_url(pagename):
+ """
+ Generate the appropriate GH link for a given docs page. This function
+ is intended for use in sphinx template files.
+ The target URL is built differently based on the type of page. Sphinx
+ provides templates with a built-in `pagename` variable that is the path
+ at the end of the URL, without the extension. For instance,
+ https://rdtools.rtfd.io/en/latest/generated/rdtools.soiling.soiling_srr.html
+ will have pagename = "generated/rdtools.soiling.soiling_srr".
+
+ Returns None if not building development or master.
+ """
+
+ # RTD automatically sets READTHEDOCS_VERSION to the version being built.
+ rtd_version = os.environ.get('READTHEDOCS_VERSION', None)
+ version_map = {
+ 'stable': 'master',
+ 'latest': 'development',
+ }
+ try:
+ branch = version_map[rtd_version]
+ except KeyError:
+ # for other builds (PRs, local builds etc), it's unclear where to link
+ return None
+
+ URL_BASE = "https://github.com/nrel/rdtools/blob/{}/".format(branch)
+
+ # is it an API autogen page?
+ if pagename.startswith("generated/"):
+ # pagename looks like "generated/rdtools.degradation.degradation_ols"
+ qualname = pagename.split("/")[-1]
+ obj, module = get_obj_module(qualname)
+ path = module.__name__.replace(".", "/") + ".py"
+ target_url = URL_BASE + path
+ # add line numbers if possible:
+ start, end = get_linenos(obj)
+ if start and end:
+ target_url += '#L{}-L{}'.format(start, end)
+
+ # is it the example notebook?
+ elif pagename == "example":
+ target_url = URL_BASE + "docs/degradation_and_soiling_example.ipynb"
+
+ # is the the changelog page?
+ elif pagename == "changelog":
+ target_url = URL_BASE + "docs/sphinx/source/changelog"
+
+ # Just a normal source RST page
+ else:
+ target_url = URL_BASE + "docs/sphinx/source/" + pagename + ".rst"
+
+ display_text = "View on github/" + branch
+ link_info = {
+ 'url': target_url,
+ 'text': display_text
+ }
+ return link_info
+
+
+# variables to pass into the HTML templating engine; these are accessible from
+# _templates/breadcrumbs.html
+html_context = {
+ 'make_github_url': make_github_url,
+}
\ No newline at end of file