breathe icon indicating copy to clipboard operation
breathe copied to clipboard

Exceptions since 4.17.0 for functions in a group

Open lgritz opened this issue 4 years ago • 15 comments

I can confirm that this worked in 4.16, and in fact up through commit c6857daea, but fails starting with commit 2fbd5dede4 ("Scoped rendering of functions").

The situation is that I have C++ source code that looks schematically like this:

namespace mynamespace {

/// @defgroup fill
/// @{
///
/// Explanation covering all of the polymorphic functions

void fill (int a);
void fill (float b);
/// @}
} // end namespace

And then in the rst, something like

.. doxygengroup:: fill

And up through 4.16, it would beautifully render the explanation followed by both of the polymorphic functions. Starting with the commit for "Scoped rendering of functions", now I get exceptions with the following traceback:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/sphinx/cmd/build.py", line 280, in build_main
    app.build(args.force_all, filenames)
  File "/usr/local/lib/python3.7/site-packages/sphinx/application.py", line 348, in build
    self.builder.build_update()
  File "/usr/local/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 299, in build_update
    len(to_build))
  File "/usr/local/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 311, in build
    updated_docnames = set(self.read())
  File "/usr/local/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 418, in read
    self._read_serial(docnames)
  File "/usr/local/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 439, in _read_serial
    self.read_doc(docname)
  File "/usr/local/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 479, in read_doc
    doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
  File "/usr/local/lib/python3.7/site-packages/sphinx/io.py", line 221, in read_doc
    pub.publish()
  File "/usr/local/lib/python3.7/site-packages/docutils/core.py", line 217, in publish
    self.settings)
  File "/usr/local/lib/python3.7/site-packages/sphinx/io.py", line 126, in read
    self.parse()
  File "/usr/local/lib/python3.7/site-packages/docutils/readers/__init__.py", line 78, in parse
    self.parser.parse(self.input, document)
  File "/usr/local/lib/python3.7/site-packages/sphinx/parsers.py", line 102, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 171, in run
    input_source=document['source'])
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 239, in run
    context, state, transitions)
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 460, in check_line
    return method(match, context, next_state)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 2753, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 239, in run
    context, state, transitions)
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 460, in check_line
    return method(match, context, next_state)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 2753, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 239, in run
    context, state, transitions)
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 460, in check_line
    return method(match, context, next_state)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 2753, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 239, in run
    context, state, transitions)
  File "/usr/local/lib/python3.7/site-packages/docutils/statemachine.py", line 460, in check_line
    return method(match, context, next_state)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 2326, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 2338, in explicit_construct
    return method(self, expmatch)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 2081, in directive
    directive_class, match, type_name, option_presets)
  File "/usr/local/lib/python3.7/site-packages/docutils/parsers/rst/states.py", line 2130, in run_directive
    result = directive_instance.run()
  File "/usr/local/lib/python3.7/site-packages/sphinx/domains/__init__.py", line 285, in run
    return super().run()
  File "/usr/local/lib/python3.7/site-packages/sphinx/domains/cpp.py", line 6527, in run
    return super().run()
  File "/usr/local/lib/python3.7/site-packages/sphinx/directives/__init__.py", line 190, in run
    name = self.handle_signature(sig, signode)
  File "/usr/local/lib/python3.7/site-packages/sphinx/domains/cpp.py", line 6546, in handle_signature
    symbol = parentSymbol.add_declaration(ast, docname=self.env.docname)
  File "/usr/local/lib/python3.7/site-packages/sphinx/domains/cpp.py", line 4338, in add_declaration
    res = self._add_symbols(nestedName, templateDecls, declaration, docname)
  File "/usr/local/lib/python3.7/site-packages/sphinx/domains/cpp.py", line 4173, in _add_symbols
    assert len(withDecl) <= 1
AssertionError

Sphinx 3.0.3 Doxygen 1.8.18

Is there something more I can relay that would be helpful to aid tracking this down?

lgritz avatar May 10 '20 23:05 lgritz

Forgot to mention, it needs multiple functions within the group to hit the exception. If there's just one function with the group, it seems fine.

lgritz avatar May 10 '20 23:05 lgritz

And I forgot to mention that the specific assertion message was:

Exception occurred:
  File "/usr/local/lib/python3.7/site-packages/sphinx/domains/cpp.py", line 4173, in _add_symbols
    assert len(withDecl) <= 1
