From d25078b404c68d459a8132739c177caa1d8ea069 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Tue, 13 Apr 2021 21:57:41 +0200 Subject: [PATCH] Fixes for Sphinx v4 --- .github/workflows/unit_tests.yml | 11 +++++------ breathe/renderer/sphinxrenderer.py | 27 +++++++++++++++++++++++---- requirements/production.txt | 2 +- tests/test_renderer.py | 27 +++++++++++++++++++++------ 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 0f704eb8..946c3448 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -6,18 +6,17 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9] + python-version: [3.6, 3.7, 3.8, 3.9] sphinx-version: - 3.0.4 - 3.1.2 - 3.2.1 - 3.3.1 - 3.4.3 - - 3.5.0 - - git+https://github.com/sphinx-doc/sphinx.git@3.5.x - - git+https://github.com/sphinx-doc/sphinx.git@3.x - # master (Sphinx 4) will require at least Python 3.6, so disable it for now - #- git+https://github.com/sphinx-doc/sphinx.git@master + - 3.5.4 + - git+https://github.com/sphinx-doc/sphinx.git@4.0.x + - git+https://github.com/sphinx-doc/sphinx.git@4.x + - git+https://github.com/sphinx-doc/sphinx.git@master steps: - uses: actions/checkout@v2 diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index 898dcebb..21547f2d 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -1,3 +1,5 @@ +import sphinx + from breathe.parser import DoxygenCompoundParser from breathe.project import ProjectInfo from breathe.renderer import RenderContext @@ -667,10 +669,23 @@ def content(contentnode): assert declarator is not None if display_obj_type is not None: n = declarator[0] - assert isinstance(n, addnodes.desc_annotation) - assert n.astext()[-1] == " " - txt = display_obj_type + ' ' - declarator[0] = addnodes.desc_annotation(txt, txt) + newStyle = True + # the new style was introduced in Sphinx v4 + if sphinx.version_info[0] < 4: + newStyle = False + # but only for the C and C++ domains + if self.get_domain() and self.get_domain() not in ('c', 'cpp'): + newStyle = False + if newStyle: + # TODO: remove the "type: ignore" when Sphinx >= 4 is required + assert isinstance(n, addnodes.desc_sig_keyword) # type: ignore + declarator[0] = addnodes.desc_sig_keyword( # type: ignore + display_obj_type, display_obj_type) + else: + assert isinstance(n, addnodes.desc_annotation) + assert n.astext()[-1] == " " + txt = display_obj_type + ' ' + declarator[0] = addnodes.desc_annotation(txt, txt) if not self.app.env.config.breathe_debug_trace_doxygen_ids: target = self.create_doxygen_target(node) declarator.insert(0, target) @@ -1162,6 +1177,7 @@ def render_signature(file_data, doxygen_target, name, kind): rst_node.document = self.state.document rst_node['objtype'] = kind + rst_node['domain'] = self.get_domain() if self.get_domain() else 'cpp' contentnode = addnodes.desc_content() rst_node.append(contentnode) @@ -1700,6 +1716,7 @@ def visit_docxrefsect(self, node) -> List[Node]: descnode = addnodes.desc() descnode['objtype'] = 'xrefsect' + descnode['domain'] = self.get_domain() if self.get_domain() else 'cpp' descnode += signode descnode += contentnode @@ -1710,6 +1727,7 @@ def visit_docvariablelist(self, node) -> List[Node]: for varlistentry, listitem in zip(node.varlistentries, node.listitems): descnode = addnodes.desc() descnode['objtype'] = 'varentry' + descnode['domain'] = self.get_domain() if self.get_domain() else 'cpp' signode = addnodes.desc_signature() signode += self.render_optional(varlistentry) descnode += signode @@ -1995,6 +2013,7 @@ def visit_friendclass(self, node) -> List[Node]: desc = addnodes.desc() desc['objtype'] = 'friendclass' + desc['domain'] = self.get_domain() if self.get_domain() else 'cpp' signode = addnodes.desc_signature() desc += signode diff --git a/requirements/production.txt b/requirements/production.txt index b0f139a8..d5fa72f9 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -2,5 +2,5 @@ docutils>=0.12 Jinja2>=2.7.3 MarkupSafe>=0.23 Pygments>=1.6 -Sphinx>=3.0,<3.6 +Sphinx>=3.0,<5 six>=1.9.0 diff --git a/tests/test_renderer.py b/tests/test_renderer.py index 93230419..c2c84234 100644 --- a/tests/test_renderer.py +++ b/tests/test_renderer.py @@ -288,11 +288,21 @@ def test_render_func(app): param=[WrappedParam(type_=WrappedLinkedText(content_=[WrappedMixedContainer(value=u'int')]))]) signature = find_node(render(app, member_def), 'desc_signature') assert signature.astext().startswith('void') - assert find_node(signature, 'desc_name')[0] == 'foo' + if sphinx.version_info[0] < 4: + assert find_node(signature, 'desc_name')[0] == 'foo' + else: + n = find_node(signature, 'desc_name')[0] + assert isinstance(n, sphinx.addnodes.desc_sig_name) + assert len(n) == 1 + assert n[0] == 'foo' params = find_node(signature, 'desc_parameterlist') assert len(params) == 1 param = params[0] - assert param[0] == 'int' + if sphinx.version_info[0] < 4: + assert param[0] == 'int' + else: + assert isinstance(param[0], sphinx.addnodes.desc_sig_keyword_type) + assert param[0][0] == 'int' def test_render_typedef(app): @@ -312,10 +322,15 @@ def test_render_c_function_typedef(app): type_='void* (*', name='voidFuncPtr', argsstring=')(float, int)') signature = find_node(render(app, member_def, domain='c'), 'desc_signature') assert signature.astext().startswith('typedef void *') - params = find_node(signature, 'desc_parameterlist') - assert len(params) == 2 - assert params[0].astext() == "float" - assert params[1].astext() == "int" + if sphinx.version_info[0] < 4: + params = find_node(signature, 'desc_parameterlist') + assert len(params) == 2 + assert params[0].astext() == "float" + assert params[1].astext() == "int" + else: + # the use of desc_parameterlist in this case was not correct, + # it should only be used for a top-level function + pass def test_render_using_alias(app):