def discoverAllNodes(self):
        '''
        .. todo:: node discovery has changed, breathe no longer used...update docs
        '''
        doxygen_index_xml = os.path.join(
            configs._doxygen_xml_output_directory,
            "index.xml"
        )
        try:
            with codecs.open(doxygen_index_xml, "r", "utf-8") as index:
                index_contents = index.read()
        except:
            raise RuntimeError("Could not read the contents of [{0}].".format(doxygen_index_xml))

        try:
            index_soup = BeautifulSoup(index_contents, "lxml-xml")
        except:
            raise RuntimeError("Could not parse the contents of [{0}] as an xml.".format(doxygen_index_xml))

        doxygen_root = index_soup.doxygenindex
        if not doxygen_root:
            raise RuntimeError(
                "Did not find root XML node named 'doxygenindex' parsing [{0}].".format(doxygen_index_xml)
            )

        for compound in doxygen_root.find_all("compound"):
            if compound.find("name") and "kind" in compound.attrs and "refid" in compound.attrs:
                curr_name  = compound.find("name").get_text()
                curr_kind  = compound.attrs["kind"]
                curr_refid = compound.attrs["refid"]
                curr_node  = ExhaleNode(curr_name, curr_kind, curr_refid)
                self.trackNodeIfUnseen(curr_node)

                # For things like files and namespaces, a "member" list will include
                # things like defines, enums, etc.  For classes and structs, we don't
                # need to pay attention because the members are the various methods or
                # data members by the class
                if curr_kind in ["file", "namespace"]:
                    for member in compound.find_all("member"):
                        if member.find("name") and "kind" in member.attrs and "refid" in member.attrs:
                            child_name  = member.find("name").get_text()
                            child_kind  = member.attrs["kind"]
                            child_refid = member.attrs["refid"]
                            child_node  = ExhaleNode(child_name, child_kind, child_refid)
                            self.trackNodeIfUnseen(child_node)

                            if curr_kind == "namespace":
                                child_node.parent = curr_node
                            else:  # curr_kind == "file"
                                child_node.def_in_file = curr_node

                            curr_node.children.append(child_node)

        # Now that we have discovered everything, we need to explicitly parse the file
        # xml documents to determine where leaf-like nodes have been declared.
        #
        # TODO: change formatting of namespace to provide a listing of all files using it
        for f in self.files:
            node_xml_contents = utils.nodeCompoundXMLContents(f)
            if node_xml_contents:
                try:
                    f.soup = BeautifulSoup(node_xml_contents, "lxml-xml")
                except:
                    utils.fancyError("Unable to parse file xml [{0}]:".format(f.name))

                try:
                    cdef = f.soup.doxygen.compounddef

                    if "language" in cdef.attrs:
                        f.language = cdef.attrs["language"]

                    err_non = "[CRITICAL] did not find refid [{0}] in `self.node_by_refid`."
                    err_dup = "Conflicting file definition: [{0}] appears to be defined in both [{1}] and [{2}]."  # noqa
                    # process classes
                    inner_classes = cdef.find_all("innerclass", recursive=False)

                    # << verboseBuild
                    utils.verbose_log(
                        "*** [{0}] had [{1}] innerclasses found".format(f.name, len(inner_classes)),
                        utils.AnsiColors.BOLD_MAGENTA
                    )

                    for class_like in inner_classes:
                        if "refid" in class_like.attrs:
                            refid = class_like.attrs["refid"]
                            if refid in self.node_by_refid:
                                node = self.node_by_refid[refid]

                                # << verboseBuild
                                utils.verbose_log(
                                    "    - [{0}]".format(node.name),
                                    utils.AnsiColors.BOLD_MAGENTA
                                )

                                if not node.def_in_file:
                                    node.def_in_file = f
                                elif node.def_in_file != f:
                                    # << verboseBuild
                                    utils.verbose_log(
                                        err_dup.format(node.name, node.def_in_file.name, f.name),
                                        utils.AnsiColors.BOLD_YELLOW
                                    )
                            else:
                                # << verboseBuild
                                utils.verbose_log(err_non.format(refid), utils.AnsiColors.BOLD_RED)
                        else:
                            # TODO: can this ever happen?
                            # << verboseBuild
                            catastrophe  = "CATASTROPHIC: doxygen xml for `{0}` found `innerclass` [{1}] that"
                            catastrophe += " does *NOT* have a `refid` attribute!"
                            catastrophe  = catastrophe.format(f, str(class_like))
                            utils.verbose_log(
                                utils.prefix("(!) ", catastrophe),
                                utils.AnsiColors.BOLD_RED
                            )

                    # try and find anything else
                    memberdefs = cdef.find_all("memberdef", recursive=False)

                    # << verboseBuild
                    utils.verbose_log(
                        "*** [{0}] had [{1}] memberdef".format(f.name, len(memberdefs)),
                        utils.AnsiColors.BOLD_MAGENTA
                    )

                    for member in cdef.find_all("memberdef", recursive=False):
                        if "id" in member.attrs:
                            refid = member.attrs["id"]
                            if refid in self.node_by_refid:
                                node = self.node_by_refid[refid]

                                # << verboseBuild
                                utils.verbose_log(
                                    "    - [{0}]".format(node.name),
                                    utils.AnsiColors.BOLD_MAGENTA
                                )

                                if not node.def_in_file:
                                    node.def_in_file = f

                    # the location of the file as determined by doxygen
                    location = cdef.find("location")
                    if location and "file" in location.attrs:
                        location_str = os.path.normpath(location.attrs["file"])
                        # some older versions of doxygen don't reliably strip from path
                        # so make sure to remove it
                        abs_strip_path = os.path.normpath(os.path.abspath(
                            configs.doxygenStripFromPath
                        ))
                        if location_str.startswith(abs_strip_path):
                            location_str = os.path.relpath(location_str, abs_strip_path)
                        f.location = os.path.normpath(location_str)

                except:
                    utils.fancyError(
                        "Could not process Doxygen xml for file [{0}]".format(f.name)
                    )

        ###### TODO: explain how the parsing works // move it to exhale.parse
        # last chance: we will still miss some, but need to pause and establish namespace relationships
        for nspace in self.namespaces:
            node_xml_contents = utils.nodeCompoundXMLContents(nspace)
            if node_xml_contents:
                try:
                    name_soup = BeautifulSoup(node_xml_contents, "lxml-xml")
                except:
                    continue

                cdef = name_soup.doxygen.compounddef
                for class_like in cdef.find_all("innerclass", recursive=False):
                    if "refid" in class_like.attrs:
                        refid = class_like.attrs["refid"]
                        if refid in self.node_by_refid:
                            node = self.node_by_refid[refid]
                            if node not in nspace.children:
                                nspace.children.append(node)
                                node.parent = nspace

                for nested_nspace in cdef.find_all("innernamespace", recursive=False):
                    if "refid" in nested_nspace.attrs:
                        refid = nested_nspace.attrs["refid"]
                        if refid in self.node_by_refid:
                            node = self.node_by_refid[refid]
                            if node not in nspace.children:
                                nspace.children.append(node)
                                node.parent = nspace

                # This is where things get interesting
                for sectiondef in cdef.find_all("sectiondef", recursive=False):
                    for memberdef in sectiondef.find_all("memberdef", recursive=False):
                        if "id" in memberdef.attrs:
                            refid = memberdef.attrs["id"]
                            if refid in self.node_by_refid:
                                node = self.node_by_refid[refid]
                                location = memberdef.find("location")
                                if location and "file" in location.attrs:
                                    filedef = os.path.normpath(location.attrs["file"])
                                    for f in self.files:
                                        if filedef == f.location:
                                            node.def_in_file = f
                                            if node not in f.children:
                                                f.children.append(node)
                                            break

        # Find the nodes that did not have their file location definition assigned
        missing_file_def            = {} # keys: refid, values: ExhaleNode
        missing_file_def_candidates = {} # keys: refid, values: ExhaleNode (file kind only!)
        for refid in self.node_by_refid:
            node = self.node_by_refid[refid]
            if node.def_in_file is None and node.kind not in ("file", "dir", "group", "namespace", "enumvalue"):
                missing_file_def[refid] = node
                missing_file_def_candidates[refid] = []

        # Some compounds like class / struct have their own XML file and if documented
        # correctly will have a <location> tag.  For example, one may need to add the
        #
        #     \class namespace::ClassName file_basename.hpp full/file/path/file_basename.hpp
        #
        # in order for the <location> tag to be generated.  And in the case of forward
        # declarations (e.g., for PIMPL patterns), in order for the class XML to be
        # generated at all it seems this must be used.
        #
        #     <?xml version='1.0' encoding='UTF-8' standalone='no'?>
        #     <doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.13">
        #       <compounddef id="classpimpl_1_1EarthImpl" kind="class" language="C++" prot="public">
        #         <compoundname>pimpl::EarthImpl</compoundname>
        #         <includes refid="earth_8hpp" local="no">include/pimpl/earth.hpp</includes>
        #         <briefdescription>
        #     <para>The <ref refid="classpimpl_1_1Earth" kindref="compound">Earth</ref> PIMPL. </para>    </briefdescription>
        #         <detaileddescription>
        #         </detaileddescription>
        #         <location file="include/pimpl/earth.hpp" line="30" column="1"/>
        #         <listofallmembers>
        #         </listofallmembers>
        #       </compounddef>
        #     </doxygen>
        #
        # So we're taking advantage of the fact that
        #
        #    namespace pimpl {
        #        /**
        #         * \class pimpl::EarthImpl earth.hpp include/pimpl/earth.hpp
        #         * \brief The Earth PIMPL.
        #         */
        #         class EarthImpl;
        #     }
        #
        # Has a <location file="include/pimpl/earth.hpp" line="30" column="1"/>
        #
        # TODO: clarify this in the docs?  You don't understand the full cause though.
        refid_removals = []
        for refid in missing_file_def:
            node = missing_file_def[refid]
            node_xml_contents = utils.nodeCompoundXMLContents(node)
            # None is returned when no {refid}.xml exists (e.g., for enum or union).
            if not node_xml_contents:
                pass

            try:
                node_soup = BeautifulSoup(node_xml_contents, "lxml-xml")
                cdef = node_soup.doxygen.compounddef
                location = cdef.find("location", recursive=False)
                if location and "file" in location.attrs:
                    file_path = os.path.normpath(location["file"])
                    for f in self.files:
                        if f.location == file_path:
                            node.def_in_file = f
                            f.children.append(node)
                            refid_removals.append(refid)
            except:
                pass

        # We found the def_in_file, don't parse the programlisting for these nodes.
        for refid in refid_removals:
            del missing_file_def[refid]

        # Go through every file and see if the refid associated with a node missing a
        # file definition location is present in the <programlisting>
        for f in self.files:
            cdef = f.soup.doxygen.compounddef
            # try and find things in the programlisting as a last resort
            programlisting = cdef.find("programlisting")
            if programlisting:
                for ref in programlisting.find_all("ref"):
                    if "refid" in ref.attrs:
                        refid = ref.attrs["refid"]
                        # be careful not to just consider any refid found, e.g. don't
                        # use the `compound` kindref's because those are just stating
                        # it was used in this file, not that it was declared here
                        if "kindref" in ref.attrs and ref.attrs["kindref"] == "member":
                            if refid in missing_file_def and f not in missing_file_def_candidates[refid]:
                                missing_file_def_candidates[refid].append(f)

        # For every refid missing a file definition location, see if we found it only
        # once in a file node's <programlisting>.  If so, assign that as the file the
        # node was defined in
        for refid in missing_file_def:
            node = missing_file_def[refid]
            candidates = missing_file_def_candidates[refid]
            # If only one found, life is good!
            if len(candidates) == 1:
                node.def_in_file = candidates[0]
                # << verboseBuild
                utils.verbose_log(utils.info(
                    "Manually setting file definition of {0} {1} to [{2}]".format(
                        node.kind, node.name, node.def_in_file.location
                    ),
                    utils.AnsiColors.BOLD_CYAN
                ))
            # More than one found, don't know what to do...
            elif len(candidates) > 1:
                # << verboseBuild
                err_msg = StringIO()
                err_msg.write(textwrap.dedent('''
                    While attempting to discover the file that Doxygen refid `{0}` was
                    defined in, more than one candidate was found.  The candidates were:
                '''.format(refid)))
                # NOTE: candidates should only ever contain File nodes (thus c.location
                #       should exist, and already be populated).
                for c in candidates:
                    err_msg.write("  - path=[{0}], refid={1}\n".format(c.location, c.refid))
                err_msg.write("\n")
                utils.verbose_log(utils.critical(err_msg.getvalue()))
            # NOTE: no 'else' clause here, a warning about no file link generated is
            #       produced when the rst file is written

        # now that all nodes have been discovered, process template parameters, and
        # coordinate any base / derived inheritance relationships
        for node in self.class_like:
            node_xml_contents = utils.nodeCompoundXMLContents(node)
            if node_xml_contents:
                try:
                    name_soup = BeautifulSoup(node_xml_contents, "lxml-xml")
                except:
                    utils.fancyError("Could not process [{0}]".format(
                        os.path.join(configs._doxygen_xml_output_directory, "{0}".format(node.refid))
                    ))

                try:
                    cdef = name_soup.doxygen.compounddef
                    tparams = cdef.find("templateparamlist", recursive=False)
                    #
                    # DANGER DANGER DANGER
                    # No, you may not build links directly right now.  Cuz they aren't initialized
                    #

                    # first, find template parameters
                    if tparams:
                        for param in tparams.find_all("param", recursive=False):
                            # Doxygen seems to produce unreliable results.  For example,
                            # sometimes you will get `param.type <- class X` with empty
                            # decloname and defname, and sometimes you will get
                            # `param.type <- class` and declname `X`.  Similar behavior
                            # is observed with `typename X`.  These are generally just
                            # ignored (falling in the broader category of a typename)
                            #
                            # Sometimes you will get a refid in the type, so deal with
                            # that as they come too (yay)!
                            param_t = param.type
                            decl_n  = param.declname
                            def_n   = param.defname

                            # TODO: this doesn't seem to happen, should probably investigate more
                            # do something with `param.defval` ?

                            # By the end:
                            # param_t <- (None | str, str) tuple
                            #             ^^^^^^^^^^
                            #             only a refid, or None
                            # decl_n  <- str; declared name
                            # def_n   <- None | str; defined name
                            #
                            # When decl_n and def_n are the same, this means no explicit
                            # default template parameter is given.  This will ultimately
                            # mean that def_n is set to None for consistency.
                            if param_t.ref:
                                if "refid" in param_t.ref.attrs:
                                    refid = param_t.ref.attrs["refid"]
                                else:
                                    # I hope this never happens.
                                    refid = None
                                param_t = (refid, param_t.ref.string)
                            else:
                                param_t = (None, param_t.string)

                            # Right now these are the soup tags, get the strings
                            if decl_n:
                                decl_n = decl_n.string
                            if def_n:
                                def_n  = def_n.string

                            # Unset def_n if same as decl_n
                            if decl_n and def_n and decl_n == def_n:
                                def_n = None

                            node.template_params.append((param_t, decl_n, def_n))

                    def prot_ref_str(soup_node):
                        if "prot" in soup_node.attrs:
                            prot = soup_node.attrs["prot"]
                        else:
                            prot = None
                        if "refid" in soup_node.attrs:
                            refid = soup_node.attrs["refid"]
                        else:
                            refid = None
                        return (prot, refid, soup_node.string)

                    # Now see if there is a reference to any base classes
                    for base in cdef.find_all("basecompoundref", recursive=False):
                        node.base_compounds.append(prot_ref_str(base))

                    # Now see if there is a reference to any derived classes
                    for derived in cdef.find_all("derivedcompoundref", recursive=False):
                        node.derived_compounds.append(prot_ref_str(derived))
                except:
                    utils.fancyError("Error processing Doxygen XML for [{0}]".format(node.name), "txt")
