sphinx-doc / sphinx

The Sphinx documentation generator
https://www.sphinx-doc.org/
Other
6.56k stars 2.12k forks source link

`make epub` crashes with NotImplementedError if any custom directive defines epub callback, and document uses sphinxext.todo, sphinxext.graphviz or various other extensions #9219

Open Mekk opened 3 years ago

Mekk commented 3 years ago

In short

Enabling simultaneously sphinxcontrib.images and spinx.ext.todo or sphinx.ext.graphviz or various other plugins causes make epub to crash with dirty NotImplementedError while processing .. todo or similar directive. Other targets (make html, make pdf) work fine.

Looks like this is caused by sole fact that sphinxcontrib.images defines explicit epub callback. This somehow changes the processing chain.

I repeated it both on python2+sphinx1.8.5 and python3+sphinx3.5.4.

Longer story

I have sphinx document which uses sphinxext.todo and contains some .. todo: directives (and also have my custom extension of similar kind, which also shows the issue). I recently added sphinxcontrib.images there. And, out of the sudden:

I found out that disabling sphinxcontrib.images (commenting it out from extensions in conf.py) resolves the issue, then tried deeper.

sphinxcontrib.images defines explicit epub callback: https://github.com/sphinx-contrib/images/blob/85da3e3227822e23f0ddc87326130a41cb4693de/sphinxcontrib/images.py#L337

Both sphinxext.todo and my custom extension do not have one.. For example sphinx/ext/todo.py has the following snippet in setup.py:

app.add_node(todo_node,
                 html=(visit_todo_node, depart_todo_node),
                 latex=(latex_visit_todo_node, latex_depart_todo_node),
                 text=(visit_todo_node, depart_todo_node),
                 man=(visit_todo_node, depart_todo_node),
                 texinfo=(visit_todo_node, depart_todo_node))

Editing this code (and editing my custom extension in the same way) resolves the issue. Once I I dirty-patched sphinx/ext/todo to:

app.add_node(todo_node,
                 html=(visit_todo_node, depart_todo_node),
                 epub=(visit_todo_node, depart_todo_node),
                 latex=(latex_visit_todo_node, latex_depart_todo_node),
                 text=(visit_todo_node, depart_todo_node),
                 man=(visit_todo_node, depart_todo_node),
                 texinfo=(visit_todo_node, depart_todo_node))

(added epub= line) whole issue disappeared, make epub started to work properly again.

So looks like „by default” sphinx nicely falls back to html callbacks while generating epub, but the fact that anybody in the ecosystem (here: sphinxcontrib.images) defined explicit epub handler changes something, and makes sphinx to work differently. And out of the sudden all directives which relied on fallback to html – cause crash.

Mekk commented 3 years ago

Simple workaround which seems to work once and for good – is to edit https://github.com/sphinx-doc/sphinx/blob/4.x/sphinx/application.py#L604 this way (added those two lines in the middle)

        docutils.register_node(node)
        if 'html' in kwds and 'epub' not in kwds:
            kwds['epub'] = kwds['html']
        self.registry.add_translation_handlers(node, **kwds)
Mekk commented 3 years ago

Suggestion from previous comment looks like possible practical fix, but as I suppose it workarounds some error in registry internals, which can also reappear elsewhere.