Создание роли coderef для sphinx - PullRequest
       28

Создание роли coderef для sphinx

0 голосов
/ 31 декабря 2018

Вопрос

Я хочу создать role, coderef, который будет ссылаться на помеченный код модуля, сгенерированный sphinx.ext.viewcode.Для этого у меня сложилось впечатление, что мне нужно правильно заполнить env._viewcode_modules, и я не уверен, как это сделать.

Фон

Глядя на viewcode, кажется, что viewcode.doctree_read сканируетдерево документа для addnode.desc_signature узлов (если оно вложено в узлы addnode.desc), заполняющее env._viewcode_modules, dict, с модулями, которые будут помечены, как это происходит.Значения, вставленные в dict, изначально None и заменяются либо False, если модуль не может быть окрашен, либо узлом документа (здесь не уверен), когда это может бытьlinted.Кажется, что sphinx.ext.viewcode.collect_pages выполняет итерацию по этим страницам, генерируя соответствующие страницы.

Текущая реализация

Я надеялся подключиться к этому механизму, и когда я сталкиваюсь с coderef вхождениями, просто добавляю некоторые дополнительные записи вenv._viewcode_modules.Я не уверен, однако, что я делаю это правильно.Код, который у меня есть, выглядит следующим образом:

from docutils          import nodes, utils
from sphinx            import addnodes
from sphinx.util.nodes import split_explicit_title

def coderef(role, rawtext, text, line, inliner, options={}, content=[]):
    try : 
     env = inliner.document.settings.env
     if not hasattr(env, '_viewcode_modules'): env._viewcode_modules = {} # View Code retains a list of modules, we sneak the cross linked modules into the list.
     test, name, link = split_explicit_title(text)
     refid   = link.replace('.','-')
     refuri  = env.app.builder.get_relative_uri("/", "/".join(["_modules", *link.split('.')])) # Originally : "_modules/" + link.replace('.','/')
     refname = utils.unescape(name) # Future : inliner.nested_parse() ?
     reflink = utils.unescape("_modules/" + link.replace(".","/")) # str(Path("_modules").join(target.split('.')))
     refnode = nodes.inline('', refname, classes=['viewcode-link']) # viewcode-link is a CSS class
     coderef = addnodes.only(expr='html')
     coderef+= addnodes.pending_xref('', refname, 
         refid       = refid,
         reftype     = 'viewcode' or role, # The reference type, see viewcode extention
         refdomain   = 'std',              # 
         refexplicit = False,              # 
         refdoc      = env.docname,        # Originally : env.docname; This represents the name of the document with all extentions stripped, I think this doubles as a back reference.
         reftarget   = reflink)
     return [coderef], [] 
    except Exception as error : # This is bad form, specify explicit errors you know how to deal with
     msg = inliner.reporter.error(
               'An error occured while determining the code reference for'
               ' "%s" ' % text,
               line = line)
     prb = inliner.problematic(rawtext, text, msg)
     return [prb], [msg]

Неудачная реализация

Раньше мне удавалось частично заставить это работать, используя nodes.reference, но затем помеченные модули не всегда генерировались какони не добавляются к env._viewcode_modules и не обрабатываются sphinx.ext.viewcode.collect_pages.

Наблюдения

Некоторые странности, за которыми я пока не следую, заключаются в том, как разрешаются addnodes.pending_xref.Кажется необходимым иметь как обратную, так и прямую ссылку, и я не думаю, что создаю соответствующую обратную ссылку в данный момент.addnodes.pending_xref также, кажется, принимает узел nodes.inline, предположительно, это узел для текста в последней ссылке;Это также не удалось должным образом на данный момент.

...