Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/sphinx/source/_templates/breadcrumbs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{#

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 %}
<li class="wy-breadcrumbs-aside">
{# Get the appropriate GH link based on this page's name: #}
{% set target_url = make_github_url(pagename) %}
{# Create the HTML element with our custom GH link: #}
<a href="{{ target_url }}" class="fa fa-github">View on Github</a>
</li>
{% endblock %}
97 changes: 96 additions & 1 deletion docs/sphinx/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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('../../..'))


Expand Down Expand Up @@ -84,4 +85,98 @@
master_doc = 'index'
# A workaround for the responsive tables always having annoying scrollbars.
def setup(app):
app.add_stylesheet("no_scrollbars.css")
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".
"""

# RTD automatically sets READTHEDOCS_VERSION to the version being built.
if os.environ.get('READTHEDOCS_VERSION', None) == 'stable':
branch = 'master'
else:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's be explicit about all the cases here. Otherwise, if we change the readthedocs configuration, we could end up with links pointing to development when they shouldn't. Not sure what the correct behavior should be for PR and local builds though. I'd almost rather it be broken than point to the wrong branch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling PR build correctly seems like a huge headache for not much benefit, and I'm not even sure what a local build should point to. What do you think about only generating the link if it's stable/master or latest/development? For other builds it would just omit that HTML element.

# if 'latest', a PR build, or unset (e.g. building locally)
branch = 'development'

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"

# Just a normal source RST page
else:
target_url = URL_BASE + "docs/sphinx/source/" + pagename + ".rst"

return target_url


# variables to pass into the HTML templating engine; these are accessible from
# _templates/breadcrumbs.html
html_context = {
'make_github_url': make_github_url,
}