Skip to content

Fancy "view on github" links in documentation #913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
example gallery and 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://pvlib-python.rtfd.org/en/stable/auto_examples/plot_singlediode.html
will have pagename = "auto_examples/plot_singlediode".

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 %}
96 changes: 95 additions & 1 deletion docs/sphinx/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
# for warning suppression
import warnings

# for generating GH links with linenumbers
import inspect


class Mock(MagicMock):
@classmethod
Expand Down Expand Up @@ -231,7 +234,6 @@ def setup(app):
# Override footnote callout CSS to be normal text instead of superscript
app.add_stylesheet("no_reference_superscript.css")


# -- Options for LaTeX output ---------------------------------------------

latex_elements = {
Expand Down Expand Up @@ -345,3 +347,95 @@ def setup(app):
warnings.filterwarnings("ignore", category=UserWarning,
message='Matplotlib is currently using agg, which is a'
' non-GUI backend, so cannot show the figure.')

# %% 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("pvlib.iotools.read_midc")
>>> mod.__name__
'pvlib.iotools.midc'
"""
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://pvlib-python.rtfd.org/en/stable/auto_examples/plot_singlediode.html
will have pagename = "auto_examples/plot_singlediode".
"""

URL_BASE = "https://github.com/pvlib/pvlib-python/blob/master/"

# is it a gallery page?
if any(d in pagename for d in sphinx_gallery_conf['gallery_dirs']):
if pagename.split("/")[-1] == "index":
example_file = "README.rst"
else:
example_file = pagename.split("/")[-1] + ".py"
target_url = URL_BASE + "docs/examples/" + example_file

# is it an API autogen page?
elif "generated" in pagename:
# pagename looks like "generated/pvlib.location.Location"
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)

# 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,
}