|
21 | 21 | # for warning suppression
|
22 | 22 | import warnings
|
23 | 23 |
|
| 24 | +# for generating GH links with linenumbers |
| 25 | +import inspect |
| 26 | + |
24 | 27 |
|
25 | 28 | class Mock(MagicMock):
|
26 | 29 | @classmethod
|
@@ -231,7 +234,6 @@ def setup(app):
|
231 | 234 | # Override footnote callout CSS to be normal text instead of superscript
|
232 | 235 | app.add_stylesheet("no_reference_superscript.css")
|
233 | 236 |
|
234 |
| - |
235 | 237 | # -- Options for LaTeX output ---------------------------------------------
|
236 | 238 |
|
237 | 239 | latex_elements = {
|
@@ -345,3 +347,95 @@ def setup(app):
|
345 | 347 | warnings.filterwarnings("ignore", category=UserWarning,
|
346 | 348 | message='Matplotlib is currently using agg, which is a'
|
347 | 349 | ' non-GUI backend, so cannot show the figure.')
|
| 350 | + |
| 351 | +# %% helper functions for intelligent "View on Github" linking |
| 352 | +# based on |
| 353 | +# https://gist.github.com/flying-sheep/b65875c0ce965fbdd1d9e5d0b9851ef1 |
| 354 | + |
| 355 | + |
| 356 | +def get_obj_module(qualname): |
| 357 | + """ |
| 358 | + Get a module/class/attribute and its original module by qualname. |
| 359 | + Useful for looking up the original location when a function is imported |
| 360 | + into an __init__.py |
| 361 | +
|
| 362 | + Examples |
| 363 | + -------- |
| 364 | + >>> func, mod = get_obj_module("pvlib.iotools.read_midc") |
| 365 | + >>> mod.__name__ |
| 366 | + 'pvlib.iotools.midc' |
| 367 | + """ |
| 368 | + modname = qualname |
| 369 | + classname = None |
| 370 | + attrname = None |
| 371 | + while modname not in sys.modules: |
| 372 | + attrname = classname |
| 373 | + modname, classname = modname.rsplit('.', 1) |
| 374 | + |
| 375 | + # retrieve object and find original module name |
| 376 | + if classname: |
| 377 | + cls = getattr(sys.modules[modname], classname) |
| 378 | + modname = cls.__module__ |
| 379 | + obj = getattr(cls, attrname) if attrname else cls |
| 380 | + else: |
| 381 | + obj = None |
| 382 | + |
| 383 | + return obj, sys.modules[modname] |
| 384 | + |
| 385 | + |
| 386 | +def get_linenos(obj): |
| 387 | + """Get an object’s line numbers in its source code file""" |
| 388 | + try: |
| 389 | + lines, start = inspect.getsourcelines(obj) |
| 390 | + except TypeError: # obj is an attribute or None |
| 391 | + return None, None |
| 392 | + else: |
| 393 | + return start, start + len(lines) - 1 |
| 394 | + |
| 395 | + |
| 396 | +def make_github_url(pagename): |
| 397 | + """ |
| 398 | + Generate the appropriate GH link for a given docs page. This function |
| 399 | + is intended for use in sphinx template files. |
| 400 | +
|
| 401 | + The target URL is built differently based on the type of page. Sphinx |
| 402 | + provides templates with a built-in `pagename` variable that is the path |
| 403 | + at the end of the URL, without the extension. For instance, |
| 404 | + https://pvlib-python.rtfd.org/en/stable/auto_examples/plot_singlediode.html |
| 405 | + will have pagename = "auto_examples/plot_singlediode". |
| 406 | + """ |
| 407 | + |
| 408 | + URL_BASE = "https://github.com/pvlib/pvlib-python/blob/master/" |
| 409 | + |
| 410 | + # is it a gallery page? |
| 411 | + if any(d in pagename for d in sphinx_gallery_conf['gallery_dirs']): |
| 412 | + if pagename.split("/")[-1] == "index": |
| 413 | + example_file = "README.rst" |
| 414 | + else: |
| 415 | + example_file = pagename.split("/")[-1] + ".py" |
| 416 | + target_url = URL_BASE + "docs/examples/" + example_file |
| 417 | + |
| 418 | + # is it an API autogen page? |
| 419 | + elif "generated" in pagename: |
| 420 | + # pagename looks like "generated/pvlib.location.Location" |
| 421 | + qualname = pagename.split("/")[-1] |
| 422 | + obj, module = get_obj_module(qualname) |
| 423 | + path = module.__name__.replace(".", "/") + ".py" |
| 424 | + target_url = URL_BASE + path |
| 425 | + # add line numbers if possible: |
| 426 | + start, end = get_linenos(obj) |
| 427 | + if start and end: |
| 428 | + target_url += '#L{}-L{}'.format(start, end) |
| 429 | + |
| 430 | + # Just a normal source RST page |
| 431 | + else: |
| 432 | + target_url = URL_BASE + "docs/sphinx/source/" + pagename + ".rst" |
| 433 | + |
| 434 | + return target_url |
| 435 | + |
| 436 | + |
| 437 | +# variables to pass into the HTML templating engine; these are accessible from |
| 438 | +# _templates/breadcrumbs.html |
| 439 | +html_context = { |
| 440 | + 'make_github_url': make_github_url, |
| 441 | +} |
0 commit comments