Hello community,

here is the log from the commit of package python-breathe for openSUSE:Factory 
checked in at 2020-10-29 09:48:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-breathe (Old)
 and      /work/SRC/openSUSE:Factory/.python-breathe.new.3463 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-breathe"

Thu Oct 29 09:48:01 2020 rev:10 rq:841649 version:4.22.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-breathe/python-breathe.changes    
2020-06-28 23:05:53.862773261 +0200
+++ /work/SRC/openSUSE:Factory/.python-breathe.new.3463/python-breathe.changes  
2020-10-29 09:48:03.076154173 +0100
@@ -1,0 +2,21 @@
+Wed Oct 14 01:38:22 UTC 2020 - Steve Kowalik <steven.kowa...@suse.com>
+
+- Update to 4.22.1:
+  * Fix anonymous struct/union usage in C domain. #585
+  * New boolean breathe_show_enumvalue_initializer option specifying whether
+    value of enumvalue should be displayed. #581
+  * Fix Read the Docs build. #567
+  * Document doxygenclass template specialisation spacing. #570
+  * Update upper Sphinx release to <3.4. #571
+  * Reuse breathe.__version__ in setup.py. #572
+  * Document :inner: for the doxygengroup section. #573
+  * Add support for verbatim inline elements. #560
+  * Fix wrong refid when Doxygen SEPARATE_MEMBER_PAGES is YES. #566
+  * Allow Sphinx 3.2. #561
+  * Update CI scripts with new Sphinx versions. #552
+  * Add support for C# using sphinx-csharp. #550
+  * Doc, fix typo, :source: -> :project:. #551
+  * Add support for innergroup. #556
+  * Avoid duplicate doxygen targets when debug tracing. #563
+
+-------------------------------------------------------------------

Old:
----
  v4.19.2.tar.gz

New:
----
  v4.22.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-breathe.spec ++++++
--- /var/tmp/diff_new_pack.p3L8tN/_old  2020-10-29 09:48:03.712154774 +0100
+++ /var/tmp/diff_new_pack.p3L8tN/_new  2020-10-29 09:48:03.716154778 +0100
@@ -18,11 +18,10 @@
 
 %define skip_python2 1
 Name:           python-breathe
-Version:        4.19.2
+Version:        4.22.1
 Release:        0
 Summary:        Sphinx Doxygen renderer
 License:        BSD-3-Clause
-Group:          Development/Languages/Python
 URL:            https://github.com/michaeljones/breathe
 Source:         
https://github.com/michaeljones/breathe/archive/v%{version}.tar.gz
 BuildRequires:  %{python_module Sphinx >= 3.0.4}

++++++ v4.19.2.tar.gz -> v4.22.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/.github/workflows/unit_tests.yml 
new/breathe-4.22.1/.github/workflows/unit_tests.yml
--- old/breathe-4.19.2/.github/workflows/unit_tests.yml 2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/.github/workflows/unit_tests.yml 2020-09-26 
21:27:40.000000000 +0200
@@ -8,9 +8,10 @@
       matrix:
         python-version: [3.5, 3.6, 3.7, 3.8]
         sphinx-version:
-          - 3.0.0
-          - 3.1.0
-          - git+https://github.com/sphinx-doc/sphinx.git@3.1.x
+          - 3.0.4
+          - 3.1.2
+          - 3.2.0
+          - git+https://github.com/sphinx-doc/sphinx.git@3.2.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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/.readthedocs.yaml 
new/breathe-4.22.1/.readthedocs.yaml
--- old/breathe-4.19.2/.readthedocs.yaml        1970-01-01 01:00:00.000000000 
+0100
+++ new/breathe-4.22.1/.readthedocs.yaml        2020-09-26 21:27:40.000000000 
+0200
@@ -0,0 +1,13 @@
+version: 2
+
+python:
+  version: 3
+  install:
+    - requirements: requirements/development.txt
+    - method: pip
+      path: .
+
+sphinx:
+  builder: html
+  configuration: documentation/source/conf.py
+  fail_on_warning: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/.travis.yml 
new/breathe-4.22.1/.travis.yml
--- old/breathe-4.19.2/.travis.yml      2020-06-17 22:03:59.000000000 +0200
+++ new/breathe-4.22.1/.travis.yml      1970-01-01 01:00:00.000000000 +0100
@@ -1,27 +0,0 @@
-language: python
-
-env:
-  - SPHINX_VERSION=3.0 TRAVIS_CI=True
-
-python:
-  - "3.5"
-  - "3.6"
-
-before_install:
-  - sudo apt-get update -qq
-  - sudo apt-get install -y doxygen texlive-latex-base texlive-latex-extra 
texlive-fonts-recommended latexmk
-
-install:
-  - pip install flake8
-  - pip install pytest
-  - pip install Sphinx==$SPHINX_VERSION
-  - pip install .
-
-# Builds all examples & html documentation
-#
-# Provide definition for DOXYGEN variable to stop it trying
-# to run `which doxygen`
-script:
-  - make DOXYGEN=doxygen DEBUG=""
-  - make test
-  - make flake8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/README.rst 
new/breathe-4.22.1/README.rst
--- old/breathe-4.19.2/README.rst       2020-06-17 22:03:59.000000000 +0200
+++ new/breathe-4.22.1/README.rst       2020-09-26 21:27:40.000000000 +0200
@@ -2,9 +2,6 @@
 Breathe
 =======
 
-.. image:: https://travis-ci.org/michaeljones/breathe.svg?branch=master
-    :target: https://travis-ci.org/michaeljones/breathe
-
 .. image:: 
https://github.com/michaeljones/breathe/workflows/unit%20tests/badge.svg
     :target: 
https://github.com/michaeljones/breathe/actions?query=workflow%3A%22unit+tests%22
 
