Skip to content

Instantly share code, notes, and snippets.

@flying-sheep
Last active August 29, 2017 13:31
Show Gist options
  • Save flying-sheep/b65875c0ce965fbdd1d9e5d0b9851ef1 to your computer and use it in GitHub Desktop.
Save flying-sheep/b65875c0ce965fbdd1d9e5d0b9851ef1 to your computer and use it in GitHub Desktop.
Sphinx configuration for GitHub code links. Every autosummary page will link to the python code, other pages to the .rst documents.
github_url:{{ fullname | modurl }}

{% extends "!autosummary/base.rst" %}

#!/usr/bin/env python3
import sys
import inspect
from pathlib import Path
master_doc = 'index'
templates_path = ['_templates']
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
]
autosummary_generate = True
# RTD theme
html_theme = 'sphinx_rtd_theme'
html_context = dict(
display_github=True,
github_user=...,
github_repo=...,
github_version='master',
conf_py_path='/docs/',
)
# module path filter
def get_obj_module(qualname):
"""Get a module/class/attribute and its original module by qualname"""
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
project_dir = Path(__file__).parent.parent # project/docs/conf.py/../.. → project/
github_url = 'https://github.com/{github_user}/{github_repo}/tree/{github_version}'.format_map(html_context)
def modurl(qualname):
"""Get the full GitHub URL for some object’s qualname"""
obj, module = get_obj_module(qualname)
path = Path(module.__file__).relative_to(project_dir)
start, end = get_linenos(obj)
fragment = '#L{}-L{}'.format(start, end) if start and end else ''
return '{}/{}{}'.format(github_url, path, fragment)
# html_context doesn’t apply to autosummary templates ☹
# and there’s no way to insert filters into those templates
# so we have to modify the default filters
from jinja2.defaults import DEFAULT_FILTERS
DEFAULT_FILTERS['modurl'] = modurl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment