1import os.path as path 2import subprocess 3import shlex 4from sphinx.util import logging 5from docutils import nodes 6logger = logging.getLogger(__name__) 7 8 9# use an old git trick, to get the top-level, could have used ../ etc.. but 10# this will be fine.. 11top = subprocess.check_output(shlex.split( 12 "git rev-parse --show-toplevel")).strip().decode("utf-8") 13 14 15def make_ref(text): 16 """ Make hyperlink to Github """ 17 full_path = path.join(top, text) 18 if path.isfile(full_path): 19 ref = "https://www.github.com/numba/numba/blob/master/" + text 20 elif path.isdir(full_path): 21 ref = "https://www.github.com/numba/numba/tree/master/" + text 22 else: 23 logger.warn("Failed to find file in repomap: " + text) 24 ref = "https://www.github.com/numba/numba" 25 return ref 26 27 28def intersperse(lst, item): 29 """ Insert item between each item in lst. 30 31 Copied under CC-BY-SA from stackoverflow at: 32 33 https://stackoverflow.com/questions/5920643/ 34 add-an-item-between-each-item-already-in-the-list 35 36 """ 37 result = [item] * (len(lst) * 2 - 1) 38 result[0::2] = lst 39 return result 40 41 42def ghfile_role(name, rawtext, text, lineno, inliner, options={}, content=[]): 43 """ Emit hyperlink nodes for a given file in repomap. """ 44 my_nodes = [] 45 if "{" in text: # myfile.{c,h} - make two nodes 46 # could have used regexes, but this will be fine.. 47 base = text[:text.find(".") + 1] 48 exts = text[text.find("{") + 1:text.find("}")].split(",") 49 for e in exts: 50 node = nodes.reference(rawtext, 51 base + e, 52 refuri=make_ref(base + e), 53 **options) 54 my_nodes.append(node) 55 elif "*" in text: # path/*_files.py - link to directory 56 # Could have used something from os.path, but this will be fine.. 57 ref = path.dirname(text) + path.sep 58 node = nodes.reference(rawtext, text, refuri=make_ref(ref), **options) 59 my_nodes.append(node) 60 else: # everything else is taken verbatim 61 node = nodes.reference(rawtext, text, refuri=make_ref(text), **options) 62 my_nodes.append(node) 63 64 # insert seperators if needed 65 if len(my_nodes) > 1: 66 my_nodes = intersperse(my_nodes, nodes.Text(" | ")) 67 return my_nodes, [] 68 69 70def setup(app): 71 logger.info('Initializing ghfiles plugin') 72 app.add_role('ghfile', ghfile_role) 73 74 metadata = {'parallel_read_safe': True, 'parallel_write_safe': True} 75 return metadata 76