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