From 9f28185ae9b448b4f3a33c74bbfd7f6a61159503 Mon Sep 17 00:00:00 2001 From: kanderso-nrel Date: Mon, 24 Feb 2020 21:57:58 -0700 Subject: [PATCH 1/5] try out fancy GH linking --- .../sphinx/source/_templates/breadcrumbs.html | 24 ++++++ docs/sphinx/source/conf.py | 73 ++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 docs/sphinx/source/_templates/breadcrumbs.html diff --git a/docs/sphinx/source/_templates/breadcrumbs.html b/docs/sphinx/source/_templates/breadcrumbs.html new file mode 100644 index 0000000000..e9c66f4109 --- /dev/null +++ b/docs/sphinx/source/_templates/breadcrumbs.html @@ -0,0 +1,24 @@ +{# Modify the "Edit on Github" links to handle auto-generated pages #} + +{% extends "!breadcrumbs.html" %} +{% block breadcrumbs_aside %} +
  • + {# Is it a gallery page? #} + {% if gallery_dir in pagename %} + {% if pagename.split("/")[-1] == "index" %} + {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/examples/README.rst" %} + {% else %} + {% set example_script = pagename.split("/")[-1] + ".py" %} + {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/examples/" + example_script %} + {% endif %} + {# Is it an API autogen page? #} + {% elif "generated" in pagename %} + {# use our make_url function defined in conf.py #} + {% set target_url = make_url(pagename.split("/")[-1]) %} + {# Just a normal source page #} + {% else %} + {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/sphinx/source/" + pagename + ".rst" %} + {% endif %} + View on Github +
  • +{% endblock %} \ No newline at end of file diff --git a/docs/sphinx/source/conf.py b/docs/sphinx/source/conf.py index 7e050726e8..398ef49fb1 100644 --- a/docs/sphinx/source/conf.py +++ b/docs/sphinx/source/conf.py @@ -21,6 +21,9 @@ # for warning suppression import warnings +# for generating GH links with linenumbers +import inspect + class Mock(MagicMock): @classmethod @@ -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 = { @@ -345,3 +347,72 @@ 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""" + 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_url(qualname): + """ + Get the full GitHub URL for some object’s qualname + + Example + ------- + >>> make_url("pvlib.tracking.singleaxis") + 'https://github.com/pvlib/pvlib-python/blob/master/pvlib/tracking.py#L248-L572' + """ + url_base = 'https://github.com/pvlib/pvlib-python/blob/master/' + obj, module = get_obj_module(qualname) + path = module.__name__.replace(".", "/") + ".py" + start, end = get_linenos(obj) + fragment = '#L{}-L{}'.format(start, end) if start and end else '' + return url_base + path + fragment + + +# variables to pass into the HTML templating engine; these are accessible from +# _templates/breadcrumbs.html +html_context = { + 'gallery_dir': sphinx_gallery_conf['gallery_dirs'][0], + 'make_url': make_url, +} From 11ab27246f0e10f02b5bdccd39e102a1454fa544 Mon Sep 17 00:00:00 2001 From: kanderso-nrel Date: Sat, 29 Feb 2020 13:39:58 -0700 Subject: [PATCH 2/5] comment breadcrumbs.html --- .../sphinx/source/_templates/breadcrumbs.html | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/sphinx/source/_templates/breadcrumbs.html b/docs/sphinx/source/_templates/breadcrumbs.html index e9c66f4109..103600ad5d 100644 --- a/docs/sphinx/source/_templates/breadcrumbs.html +++ b/docs/sphinx/source/_templates/breadcrumbs.html @@ -1,9 +1,25 @@ -{# Modify the "Edit on Github" links to handle auto-generated pages #} +{# + +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. + +#} {% extends "!breadcrumbs.html" %} {% block breadcrumbs_aside %}
  • - {# Is it a gallery page? #} + {# + 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". + #} + + {# Is it a gallery page? If so, "auto_examples" will be in the name #} {% if gallery_dir in pagename %} {% if pagename.split("/")[-1] == "index" %} {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/examples/README.rst" %} @@ -11,14 +27,18 @@ {% set example_script = pagename.split("/")[-1] + ".py" %} {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/examples/" + example_script %} {% endif %} - {# Is it an API autogen page? #} + + {# Is it an API autogen page? If so, pagename looks like "generated/pvlib.location.Location" #} {% elif "generated" in pagename %} - {# use our make_url function defined in conf.py #} + # use our make_url function defined in conf.py {% set target_url = make_url(pagename.split("/")[-1]) %} - {# Just a normal source page #} + + {# Just a normal source RST page #} {% else %} {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/sphinx/source/" + pagename + ".rst" %} + {% endif %} + {# Create the HTML element with our custom GH link: #} View on Github
  • -{% endblock %} \ No newline at end of file +{% endblock %} From 548a8eee7ac9dea507c2cf907e41f7d1e2130b56 Mon Sep 17 00:00:00 2001 From: kanderso-nrel Date: Sat, 29 Feb 2020 13:41:10 -0700 Subject: [PATCH 3/5] fix syntax --- docs/sphinx/source/_templates/breadcrumbs.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/source/_templates/breadcrumbs.html b/docs/sphinx/source/_templates/breadcrumbs.html index 103600ad5d..4fe0c8e256 100644 --- a/docs/sphinx/source/_templates/breadcrumbs.html +++ b/docs/sphinx/source/_templates/breadcrumbs.html @@ -30,7 +30,7 @@ {# Is it an API autogen page? If so, pagename looks like "generated/pvlib.location.Location" #} {% elif "generated" in pagename %} - # use our make_url function defined in conf.py + {# use our make_url function defined in conf.py #} {% set target_url = make_url(pagename.split("/")[-1]) %} {# Just a normal source RST page #} From 7d570fbf4ca9e8c3b9f0766cb0c31cd42e50349d Mon Sep 17 00:00:00 2001 From: kanderso-nrel Date: Sun, 1 Mar 2020 14:09:01 -0700 Subject: [PATCH 4/5] refactor GH link logic out of the template and into conf.py --- .../sphinx/source/_templates/breadcrumbs.html | 38 ++++--------- docs/sphinx/source/conf.py | 55 +++++++++++++------ 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/docs/sphinx/source/_templates/breadcrumbs.html b/docs/sphinx/source/_templates/breadcrumbs.html index 4fe0c8e256..b2078c9119 100644 --- a/docs/sphinx/source/_templates/breadcrumbs.html +++ b/docs/sphinx/source/_templates/breadcrumbs.html @@ -5,39 +5,21 @@ 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 %}
  • - {# - 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". - #} - - {# Is it a gallery page? If so, "auto_examples" will be in the name #} - {% if gallery_dir in pagename %} - {% if pagename.split("/")[-1] == "index" %} - {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/examples/README.rst" %} - {% else %} - {% set example_script = pagename.split("/")[-1] + ".py" %} - {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/examples/" + example_script %} - {% endif %} - - {# Is it an API autogen page? If so, pagename looks like "generated/pvlib.location.Location" #} - {% elif "generated" in pagename %} - {# use our make_url function defined in conf.py #} - {% set target_url = make_url(pagename.split("/")[-1]) %} - - {# Just a normal source RST page #} - {% else %} - {% set target_url = "https://github.com/pvlib/pvlib-python/blob/master/docs/sphinx/source/" + pagename + ".rst" %} - - {% endif %} + {# 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: #} View on Github
  • diff --git a/docs/sphinx/source/conf.py b/docs/sphinx/source/conf.py index 398ef49fb1..b0f4733108 100644 --- a/docs/sphinx/source/conf.py +++ b/docs/sphinx/source/conf.py @@ -384,7 +384,7 @@ def get_obj_module(qualname): def get_linenos(obj): - """Get an object’s line numbers""" + """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 @@ -393,26 +393,49 @@ def get_linenos(obj): return start, start + len(lines) - 1 -def make_url(qualname): +def make_github_url(pagename): """ - Get the full GitHub URL for some object’s qualname - - Example - ------- - >>> make_url("pvlib.tracking.singleaxis") - 'https://github.com/pvlib/pvlib-python/blob/master/pvlib/tracking.py#L248-L572' + 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/' - obj, module = get_obj_module(qualname) - path = module.__name__.replace(".", "/") + ".py" - start, end = get_linenos(obj) - fragment = '#L{}-L{}'.format(start, end) if start and end else '' - return url_base + path + fragment + + 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 = { - 'gallery_dir': sphinx_gallery_conf['gallery_dirs'][0], - 'make_url': make_url, + 'make_github_url': make_github_url, } From 02dcd976787171fe84cf3445ea770a5fbaa679d1 Mon Sep 17 00:00:00 2001 From: kanderso-nrel Date: Sun, 1 Mar 2020 14:15:57 -0700 Subject: [PATCH 5/5] typo --- docs/sphinx/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/source/conf.py b/docs/sphinx/source/conf.py index b0f4733108..413c2b94b6 100644 --- a/docs/sphinx/source/conf.py +++ b/docs/sphinx/source/conf.py @@ -429,7 +429,7 @@ def make_github_url(pagename): # Just a normal source RST page else: - target_url = URL_BASE = "docs/sphinx/source/" + pagename + ".rst" + target_url = URL_BASE + "docs/sphinx/source/" + pagename + ".rst" return target_url