I have developed a sphinx extension for creating dependencies between different sections of a document. The primary application is plain text requirements management.
The main object in the extension is a 'Vertex' directive. Arbitrary content can be wrapped inside a Vertex directive, and annotated with 'parent' vertexes that it depends on.
.. vertex:: SYS-002
:parents: USR-001:4sMl
this is a system requirement derived from some user requirement
.. note::
it contains nested restructured text
This works fine, until the nested content contains a glossary term-
.. vertex:: SYS-002
:parents: USR-001:4sMl
this is a system requirement derived from some user requirement
it has an embedded glossary term - :term:`Some Term`
this causes a build failure when using the latexpdf builder, and fails silently when using the html builder-
Exception occurred:
File "/home/daniel.eades/Code/python/sphinx-graph/.venv/lib/python3.10/site-packages/docutils/nodes.py", line 652, in __getitem__
return self.attributes[key]
KeyError: 'refdocname'
i'm guessing this is something to do with the order in which references are resolved.
I'm processing the Vertex directive like this-
@dataclass
class Args:
"""Parsed arguments for the Vertex directive."""
uid: str
parents: list[Link] = field(default_factory=list)
layout: str = DEFAULT_LAYOUT
class Directive(SphinxDirective):
"""An RST node representing a To-Do item."""
has_content = True
required_arguments = 1
option_spec = {
"parents": parse.parents,
"layout": parse.string,
}
def run(self) -> Sequence[nodes.Node]:
"""Run the directive and return a Vertex node."""
args = Args(uid=self.arguments[0], **self.options)
content_node = Node("\n".join(self.content))
self.state.nested_parse(self.content, self.content_offset, content_node)
fingerprint = base64.b64encode(
hashlib.md5(content_node.astext().encode()).digest()
)[:4].decode()
targetnode = nodes.target("", "", ids=[args.uid])
placeholder_node = Node(graph_uid=args.uid)
with get_state(self.env) as state:
state.insert_vertex(
args.uid,
Info(
docname=self.env.docname,
lineno=self.lineno,
node=content_node,
target=targetnode,
parents=args.parents,
fingerprint=fingerprint,
layout=args.layout,
),
)
return [targetnode, placeholder_node]
this is probably the part i'm least confident is correct-
content_node = Node("\n".join(self.content))
self.state.nested_parse(self.content, self.content_offset, content_node)
There's a reproduction here - https://github.com/danieleades/sphinx-graph/tree/bug-42
cd docs/
poetry run make latexpdf
(you'll need poetry installed)