@@ -173,6 +170,36 @@
 
 Inspired by `Keepachangelog.com <http://keepachangelog.com/>`__.
 
+- 2020-09-26 - Breathe v4.22.1
+
+  - Fix anonymous struct/union usage in C domain. #585
+
+- 2020-09-19 - Breathe v4.22.0
+
+  - Fix Read the Docs build (again). #576
+  - New boolean `breathe_show_enumvalue_initializer` option specifying
+    whether value of enumvalue should be displayed. #581
+
+- 2020-09-10 - Breathe v4.21.0
+
+  - Fix Read the Docs build. #567
+  - Document doxygenclass template specialisation spacing. #570
+  - Update upper Sphinx release to <3.4. #571
+  - Reuse breathe.__version__ in setup.py. #572
+  - Document :inner: for the doxygengroup section. #573
+  - Add support for verbatim inline elements. #560
+  - Fix wrong refid when Doxygen SEPARATE_MEMBER_PAGES is YES. #566
+
+- 2020-08-19 - Breathe v4.20.0
+
+  - Allow Sphinx 3.2. #561
+  - Update CI scripts with new Sphinx versions. #552
+  - Add support for C# using sphinx-csharp. #550
+  - Doc, fix typo, :source: -> :project:. #551
+  - Add support for innergroup. #556
+  - Avoid duplicate doxygen targets when debug tracing. #563
+  - Remove Travis badge from README file. #564
+
 - 2020-06-17 - Breathe v4.19.2
 
   - Fix crash when visiting typedef. #547
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/breathe/__init__.py 
new/breathe-4.22.1/breathe/__init__.py
--- old/breathe-4.19.2/breathe/__init__.py      2020-06-17 22:03:59.000000000 
+0200
+++ new/breathe-4.22.1/breathe/__init__.py      2020-09-26 21:27:40.000000000 
+0200
@@ -4,7 +4,7 @@
 
 from sphinx.application import Sphinx
 
-__version__ = '4.19.2'
+__version__ = '4.22.1'
 
 
 def setup(app: Sphinx):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/breathe/directives.py 
new/breathe-4.22.1/breathe/directives.py
--- old/breathe-4.19.2/breathe/directives.py    2020-06-17 22:03:59.000000000 
+0200
+++ new/breathe-4.22.1/breathe/directives.py    2020-09-26 21:27:40.000000000 
+0200
@@ -406,6 +406,10 @@
 
 class DoxygenGroupDirective(_DoxygenContentBlockDirective):
     kind = "group"
+    option_spec = {
+        **_DoxygenContentBlockDirective.option_spec,
+        "inner": flag,
+    }
 
 
 # TODO: is this comment still relevant?
@@ -575,16 +579,19 @@
     app.add_config_value("breathe_projects", {}, True)  # Dict[str, str]
     app.add_config_value("breathe_default_project", "", True)  # str
     # Provide reasonable defaults for domain_by_extension mapping. Can be 
overridden by users.
-    app.add_config_value("breathe_domain_by_extension", {'py': 'py'}, True)  # 
Dict[str, str]
+    app.add_config_value("breathe_domain_by_extension",
+                         {'py': 'py', 'cs': 'cs'}, True)  # Dict[str, str]
     app.add_config_value("breathe_domain_by_file_pattern", {}, True)  # 
Dict[str, str]
     app.add_config_value("breathe_projects_source", {}, True)
     app.add_config_value("breathe_build_directory", '', True)
     app.add_config_value("breathe_default_members", (), True)
     app.add_config_value("breathe_show_define_initializer", False, 'env')
+    app.add_config_value("breathe_show_enumvalue_initializer", False, 'env')
     app.add_config_value("breathe_implementation_filename_extensions", ['.c', 
'.cc', '.cpp'], True)
     app.add_config_value("breathe_doxygen_config_options", {}, True)
     app.add_config_value("breathe_use_project_refids", False, "env")
     app.add_config_value("breathe_order_parameters_first", False, 'env')
+    app.add_config_value("breathe_separate_member_pages", False, 'env')
 
     breathe_css = "breathe.css"
     if (os.path.exists(os.path.join(app.confdir, "_static", breathe_css))):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/breathe/process.py 
new/breathe-4.22.1/breathe/process.py
--- old/breathe-4.19.2/breathe/process.py       2020-06-17 22:03:59.000000000 
+0200
+++ new/breathe-4.22.1/breathe/process.py       2020-09-26 21:27:40.000000000 
+0200
@@ -26,6 +26,7 @@
 GENERATE_XML = YES
 ALIASES = "rst=\verbatim embed:rst"
 ALIASES += "endrst=\endverbatim"