def discoverAllNodes ( self ) : doxygen_index_xml = os . path . join ( configs . _doxygen_xml_output_directory , "index.xml" ) try : with codecs . open ( doxygen_index_xml , "r" , "utf-8" ) as index : index_contents = index . read ( ) except : raise RuntimeError ( "Could not read the contents of [{0}]." . format ( doxygen_index_xml ) ) try : index_soup = BeautifulSoup ( index_contents , "lxml-xml" ) except : raise RuntimeError ( "Could not parse the contents of [{0}] as an xml." . format ( doxygen_index_xml ) ) doxygen_root = index_soup . doxygenindex if not doxygen_root : raise RuntimeError ( "Did not find root XML node named 'doxygenindex' parsing [{0}]." . format ( doxygen_index_xml ) ) for compound in doxygen_root . find_all ( "compound" ) : if compound . find ( "name" ) and "kind" in compound . attrs and "refid" in compound . attrs : curr_name = compound . find ( "name" ) . get_text ( ) curr_kind = compound . attrs [ "kind" ] curr_refid = compound . attrs [ "refid" ] curr_node = ExhaleNode ( curr_name , curr_kind , curr_refid ) self . trackNodeIfUnseen ( curr_node ) if curr_kind in [ "file" , "namespace" ] : for member in compound . find_all ( "member" ) : if member . find ( "name" ) and "kind" in member . attrs and "refid" in member . attrs : child_name = member . find ( "name" ) . get_text ( ) child_kind = member . attrs [ "kind" ] child_refid = member . attrs [ "refid" ] child_node = ExhaleNode ( child_name , child_kind , child_refid ) self . trackNodeIfUnseen ( child_node ) if curr_kind == "namespace" : child_node . parent = curr_node else : child_node . def_in_file = curr_node curr_node . children . append ( child_node ) for f in self . files : node_xml_contents = utils . nodeCompoundXMLContents ( f ) if node_xml_contents : try : f . soup = BeautifulSoup ( node_xml_contents , "lxml-xml" ) except : utils . fancyError ( "Unable to parse file xml [{0}]:" . format ( f . name ) ) try : cdef = f . soup . doxygen . compounddef if "language" in cdef . attrs : f . language = cdef . attrs [ "language" ] err_non = "[CRITICAL] did not find refid [{0}] in `self.node_by_refid`." err_dup = "Conflicting file definition: [{0}] appears to be defined in both [{1}] and [{2}]." inner_classes = cdef . find_all ( "innerclass" , recursive = False ) utils . verbose_log ( "*** [{0}] had [{1}] innerclasses found" . format ( f . name , len ( inner_classes ) ) , utils . AnsiColors . BOLD_MAGENTA ) for class_like in inner_classes : if "refid" in class_like . attrs : refid = class_like . attrs [ "refid" ] if refid in self . node_by_refid : node = self . node_by_refid [ refid ] utils . verbose_log ( "    - [{0}]" . format ( node . name ) , utils . AnsiColors . BOLD_MAGENTA ) if not node . def_in_file : node . def_in_file = f elif node . def_in_file != f : utils . verbose_log ( err_dup . format ( node . name , node . def_in_file . name , f . name ) , utils . AnsiColors . BOLD_YELLOW ) else : utils . verbose_log ( err_non . format ( refid ) , utils . AnsiColors . BOLD_RED ) else : catastrophe = "CATASTROPHIC: doxygen xml for `{0}` found `innerclass` [{1}] that" catastrophe += " does *NOT* have a `refid` attribute!" catastrophe = catastrophe . format ( f , str ( class_like ) ) utils . verbose_log ( utils . prefix ( "(!) " , catastrophe ) , utils . AnsiColors . BOLD_RED ) memberdefs = cdef . find_all ( "memberdef" , recursive = False ) utils . verbose_log ( "*** [{0}] had [{1}] memberdef" . format ( f . name , len ( memberdefs ) ) , utils . AnsiColors . BOLD_MAGENTA ) for member in cdef . find_all ( "memberdef" , recursive = False ) : if "id" in member . attrs : refid = member . attrs [ "id" ] if refid in self . node_by_refid : node = self . node_by_refid [ refid ] utils . verbose_log ( "    - [{0}]" . format ( node . name ) , utils . AnsiColors . BOLD_MAGENTA ) if not node . def_in_file : node . def_in_file = f location = cdef . find ( "location" ) if location and "file" in location . attrs : location_str = os . path . normpath ( location . attrs [ "file" ] ) abs_strip_path = os . path . normpath ( os . path . abspath ( configs . doxygenStripFromPath ) ) if location_str . startswith ( abs_strip_path ) : location_str = os . path . relpath ( location_str , abs_strip_path ) f . location = os . path . normpath ( location_str ) except : utils . fancyError ( "Could not process Doxygen xml for file [{0}]" . format ( f . name ) ) for nspace in self . namespaces : node_xml_contents = utils . nodeCompoundXMLContents ( nspace ) if node_xml_contents : try : name_soup = BeautifulSoup ( node_xml_contents , "lxml-xml" ) except : continue cdef = name_soup . doxygen . compounddef for class_like in cdef . find_all ( "innerclass" , recursive = False ) : if "refid" in class_like . attrs : refid = class_like . attrs [ "refid" ] if refid in self . node_by_refid : node = self . node_by_refid [ refid ] if node not in nspace . children : nspace . children . append ( node ) node . parent = nspace for nested_nspace in cdef . find_all ( "innernamespace" , recursive = False ) : if "refid" in nested_nspace . attrs : refid = nested_nspace . attrs [ "refid" ] if refid in self . node_by_refid : node = self . node_by_refid [ refid ] if node not in nspace . children : nspace . children . append ( node ) node . parent = nspace for sectiondef in cdef . find_all ( "sectiondef" , recursive = False ) : for memberdef in sectiondef . find_all ( "memberdef" , recursive = False ) : if "id" in memberdef . attrs : refid = memberdef . attrs [ "id" ] if refid in self . node_by_refid : node = self . node_by_refid [ refid ] location = memberdef . find ( "location" ) if location and "file" in location . attrs : filedef = os . path . normpath ( location . attrs [ "file" ] ) for f in self . files : if filedef == f . location : node . def_in_file = f if node not in f . children : f . children . append ( node ) break missing_file_def = { } missing_file_def_candidates = { } for refid in self . node_by_refid : node = self . node_by_refid [ refid ] if node . def_in_file is None and node . kind not in ( "file" , "dir" , "group" , "namespace" , "enumvalue" ) : missing_file_def [ refid ] = node missing_file_def_candidates [ refid ] = [ ] refid_removals = [ ] for refid in missing_file_def : node = missing_file_def [ refid ] node_xml_contents = utils . nodeCompoundXMLContents ( node ) if not node_xml_contents : pass try : node_soup = BeautifulSoup ( node_xml_contents , "lxml-xml" ) cdef = node_soup . doxygen . compounddef location = cdef . find ( "location" , recursive = False ) if location and "file" in location . attrs : file_path = os . path . normpath ( location [ "file" ] ) for f in self . files : if f . location == file_path : node . def_in_file = f f . children . append ( node ) refid_removals . append ( refid ) except : pass for refid in refid_removals : del missing_file_def [ refid ] for f in self . files : cdef = f . soup . doxygen . compounddef programlisting = cdef . find ( "programlisting" ) if programlisting : for ref in programlisting . find_all ( "ref" ) : if "refid" in ref . attrs : refid = ref . attrs [ "refid" ] if "kindref" in ref . attrs and ref . attrs [ "kindref" ] == "member" : if refid in missing_file_def and f not in missing_file_def_candidates [ refid ] : missing_file_def_candidates [ refid ] . append ( f ) for refid in missing_file_def : node = missing_file_def [ refid ] candidates = missing_file_def_candidates [ refid ] if len ( candidates ) == 1 : node . def_in_file = candidates [ 0 ] utils . verbose_log ( utils . info ( "Manually setting file definition of {0} {1} to [{2}]" . format ( node . kind , node . name , node . def_in_file . location ) , utils . AnsiColors . BOLD_CYAN ) ) elif len ( candidates ) > 1 : err_msg = StringIO ( ) err_msg . write ( textwrap . dedent ( '''
                    While attempting to discover the file that Doxygen refid `{0}` was
                    defined in, more than one candidate was found.  The candidates were:
                ''' . format ( refid ) ) ) for c in candidates : err_msg . write ( "  - path=[{0}], refid={1}\n" . format ( c . location , c . refid ) ) err_msg . write ( "\n" ) utils . verbose_log ( utils . critical ( err_msg . getvalue ( ) ) ) for node in self . class_like : node_xml_contents = utils . nodeCompoundXMLContents ( node ) if node_xml_contents : try : name_soup = BeautifulSoup ( node_xml_contents , "lxml-xml" ) except : utils . fancyError ( "Could not process [{0}]" . format ( os . path . join ( configs . _doxygen_xml_output_directory , "{0}" . format ( node . refid ) ) ) ) try : cdef = name_soup . doxygen . compounddef tparams = cdef . find ( "templateparamlist" , recursive = False ) if tparams : for param in tparams . find_all ( "param" , recursive = False ) : param_t = param . type decl_n = param . declname def_n = param . defname if param_t . ref : if "refid" in param_t . ref . attrs : refid = param_t . ref . attrs [ "refid" ] else : refid = None param_t = ( refid , param_t . ref . string ) else : param_t = ( None , param_t . string ) if decl_n : decl_n = decl_n . string if def_n : def_n = def_n . string if decl_n and def_n and decl_n == def_n : def_n = None node . template_params . append ( ( param_t , decl_n , def_n ) ) def prot_ref_str ( soup_node ) : if "prot" in soup_node . attrs : prot = soup_node . attrs [ "prot" ] else : prot = None if "refid" in soup_node . attrs : refid = soup_node . attrs [ "refid" ] else : refid = None return ( prot , refid , soup_node . string ) for base in cdef . find_all ( "basecompoundref" , recursive = False ) : node . base_compounds . append ( prot_ref_str ( base ) ) for derived in cdef . find_all ( "derivedcompoundref" , recursive = False ) : node . derived_compounds . append ( prot_ref_str ( derived ) ) except : utils . fancyError ( "Error processing Doxygen XML for [{0}]" . format ( node . name ) , "txt" )
.. todo:: node discovery has changed, breathe no longer used...update docs