2

I'm the maintainer of sphinx-needs, which allows the definition of requirements, bugs, ...

These objects get stored inside the related directive run function and I finally get a list of all objects inside my sphinx documentation.

The objects can be linked to each other and I want to create a diagram of these links (using plantuml and related sphinx-plantuml extension).

The problem is, that I don't know how to let sphinx add and rerender a dynamically created plantuml diagram specification.

Inside a directive, I could use the state_machine to get this done:

diagram = generate_plantuml_spec(objects)
self.state_machine.insert_input(
        diagram.split('\n'),
        self.state_machine.document.attributes['source'])

But that's the wrong place, as my extension has not collected all objects yet.

So the right place should be inside a function, which gets executed when the event "doctree-resolved" is fired by sphinx.

Inside this function I'm able to add any kind of docutils nodes. My idea is to create a node.Text() with the generated diagram spec

 def process_needfilters(app, doctree, fromdocname):
     diagram_data = """"
                    .. plantuml::

                       @startuml
                       node Test
                       @enduml
                    """
     for node in doctree.traverse(needs_diagram):
         content = []
         diagram = nodes.Text(diagram_data, diagram_data)
         content.append(diagram)
         node.replace_self(content)

However this will not force sphinx to render the content.

I also found a sphinx function called nested_parse_with_titles(), but this needs a 'state' object, which is only available inside a directive and not inside an event handler.

So, any idea how I can render rst content inside sphinx event handlers?

barryhunter
  • 20,886
  • 3
  • 30
  • 43
danwos
  • 416
  • 3
  • 12

1 Answers1

1

Solution is to use directly the plantuml node from the plantuml-extension:

Simplified code snippet from sphinx-needs:

from sphinxcontrib.plantuml import plantuml

for node in doctree.traverse(MyDirective):
    plantuml_block_text = ".. plantuml::\n" \
                          "\n" \
                          "   @startuml" \
                          "   @enduml"
    puml_node = plantuml(plantuml_block_text, **dict())
    node.replace_self(puml_node)
danwos
  • 416
  • 3
  • 12
  • this is very interesting. would this allow to import .puml files into .rst? e.g. something like `.. uml:: mydir/myfile.puml` (I guess this is not the way to do it, but I hope you understand my idea). the idea is to manage .puml diagrams with a separate plugin (eg PyCharm PlantUML integration, because it performs better than sphinxcontrib-plantuml 0.8.2). – axd Nov 14 '17 at 08:26
  • 1
    I think what you describe is already possible with spinxcontrib-plantuml. Even your syntax example is correct. And your use case is also exact the same as I do it for my sphinx projects. [Here](http://dwf.readthedocs.io) is a short presentation of our sphinx-workflow with plantuml + sphinx-needs integration. – danwos Nov 14 '17 at 13:24