+ALIASES += "inlinerst=\verbatim embed:rst:inline"
 {extra}
 """.strip()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/breathe/renderer/sphinxrenderer.py 
new/breathe-4.22.1/breathe/renderer/sphinxrenderer.py
--- old/breathe-4.19.2/breathe/renderer/sphinxrenderer.py       2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/breathe/renderer/sphinxrenderer.py       2020-09-26 
21:27:40.000000000 +0200
@@ -12,13 +12,19 @@
 
 from docutils import nodes
 from docutils.nodes import Element, Node, TextElement  # noqa
-from docutils.statemachine import StringList
+from docutils.statemachine import StringList, UnexpectedIndentationError
+from docutils.parsers.rst.states import Text
 
 try:
     from sphinxcontrib import phpdomain as php  # type: ignore
 except ImportError:
     php = None
 
+try:
+    from sphinx_csharp import csharp as cs  # type: ignore
+except ImportError:
+    cs = None
+
 import re
 import six
 import textwrap
@@ -142,6 +148,55 @@
 
 # ----------------------------------------------------------------------------
 
+if cs is not None:
+    class CSharpCurrentNamespace(BaseObject, cs.CSharpCurrentNamespace):
+        pass
+
+    class CSharpNamespacePlain(BaseObject, cs.CSharpNamespacePlain):
+        pass
+
+    class CSharpClass(BaseObject, cs.CSharpClass):
+        pass
+
+    class CSharpStruct(BaseObject, cs.CSharpStruct):
+        pass
+
+    class CSharpInterface(BaseObject, cs.CSharpInterface):
+        pass
+
+    class CSharpInherits(BaseObject, cs.CSharpInherits):
+        pass
+
+    class CSharpMethod(BaseObject, cs.CSharpMethod):
+        pass
+
+    class CSharpVariable(BaseObject, cs.CSharpVariable):
+        pass
+
+    class CSharpProperty(BaseObject, cs.CSharpProperty):
+        pass
+
+    class CSharpEvent(BaseObject, cs.CSharpEvent):
+        pass
+
+    class CSharpEnum(BaseObject, cs.CSharpEnum):
+        pass
+
+    class CSharpEnumValue(BaseObject, cs.CSharpEnumValue):
+        pass
+
+    class CSharpAttribute(BaseObject, cs.CSharpAttribute):
+        pass
+
+    class CSharpIndexer(BaseObject, cs.CSharpIndexer):
+        pass
+
+    class CSharpXRefRole(BaseObject, cs.CSharpXRefRole):
+        pass
+
+
+# ----------------------------------------------------------------------------
+
 class DomainDirectiveFactory:
     # A mapping from node kinds to domain directives and their names.
     cpp_classes = {
@@ -191,6 +246,30 @@
             'global': (php.PhpGloballevel, 'global'),
         }
 
+    if cs is not None:
+        cs_classes = {
+            # 'doxygen-name': (CSharp class, key in CSharpDomain.object_types)
+            'namespace': (CSharpNamespacePlain, 'namespace'),
+
+            'class': (CSharpClass, 'class'),
+            'struct': (CSharpStruct, 'struct'),
+            'interface': (CSharpInterface, 'interface'),
+
+            'function': (CSharpMethod, 'function'),
+            'method': (CSharpMethod, 'method'),
+
+            'variable': (CSharpVariable, 'var'),
+            'property': (CSharpProperty, 'property'),
+            'event': (CSharpEvent, 'event'),
+
+            'enum': (CSharpEnum, 'enum'),
+            'enumvalue': (CSharpEnumValue, 'enumerator'),
+            'attribute': (CSharpAttribute, 'attr'),
+
+            # Fallback to cpp domain
+            'typedef': (CPPTypeObject, 'type'),
+        }
+
     @staticmethod
     def create(domain: str, args) -> ObjectDescription:
         cls = cast(Type[ObjectDescription], None)
@@ -214,6 +293,8 @@
                     arg_0 = 'global'
             cls, name = DomainDirectiveFactory.php_classes.get(
                 arg_0, (php.PhpClasslike, 'class'))
+        elif cs is not None and domain == 'cs':
+            cls, name = DomainDirectiveFactory.cs_classes[args[0]]  # type: 
ignore
         else:
             domain = 'cpp'
             cls, name = DomainDirectiveFactory.cpp_classes[args[0]]  # type: 
ignore
@@ -316,6 +397,49 @@
     return definition
 
 
+class InlineText(Text):
+    """
+    Add a custom docutils class to allow parsing inline text. This is to be
+    used inside a @verbatim/@endverbatim block but only the first line is
+    consumed and a inline element is generated as the parent, instead of the
+    paragraph used by Text.
+    """
+    patterns = {'inlinetext': r''}
+    initial_transitions = [('inlinetext', )]
+
+    def indent(self, match, context, next_state):
+        """
+        Avoid Text's indent from detecting space prefixed text and
+        doing "funny" stuff; always rely on inlinetext for parsing.
+        """
+        return self.inlinetext(match, context, next_state)
+
+    def eof(self, context):
+        """
+        Text.eof() inserts a paragraph, so override it to skip adding elements.
+        """
+        return []
+
+    def inlinetext(self, match, context, next_state):
+        """
+        Called by the StateMachine when an inline element is found (which is
+        any text when this class is added as the single transition.
+        """
+        startline = self.state_machine.abs_line_number() - 1
+        msg = None
+        try:
+            block = self.state_machine.get_text_block()
+        except UnexpectedIndentationError as err:
+            block, src, srcline = err.args
+            msg = self.reporter.error('Unexpected indentation.',
+                                      source=src, line=srcline)
+        lines = context + list(block)
+        text, _ = self.inline_text(lines[0], startline)
+        self.parent += text
+        self.parent += msg
+        return [], next_state, []
+
+
 class SphinxRenderer:
     """
     Doxygen node visitor that converts input into Sphinx/RST representation.
@@ -351,7 +475,44 @@
         if self.context.domain == '':
             self.context.domain = self.get_domain()
 
+    # XXX: fix broken links in XML generated by Doxygen when Doxygen's
+    # SEPARATE_MEMBER_PAGES is set to YES; this function should be harmless
+    # when SEPARATE_MEMBER_PAGES is NO!
+    #
+    # The issue was discussed here: 
https://github.com/doxygen/doxygen/pull/7971
+    #
+    # A Doxygen anchor consists of a 32-byte string version of the results of
+    # passing in the stringified identifier or prototype that is being 
"hashed".
+    # An "a" character is then prefixed to mark it as an anchor. Depending on 
how
+    # the identifier is linked, it can also get a "g" prefix to mean it is part
+    # of a Doxygen group. This results in an id having either 33 or 34 bytes
+    # (containing a "g" or not). Some identifiers, eg enumerators, get twice 
that
+    # length to have both a unique enum + unique enumerator, and sometimes they
+    # get two "g" characters as prefix instead of one.
+    def _fixup_separate_member_pages(self, refid: str) -> str:
+        if refid:
+            parts = refid.rsplit("_", 1)
+            if len(parts) == 2 and parts[1].startswith("1"):
+                anchorid = parts[1][1:]
+                if len(anchorid) in set([33, 34]) and 
parts[0].endswith(anchorid):
+                    return parts[0][:-len(anchorid)] + parts[1]
+                elif len(anchorid) > 34:
+                    index = 0
+                    if anchorid.startswith('gg'):
+                        index = 1
+                        _len = 35
+                    elif anchorid.startswith('g'):
+                        _len = 34
+                    else:
+                        _len = 33
+                    if parts[0].endswith(anchorid[index:_len]):
+                        return parts[0][:-(_len - index)] + parts[1]
+
+        return refid
+
     def get_refid(self, refid: str) -> str:
+        if self.app.config.breathe_separate_member_pages:  # type: ignore
+            refid = self._fixup_separate_member_pages(refid)
         if self.app.config.breathe_use_project_refids:  # type: ignore
             return "%s%s" % (self.project_info.name(), refid)
         else:
@@ -446,11 +607,12 @@
         declaration = declaration.replace('\n', ' ')
         nodes_ = self.run_directive(obj_type, declaration, content_callback, 
options)
         if self.app.env.config.breathe_debug_trace_doxygen_ids:
-            ts = self.create_doxygen_target(node)
-            if len(ts) == 0:
+            target = self.create_doxygen_target(node)
+            if len(target) == 0:
                 print("{}Doxygen target: (none)".format('  ' * _debug_indent))
             else:
-                print("{}Doxygen target: {}".format('  ' * _debug_indent, 
ts[0]['ids']))
+                print("{}Doxygen target: {}".format('  ' * _debug_indent,
+                                                    target[0]['ids']))
 
         # <desc><desc_signature> and then one or more <desc_signature_line>
         # each <desc_signature_line> has a sphinx_line_type which hints what 
is present in that line
@@ -477,7 +639,8 @@
             assert n.astext()[-1] == " "
             txt = display_obj_type + ' '
             declarator[0] = addnodes.desc_annotation(txt, txt)
-        target = self.create_doxygen_target(node)
+        if not self.app.env.config.breathe_debug_trace_doxygen_ids:
+            target = self.create_doxygen_target(node)
         declarator.insert(0, target)
         if declarator_callback:
             declarator_callback(declarator)
@@ -644,11 +807,11 @@
             obj_type = node.kind
         nodes = self.run_domain_directive(obj_type, [declaration.replace('\n', 
' ')])
         if self.app.env.config.breathe_debug_trace_doxygen_ids:
-            ts = self.create_doxygen_target(node)
-            if len(ts) == 0:
+            target = self.create_doxygen_target(node)
+            if len(target) == 0:
                 print("{}Doxygen target (old): (none)".format('  ' * 
_debug_indent))
             else:
-                print("{}Doxygen target (old): {}".format('  ' * 
_debug_indent, ts[0]['ids']))
+                print("{}Doxygen target (old): {}".format('  ' * 
_debug_indent, target[0]['ids']))
 
         rst_node = nodes[1]
         finder = NodeFinder(rst_node.document)
@@ -662,7 +825,9 @@
             update_signature(signode, obj_type)
         if description is None:
             description = self.description(node)
-        signode.insert(0, self.create_doxygen_target(node))
+        if not self.app.env.config.breathe_debug_trace_doxygen_ids:
+            target = self.create_doxygen_target(node)
+        signode.insert(0, target)
         contentnode.extend(description)
         return nodes
 
@@ -827,11 +992,11 @@
             return self.visit_union(node)
         elif kind in ('struct', 'class', 'interface'):
             dom = self.get_domain()
-            if not dom or dom in ('c', 'cpp', 'py'):
+            if not dom or dom in ('c', 'cpp', 'py', 'cs'):
                 return self.visit_class(node)
         elif kind == 'namespace':
             dom = self.get_domain()
-            if not dom or dom in ('c', 'cpp', 'py'):
+            if not dom or dom in ('c', 'cpp', 'py', 'cs'):
                 return self.visit_namespace(node)
 
         self.context = cast(RenderContext, self.context)
@@ -924,7 +1089,7 @@
     # having two lists in case they fall out of sync
     #
     # If this list is edited, also change the sections option documentation for
-    # the doxygen(auto)file directive in documentation/source/autofile.rst.
+    # the doxygen(auto)file directive in documentation/source/file.rst.
     sections = [
         ("user-defined", "User Defined"),
         ("public-type", "Public Types"),
@@ -933,8 +1098,8 @@
         ("public-slot", "Public Slots"),
         ("signal", "Signals"),
         ("dcop-func", "DCOP Function"),
-        ("property", "Property"),
-        ("event", "Event"),
+        ("property", "Properties"),
+        ("event", "Events"),
         ("public-static-func", "Public Static Functions"),
         ("public-static-attrib", "Public Static Attributes"),
         ("protected-type", "Protected Types"),
@@ -1024,6 +1189,12 @@
         addnode('innerclass', lambda: self.render_iterable(node.innerclass))
         addnode('innernamespace', lambda: 
self.render_iterable(node.innernamespace))
 
+        if 'inner' in options:
+            for node in node.innergroup:
+                file_data = self.compound_parser.parse(node.refid)
+                inner = file_data.compounddef
+                addnode('innergroup', lambda: self.visit_compounddef(inner))
+
         nodelist = []
         for i, nodes_ in sorted(nodemap.items()):
             nodelist += nodes_
@@ -1217,6 +1388,25 @@
     def visit_highlight(self, node) -> List[Node]:
         return self.render_iterable(node.content_)
 
+    def _nested_inline_parse_with_titles(self, content, node) -> str:
+        """
+        This code is basically a customized nested_parse_with_titles from
+        docutils, using the InlineText class on the statemachine.
+        """
+        surrounding_title_styles = self.state.memo.title_styles
+        surrounding_section_level = self.state.memo.section_level
+        self.state.memo.title_styles = []
+        self.state.memo.section_level = 0
+        try:
+            return self.state.nested_parse(content, 0, node, match_titles=1,
+                                           state_machine_kwargs={
+                                               'state_classes': (InlineText,),
+                                               'initial_state': 'InlineText'
+                                           })
+        finally:
+            self.state.memo.title_styles = surrounding_title_styles
+            self.state.memo.section_level = surrounding_section_level
+
     def visit_verbatim(self, node) -> List[Node]:
         if not node.text.strip().startswith("embed:rst"):
             # Remove trailing new lines. Purely subjective call from viewing 
results
@@ -1225,6 +1415,8 @@
             # Handle has a preformatted text
             return [nodes.literal_block(text, text)]
 
+        is_inline = False
+
         # do we need to strip leading asterisks?
         # NOTE: We could choose to guess this based on every line starting 
with '*'.
         #   However This would have a side-effect for any users who have an 
rst-block
@@ -1243,11 +1435,19 @@
             lines = map(lambda text: text.replace("///", "   ", 1), lines)
             node.text = "\n".join(lines)
 
-        # Remove the first line which is "embed:rst[:leading-asterisk]"
-        text = "\n".join(node.text.split(u"\n")[1:])
+        elif node.text.strip().startswith("embed:rst:inline"):
+            # Inline all text inside the verbatim
+            node.text = "".join(node.text.splitlines())
+            is_inline = True
+
+        if is_inline:
+            text = node.text.replace("embed:rst:inline", "", 1)
+        else:
+            # Remove the first line which is "embed:rst[:leading-asterisk]"
+            text = "\n".join(node.text.split(u"\n")[1:])
 
-        # Remove starting whitespace
-        text = textwrap.dedent(text)
+            # Remove starting whitespace
+            text = textwrap.dedent(text)
 
         # Inspired by autodoc.py in Sphinx
         rst = StringList()
@@ -1255,13 +1455,19 @@
             rst.append(line, "<breathe>")
 
         # Parent node for the generated node subtree
-        rst_node = nodes.paragraph()
+        if is_inline:
+            rst_node = nodes.inline()
+        else:
+            rst_node = nodes.paragraph()
         rst_node.document = self.state.document
 
         # Generate node subtree
-        nested_parse_with_titles(self.state, rst, rst_node)
-        # TODO: hmm, what is supposed to be returned? something is strange 
with the types
-        return rst_node  # type: ignore
+        if is_inline:
+            self._nested_inline_parse_with_titles(rst, rst_node)
+        else:
+            nested_parse_with_titles(self.state, rst, rst_node)
+
+        return [rst_node]
 
     def visit_inc(self, node) -> List[Node]:
         if node.local == u"yes":
@@ -1344,7 +1550,7 @@
 
     def visit_function(self, node) -> List[Node]:
         dom = self.get_domain()
-        if not dom or dom in ('c', 'cpp', 'py'):
+        if not dom or dom in ('c', 'cpp', 'py', 'cs'):
             names = self.get_qualification()
             names.append(node.get_name())
             name = self.join_nested_name(names)
@@ -1396,11 +1602,12 @@
 
             nodes = self.run_domain_directive(node.kind, 
self.context.directive_args[1])
             if self.app.env.config.breathe_debug_trace_doxygen_ids:
-                ts = self.create_doxygen_target(node)
-                if len(ts) == 0:
+                target = self.create_doxygen_target(node)
+                if len(target) == 0:
                     print("{}Doxygen target (old): (none)".format('  ' * 
_debug_indent))
                 else:
-                    print("{}Doxygen target (old): {}".format('  ' * 
_debug_indent, ts[0]['ids']))
+                    print("{}Doxygen target (old): {}".format('  ' * 
_debug_indent,
+                                                              
target[0]['ids']))
 
             rst_node = nodes[1]
             finder = NodeFinder(rst_node.document)
@@ -1408,7 +1615,9 @@
 
             # Templates have multiple signature nodes in recent versions of 
Sphinx.
             # Insert Doxygen target into the first signature node.
-            rst_node.children[0].insert(0, self.create_doxygen_target(node))  
# type: ignore
+            if not self.app.env.config.breathe_debug_trace_doxygen_ids:
+                target = self.create_doxygen_target(node)
+            rst_node.children[0].insert(0, target)  # type: ignore
 
             finder.content.extend(self.description(node))
             return nodes
@@ -1447,7 +1656,10 @@
         return self.handle_declaration(node, declaration, 
content_callback=content)
 
     def visit_enumvalue(self, node) -> List[Node]:
-        declaration = node.name + self.make_initializer(node)
+        if self.app.config.breathe_show_enumvalue_initializer:  # type: ignore
+            declaration = node.name + self.make_initializer(node)
+        else:
+            declaration = node.name
         return self.handle_declaration(node, declaration, obj_type='enumvalue')
 
     def visit_typedef(self, node) -> List[Node]:
@@ -1495,14 +1707,17 @@
             if len(initializer) != 0:
                 options['value'] = initializer
         else:
+            typename = ''.join(n.astext() for n in 
self.render(node.get_type()))
+            if dom == 'c' and '::' in typename:
+                typename = typename.replace('::', '.')
             declaration = ' '.join([
                 self.create_template_prefix(node),
-                ''.join(n.astext() for n in self.render(node.get_type())),  # 
type: ignore
+                typename,
                 name,
                 node.get_argsstring(),
                 self.make_initializer(node)
             ])
-        if not dom or dom in ('c', 'cpp', 'py'):
+        if not dom or dom in ('c', 'cpp', 'py', 'cs'):
             return self.handle_declaration(node, declaration, options=options)
         else:
             return self.render_declaration(node, declaration)
@@ -1647,6 +1862,12 @@
             return self.visit_typedef(node)
         if node.kind == "variable":
             return self.visit_variable(node)
+        if node.kind == "property":
+            # Note: visit like variable for now
+            return self.visit_variable(node)
+        if node.kind == "event":
+            # Note: visit like variable for now
+            return self.visit_variable(node)
         if node.kind == "define":
             return self.visit_define(node)
         if node.kind == "friend":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/documentation/source/autofile.rst 
new/breathe-4.22.1/documentation/source/autofile.rst
--- old/breathe-4.19.2/documentation/source/autofile.rst        2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/documentation/source/autofile.rst        2020-09-26 
21:27:40.000000000 +0200
@@ -13,7 +13,7 @@
 This should work::
 
    .. autodoxygenfile:: auto_class.h
-      :source: auto
+      :project: auto
 
 With the following config value::
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/documentation/source/class.rst 
new/breathe-4.22.1/documentation/source/class.rst
--- old/breathe-4.19.2/documentation/source/class.rst   2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/documentation/source/class.rst   2020-09-26 
21:27:40.000000000 +0200
@@ -89,6 +89,8 @@
 .. doxygenclass:: TemplateClass
    :project: template_specialisation
 
+Note the spacing inside the ``<>``, it's important: there must be a
+space after the ``<`` and before the ``>``.
 
 Members Example
 ---------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/documentation/source/directives.rst 
new/breathe-4.22.1/documentation/source/directives.rst
--- old/breathe-4.19.2/documentation/source/directives.rst      2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/documentation/source/directives.rst      2020-09-26 
21:27:40.000000000 +0200
@@ -211,6 +211,7 @@
       :private-members:
       :undoc-members:
       :no-link:
+      :inner:
 
 Checkout the :ref:`doxygengroup documentation <group-example>` for more details
 and to see it in action.
@@ -452,7 +453,7 @@
    Then your ``autodoxygenfile`` usage can look like this::
 
       .. autodoxygenfile:: file.c
-         :source: myprojectsource
+         :project: myprojectsource
 
    The directory entry in the tuple can be an empty string if the entries in 
the
    list are full paths.
@@ -517,6 +518,13 @@
    For example a define ``MAX_LENGTH 100`` would be shown with the value 100 
if this is set to ``True``,
    and without if it is set to ``False``.
 
+.. confval:: breathe_show_enumvalue_initializer
+
+   A boolean flag which can be set to ``True`` to display the initializer of 
an enum value in the output.
+
+   For example an enum value ``TWO = 2`` would be shown with the value 2 if 
this is set to ``True``,
+   and without if it is set to ``False``.
+
 .. confval:: breathe_use_project_refids
 
    True or False setting to control if the refids generated by breathe for 
doxygen
@@ -536,3 +544,11 @@
    documentation should be placed immediately after the brief and detailed 
description
    or at the end, after the returns, remarks and warnings section. Default 
value and
    also the legacy behavior is False.
+
+.. confval:: breathe_separate_member_pages
+
+   True or False setting to control if the input XML generated by Doxygen had 
the
+   Doxygen SEPARATE_MEMBER_PAGES option set to YES or NO. The Doxygen option 
defaults
+   to NO which generates XML that allows Breathe to resolve all references. 
When set
+   to YES the refid/id of elements get an extra element which Breathe tries to 
get rid
+   of when this setting is True.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/documentation/source/file.rst 
new/breathe-4.22.1/documentation/source/file.rst
--- old/breathe-4.19.2/documentation/source/file.rst    2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/documentation/source/file.rst    2020-09-26 
21:27:40.000000000 +0200
@@ -26,7 +26,7 @@
       "derivedcompoundref", "Derived compound reference"
       "detaileddescription", "Detailed description"
       "enum", "Enumerator"
-      "event", "Event"
+      "event", "Events"
       "friend", "Friend"
       "func", "Function"
       "innerclass", "**Must be given to show sections inside a class**"
@@ -42,7 +42,7 @@
       "private-static-attrib", "Private static attribute"
       "private-static-func", "Private static function"
       "private-type", "Private type"
-      "property", "Property"
+      "property", "Properties"
       "protected-attrib", "Protected attribute"
       "protected-func", "Protected function"
       "protected-slot", "Protected slot"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/documentation/source/group.rst 
new/breathe-4.22.1/documentation/source/group.rst
--- old/breathe-4.19.2/documentation/source/group.rst   2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/documentation/source/group.rst   2020-09-26 
21:27:40.000000000 +0200
@@ -10,7 +10,7 @@
 
 It takes the standard ``project``, ``path``, ``outline`` and ``no-link`` 
options
 and additionally the ``content-only``, ``members``, ``protected-members``,
-``private-members`` and ``undoc-members`` options.
+``private-members``, ``undoc-members`` and ``inner`` options.
 
 ``content-only``
    If this flag is specified, then the directive does not output the name of 
the
@@ -42,6 +42,11 @@
 use the :ref:`breathe_default_members <breathe-default-members>` configuration
 variable to set it in the ``conf.py``.
 
+``inner``
+   If specified, the groups that were defined inside this group, by either
+   defining them inside the scope of another group, or by using the Doxygen
+   \ingroup command, are also parsed and loaded.
+
 .. _doxygen documentation: 
http://www.stack.nl/~dimitri/doxygen/manual/grouping.html
 
 .. contents::
@@ -190,6 +195,27 @@
    issue. Please post an issue on github if you would like this resolved.
 
 
+Inner Example
+-------------
+
+.. cpp:namespace:: @ex_group_inner
+
+The ``inner`` option changes the output to include groups that are defined
+inside other groups.
+
+.. code-block:: rst
+
+   .. doxygengroup:: mygroup
+      :project: group
+      :inner:
+
+Produces this output:
+
+.. doxygengroup:: mygroup
+   :project: group
+   :inner:
+
+
 Outline Example
 ---------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/documentation/source/markups.rst 
new/breathe-4.22.1/documentation/source/markups.rst
--- old/breathe-4.19.2/documentation/source/markups.rst 2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/documentation/source/markups.rst 2020-09-26 
21:27:40.000000000 +0200
@@ -127,6 +127,38 @@
 
 ----
 
+Inline rST
+~~~~~~~~~~
+
+.. cpp:namespace:: @ex_markups_inline
+
+Normal verbatim elements result in block elements. But sometimes you'll want
+to generate rST references where they need to be rendered inline with the text.
+For example::
+
+   /// Some kind of method
+   ///
+   /// @param something a parameter
+   /// @returns the same value provided in something param
+   ///
+   /// @verbatim embed:rst:inline some inline text @endverbatim
+
+For these kinds of references, you can use an **embed:rst:inline** tag as
+shown in the above example.
+
+This will appropriately handle the leading slashes and render as:
+
+----
+
+.. doxygenfunction:: TestClass::rawInlineVerbatim
+   :project: rst
+
+.. doxygenfunction:: TestClass::rawVerbatim
+   :project: rst
+   :outline:
+
+----
+
 Aliases
 ~~~~~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/examples/specific/group.h 
new/breathe-4.22.1/examples/specific/group.h
--- old/breathe-4.19.2/examples/specific/group.h        2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/examples/specific/group.h        2020-09-26 
21:27:40.000000000 +0200
@@ -48,6 +48,28 @@
 
 /** @} */ // end of mygroup
 
+/** @defgroup innergroup Inner Group
+ *  @ingroup mygroup
+ *  This is an inner group
+ *  @{
+ */
+
+//! \brief inner class inside of namespace
+class InnerGroupClassTest {
+
+public:
+    //! \brief inner namespaced class function
+    void function() {};
+
+private:
+
+    //! A private function
+    void innerGroupPrivateFunction() {};
+
+    class PrivateClass {};
+};
+
+/** @} */ // end of innergroup
 
 //! \brief second class inside of namespace
 class UngroupedClassTest {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/examples/specific/rst.cfg 
new/breathe-4.22.1/examples/specific/rst.cfg
--- old/breathe-4.19.2/examples/specific/rst.cfg        2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/examples/specific/rst.cfg        2020-09-26 
21:27:40.000000000 +0200
@@ -12,3 +12,4 @@
 
 ALIASES = "rst=\verbatim embed:rst"
 ALIASES += "endrst=\endverbatim"
+ALIASES += "inlinerst=\verbatim embed:rst:inline"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/examples/specific/rst.h 
new/breathe-4.22.1/examples/specific/rst.h
--- old/breathe-4.19.2/examples/specific/rst.h  2020-06-17 22:03:59.000000000 
+0200
+++ new/breathe-4.22.1/examples/specific/rst.h  2020-09-26 21:27:40.000000000 
+0200
@@ -12,7 +12,7 @@
     This is some funky non-XML compliant text: <& !><
 
     .. note::
-        
+
        This reStructuredText has been handled correctly.
     \endrst
 
@@ -67,6 +67,12 @@
     //////////////////////////////////////////////////////////////
     virtual void rawLeadingSlashesVerbatim(int something) const = 0;
 
+    /*!
+    Inserting an inline reStructuredText snippet.
+    Linking to another function: \inlinerst :cpp:func:`TestClass::rawVerbatim` 
\endrst
+    */
+    virtual void rawInlineVerbatim() const = 0;
+
     //! Brief description
     virtual void testFunction() const {};
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/requirements/production.txt 
new/breathe-4.22.1/requirements/production.txt
--- old/breathe-4.19.2/requirements/production.txt      2020-06-17 
22:03:59.000000000 +0200
+++ new/breathe-4.22.1/requirements/production.txt      2020-09-26 
21:27:40.000000000 +0200
@@ -2,5 +2,5 @@
 Jinja2>=2.7.3
 MarkupSafe>=0.23
 Pygments>=1.6
-Sphinx>=3.0,<3.2
+Sphinx>=3.0,<3.4
 six>=1.9.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/setup.py new/breathe-4.22.1/setup.py
--- old/breathe-4.19.2/setup.py 2020-06-17 22:03:59.000000000 +0200
+++ new/breathe-4.22.1/setup.py 2020-09-26 21:27:40.000000000 +0200
@@ -7,15 +7,14 @@
     from setuptools import setup, find_packages
 
 import sys
-
-import breathe
+from breathe import __version__
 
 long_desc = '''
 Breathe is an extension to reStructuredText and Sphinx to be able to read and
  render `Doxygen <http://www.doxygen.org>`__ xml output.
 '''
 
-requires = ['Sphinx>=3.0,<3.2', 'docutils>=0.12', 'six>=1.9']
+requires = ['Sphinx>=3.0,<3.4', 'docutils>=0.12', 'six>=1.9']
 
 if sys.version_info < (3, 5):
     print('ERROR: Sphinx requires at least Python 3.5 to run.')
@@ -24,7 +23,7 @@
 
 setup(
     name='breathe',
-    version=breathe.__version__,
+    version=__version__,
     url='https://github.com/michaeljones/breathe',
     download_url='https://github.com/michaeljones/breathe',
     license='BSD',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/breathe-4.19.2/tests/test_renderer.py 
new/breathe-4.22.1/tests/test_renderer.py
--- old/breathe-4.19.2/tests/test_renderer.py   2020-06-17 22:03:59.000000000 
+0200
+++ new/breathe-4.22.1/tests/test_renderer.py   2020-09-26 21:27:40.000000000 
+0200
@@ -2,7 +2,10 @@
 
 import sphinx.addnodes
 import sphinx.environment
-from breathe.parser.compound import linkedTextTypeSub, memberdefTypeSub, 
paramTypeSub, MixedContainer
+from breathe.parser.compound import (
+    compounddefTypeSub, linkedTextTypeSub, memberdefTypeSub, paramTypeSub,
+    refTypeSub, MixedContainer
+)
 from breathe.renderer.sphinxrenderer import SphinxRenderer
 from breathe.renderer.filter import OpenFilter
 from docutils import frontend, nodes, parsers, utils
@@ -44,9 +47,9 @@
     A base class for test wrappers of Doxygen nodes. It allows setting all 
attributes via keyword arguments
     in the constructor.
     """
-    def __init__(self, cls, **kwargs):
+    def __init__(self, cls, *args, **kwargs):
         if cls:
-            cls.__init__(self)
+            cls.__init__(self, args)
         for name, value in kwargs.items():
             if not hasattr(self, name):
                 raise AttributeError('invalid attribute ' + name)
@@ -78,6 +81,18 @@
         WrappedDoxygenNode.__init__(self, paramTypeSub, **kwargs)
 
 
+class WrappedRef(refTypeSub, WrappedDoxygenNode):
+    """A test wrapper of Doxygen ref."""
+    def __init__(self, node_name, **kwargs):
+        WrappedDoxygenNode.__init__(self, refTypeSub, node_name, **kwargs)
+
+
+class WrappedCompoundDef(compounddefTypeSub, WrappedDoxygenNode):
+    """A test wrapper of Doxygen compound definition."""
+    def __init__(self, **kwargs):
+        WrappedDoxygenNode.__init__(self, compounddefTypeSub, **kwargs)
+
+
 class MockState:
     def __init__(self, app):
         env = sphinx.environment.BuildEnvironment(app)
@@ -120,17 +135,17 @@
 
 
 class MockContext:
-    def __init__(self, app, node_stack, domain=None):
+    def __init__(self, app, node_stack, domain=None, options=[]):
         self.domain = domain
         self.node_stack = node_stack
         self.directive_args = [
-            None,  # name
-            None,  # arguments
-            [],    # options
-            None,  # content
-            None,  # lineno
-            None,  # content_offset
-            None,  # block_text
+            None,     # name
+            None,     # arguments
+            options,  # options
+            None,     # content
+            None,     # lineno
+            None,     # content_offset
+            None,     # block_text
             MockState(app), MockStateMachine()]
         self.child = None
         self.mask_factory = MockMaskFactory()
@@ -152,6 +167,23 @@
         self.reporter = MockReporter()
 
 
+class MockCompoundParser:
+    """
+    A compound parser reads a doxygen XML file from disk; this mock implements
+    a mapping of what would be the file name on disk to data using a dict.
+    """
+    def __init__(self, compound_dict):
+        self.compound_dict = compound_dict
+
+    class MockFileData:
+        def __init__(self, compounddef):
+            self.compounddef = compounddef
+
+    def parse(self, compoundname):
+        compounddef = self.compound_dict[compoundname]
+        return self.MockFileData(compounddef)
+
+
 class NodeFinder(nodes.NodeVisitor):
     """Find node with specified class name."""
     def __init__(self, name, document):
@@ -224,9 +256,11 @@
                     'the number of nodes Text is 2')
 
 
-def render(app, member_def, domain=None, show_define_initializer=False):
+def render(app, member_def, domain=None, show_define_initializer=False,
+           compound_parser=None, options=[]):
     """Render Doxygen *member_def* with *renderer_class*."""
 
+    app.config.breathe_separate_member_pages = False
     app.config.breathe_use_project_refids = False
     app.config.breathe_show_define_initializer = show_define_initializer
     app.config.breathe_debug_trace_directives = False
@@ -238,9 +272,9 @@
                               None,  # state
                               None,  # document
                               MockTargetHandler(),
-                              None,   # compound_parser
+                              compound_parser,
                               OpenFilter())
-    renderer.context = MockContext(app, [member_def], domain)
+    renderer.context = MockContext(app, [member_def], domain, options)
     return renderer.render(member_def)
 
 
@@ -346,3 +380,24 @@
     member_def = WrappedMemberDef(kind='define', name='USE_MILK')
     signature = find_node(render(app, member_def), 'desc_signature')
     assert signature.astext() == 'USE_MILK'
+
+
+def test_render_innergroup(app):
+    refid = 'group__innergroup'
+    mock_compound_parser = MockCompoundParser({
+        refid: WrappedCompoundDef(kind='group',
+                                  compoundname='InnerGroup',
+                                  briefdescription='InnerGroup')
+    })
+    ref = WrappedRef('InnerGroup', refid=refid)
+    compound_def = WrappedCompoundDef(kind='group',
+                                      compoundname='OuterGroup',
+                                      briefdescription='OuterGroup',
+                                      innergroup=[ref])
+    assert all(el.astext() != 'InnerGroup'
+               for el in render(app, compound_def,
+                                compound_parser=mock_compound_parser))
+    assert any(el.astext() == 'InnerGroup'
+               for el in render(app, compound_def,
+                                compound_parser=mock_compound_parser,
+                                options=['inner']))


Reply via email to