AssertionError

lgritz avatar May 10 '20 23:05 lgritz

I'm not able to reproduce it in my own small setup. Do you have an archive/repo available with (a slimmed down) example?

jakobandersen avatar May 11 '20 07:05 jakobandersen

Yes, I'll try to make a small example today.

lgritz avatar May 11 '20 16:05 lgritz

How about this? https://github.com/lgritz/breathe-bug

I've narrowed it way down. In this example, it's slightly more complicated than my description (not by much, though). Almost any code I remove, at this point, allows it to succeed.

lgritz avatar May 12 '20 04:05 lgritz

Aside from the Doxygen version (I have 1.8.13) I have tried with combinations of Breathe and Sphinx versions without hitting the same error. Perhaps it may be a an old pickle file that is somehow is not discarded, which can mess things up. However, I did run into a different crash:

  File "/home/jla/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/home/jla/repos/breathe/breathe/directives.py", line 163, in run
    result = warning.warn(raw_text, warning_nodes)
  File "/home/jla/repos/breathe/breathe/directive/base.py", line 18, in warn
    raw_text = self.format(raw_text)
  File "/home/jla/repos/breathe/breathe/directive/base.py", line 27, in format
    return text.format(**self.context)
IndexError: tuple index out of range

The warning it tries to emit is

doxygenfunction: Unable to resolve multiple matches for function "{namespace}{function}" with arguments ({args}) {tail}.
Potential matches:
    - ImageBuf zero(ROI roi, int nthreads = 0)
    - bool zero(ImageBuf &dst, ROI roi = {}, int nthreads = 0)

jakobandersen avatar May 12 '20 09:05 jakobandersen

I have seen the "tuple index out of range" error as well, on my real docs. It's just not the first thing I was hitting in my pared-down example.

Is that enough for you to go on, or is there something else I can provide that will help?

lgritz avatar May 12 '20 17:05 lgritz

By the way, semi-unrelated to this bug, but your warning reminded me: It sure would be handy if (as an option?) rather than warn when a method signature is ambiguous, it would just print all the matches. Like, I would love to just say

.. doxygenfunction:: zero
    :print-all:

and have it happily insert the descriptions of all of the zero() varieties in that spot.

In fact, the whole reason I'm using "doxygengroup" in the way that is hitting the error is to enclose several polymorphic versions of a function in a group, and have a single directive to insert them all into the text. If I could do it in one step with "doxygenfunction", I would.

lgritz avatar May 12 '20 17:05 lgritz

Not sure if this is related to this issue described in pybind11 PR #2220. That project includes two inline constructors in a group using an \addtogroup block and fails with

Exception occurred:
  File "/usr/lib/python3.8/site-packages/breathe/renderer/sphinxrenderer.py", line 408, in run_directive
    rst_node = nodes[1]
IndexError: list index out of range

ahesford avatar May 20 '20 12:05 ahesford

Any progress on this? Is there more I can do to help track it down?

lgritz avatar May 25 '20 03:05 lgritz

(@ahesford, I believe that is another distinct issue)

jakobandersen avatar May 25 '20 17:05 jakobandersen

Now I tried in a completely fresh Ubuntu 18.04 container, with Doxygen 1.8.18, Breathe 4.17.0, and Sphinx 3.0.3, and I still get the same error regarding text.format(**self.context) (which indeed is a problem, triggered by the {} in one of the signatures).

jakobandersen avatar May 25 '20 18:05 jakobandersen

Interesting. I really liked the compact initializer = {}, but if this is very hard to fix, I suppose I could replace this with the longhand = ROI() if that will unclog my documentation pipeline.

lgritz avatar May 25 '20 18:05 lgritz

I just posted PR #535 which should avoid crashing on the warning. I suspect that the reason for the warning in the first place is related to #289.

jakobandersen avatar May 25 '20 19:05 jakobandersen

The PR #605 mentioned this issue, and #606 provided a more proper fix for parsing function signatures. I am not entirely sure how or if this issue actually relates to that though. #535 is also posted above, so perhaps this issue should already be considered closed?

@lgritz Could you give it another try with the just released Breathe 4.25.0 and share thoughts?

vermeeren avatar Dec 15 '20 16:12 vermeeren