Exhale Graph Module
Helper Class ExhaleNode Reference
- class exhale.graph.ExhaleNode(name, kind, refid)[source]
A wrapper class to track parental relationships, filenames, etc.
- Parameters
name
(str)The name of the compound.
kind
(str)The kind of the compound (see
AVAILABLE_KINDS
).refid
(str)The reference ID that Doxygen has associated with this compound.
- Attributes
kind
(str)The value of the
kind
parameter.name
(str)The value of the
name
parameter.refid
(str)The value of the
refid
parameter.children
(list)A potentially empty list of
ExhaleNode
object references that are considered a child of this Node. Please note that a child reference in anychildren
list may be stored in many other lists. Mutating a given child will mutate the object, and therefore affect other parents of this child. Lastly, a node of kindenum
will never have itsenumvalue
children as it is impossible to rebuild that relationship without more Doxygen xml parsing.parent
(ExhaleNode
)If an ExhaleNode is determined to be a child of another ExhaleNode, this node will be added to its parent’s
children
list, and a reference to the parent will be in this field. Initialized toNone
, make sure you check that it is an object first.Warning
Do not ever set the
parent
of a given node if the would-be parent’s kind is"file"
. Doing so will break many important relationships, such as nested class definitions. Effectively, every node will be added as a child to a file node at some point. The file node will track this, but the child should not.
The following three member variables are stored internally, but managed externally by the
ExhaleRoot
class:file_name
(str)The name of the file to create. Set to
None
on creation, refer toinitializeNodeFilenameAndLink()
.link_name
(str)The name of the reStructuredText link that will be at the top of the file. Set to
None
on creation, refer toinitializeNodeFilenameAndLink()
.title
(str)The title that will appear at the top of the reStructuredText file
file_name
. When the reStructuredText document for this node is being written, the root object will set this field.
The following two fields are used for tracking what has or has not already been included in the hierarchy views. Things like classes or structs in the global namespace will not be found by
inClassHierarchy()
, and the ExhaleRoot object will need to track which ones were missed.in_class_hierarchy
(bool)Whether or not this node has already been incorporated in the class view.
in_file_hierarchy
(bool)Whether or not this node has already been incorporated in the file view.
This class wields duck typing. If
self.kind == "file"
, then the additional member variables below exist:namespaces_used
(list)A list of namespace nodes that are either defined or used in this file.
includes
(list)A list of strings that are parsed from the Doxygen xml for this file as include directives.
included_by
(list)A list of (refid, name) string tuples that are parsed from the Doxygen xml for this file presenting all of the other files that include this file. They are stored this way so that the root class can later link to that file by its refid.
location
(str)A string parsed from the Doxygen xml for this file stating where this file is physically in relation to the Doxygen root.
program_listing
(list)A list of strings that is the Doxygen xml <programlisting>, without the opening or closing <programlisting> tags.
program_file
(list)Managed externally by the root similar to
file_name
etc, this is the name of the file that will be created to display the program listing if it exists. Set toNone
on creation, refer toinitializeNodeFilenameAndLink()
.program_link_name
(str)Managed externally by the root similar to
file_name
etc, this is the reStructuredText link that will be declared at the top of theprogram_file
. Set toNone
on creation, refer toinitializeNodeFilenameAndLink()
.
- __lt__(other)[source]
The
ExhaleRoot
class stores a bunch of lists ofExhaleNode
objects. When these lists are sorted, this method will be called to perform the sorting.- Parameters
other
(ExhaleNode)The node we are comparing whether
self
is less than or not.
- Return (bool)
True if
self
is less thanother
, False otherwise.
- set_owner(root)[source]
Sets the
ExhaleRoot
ownerself.root_owner
.
- breathe_identifier()[source]
The unique identifier for breathe directives.
Note
This method is currently assumed to only be called for nodes that are in
exhale.utils.LEAF_LIKE_KINDS
(see alsoexhale.graph.ExhaleRoot.generateSingleNodeRST()
where it is used).Return
str
Usually, this will just be
self.name
. However, for functions in particular the signature must be included to distinguish overloads.
- full_signature()[source]
The full signature of a
"function"
node.- Return
str
The full signature of the function, including template, return type, name, and parameter types.
- Raises
RuntimeError
If
self.kind != "function"
.
- templateParametersStringAsRestList(nodeByRefid)[source]
Todo
document this, create another method for creating this without the need for generating links, to be used in making the node titles and labels
- baseOrDerivedListString(lst, nodeByRefid)[source]
Todo
long time from now: intersphinx should be possible here
- findNestedNamespaces(lst)[source]
Recursive helper function for finding nested namespaces. If this node is a namespace node, it is appended to
lst
. Each node also calls each of its childfindNestedNamespaces
with the same list.- Parameters
lst
(list)The list each namespace node is to be appended to.
- findNestedDirectories(lst)[source]
Recursive helper function for finding nested directories. If this node is a directory node, it is appended to
lst
. Each node also calls each of its childfindNestedDirectories
with the same list.- Parameters
lst
(list)The list each directory node is to be appended to.
- findNestedClassLike(lst)[source]
Recursive helper function for finding nested classes and structs. If this node is a class or struct, it is appended to
lst
. Each node also calls each of its childfindNestedClassLike
with the same list.- Parameters
lst
(list)The list each class or struct node is to be appended to.
- findNestedEnums(lst)[source]
Recursive helper function for finding nested enums. If this node is a class or struct it may have had an enum added to its child list. When this occurred, the enum was removed from
self.enums
in theExhaleRoot
class and needs to be rediscovered by calling this method on all of its children. If this node is an enum, it is because a parent class or struct called this method, in which case it is added tolst
.Note: this is used slightly differently than nested directories, namespaces, and classes will be. Refer to
generateNodeDocuments()
.- Parameters
lst
(list)The list each enum is to be appended to.
- findNestedUnions(lst)[source]
Recursive helper function for finding nested unions. If this node is a class or struct it may have had a union added to its child list. When this occurred, the union was removed from
self.unions
in theExhaleRoot
class and needs to be rediscovered by calling this method on all of its children. If this node is a union, it is because a parent class or struct called this method, in which case it is added tolst
.Note: this is used slightly differently than nested directories, namespaces, and classes will be. Refer to
generateNodeDocuments()
.- Parameters
lst
(list)The list each union is to be appended to.
- toConsole(level, fmt_spec, printChildren=True)[source]
Debugging tool for printing hierarchies / ownership to the console. Recursively calls children
toConsole
if this node is not a directory or a file, andprintChildren == True
.Todo
fmt_spec docs needed. keys are
kind
and values are color spec- Parameters
level
(int)The indentation level to be used, should be greater than or equal to 0.
printChildren
(bool)Whether or not the
toConsole
method for the children found inself.children
should be called withlevel+1
. Default is True, set to False for directories and files.
- typeSort()[source]
Sorts
self.children
in place, and has each child sort its own children. Refer todeepSortList()
for more information on when this is necessary.
- inPageHierarchy()[source]
Whether or not this node should be included in the page view hierarchy. Helper method for
toHierarchy()
. Sets the member variableself.in_page_hierarchy
to True if appropriate.- Return (bool)
True if this node should be included in the page view — if it is a node of kind
page
. Returns False otherwise.
- inClassHierarchy()[source]
Whether or not this node should be included in the class view hierarchy. Helper method for
toHierarchy()
. Sets the member variableself.in_class_hierarchy
to True if appropriate.- Return (bool)
True if this node should be included in the class view — either it is a node of kind
struct
,class
,enum
,union
, or it is anamespace
that one or more if its descendants was one of the previous four kinds. Returns False otherwise.
- inFileHierarchy()[source]
Whether or not this node should be included in the file view hierarchy. Helper method for
toHierarchy()
. Sets the member variableself.in_file_hierarchy
to True if appropriate.- Return (bool)
True if this node should be included in the file view — either it is a node of kind
file
, or it is adir
that one or more if its descendants was afile
. Returns False otherwise.
- toHierarchy(hierarchyType, level, stream, lastChild=False)[source]
- Parameters
hierarchyType
(str)"page"
if generating the Page Hierarchy,"class"
if generating the Class Hierarchy,"file"
if generating the File Hierarchy.level
(int)Recursion level used to determine indentation.
stream
(StringIO)The stream to write the contents to.
lastChild
(bool)When
createTreeView
isTrue
andtreeViewIsBootstrap
isFalse
, the generated HTMLli
elements need to add aclass="lastChild"
to use the appropriate styling.
Todo
add thorough documentation of this
- __weakref__
list of weak references to the object (if defined)
Primary Class ExhaleRoot Reference
- class exhale.graph.ExhaleRoot[source]
The full representation of the hierarchy graphs. In addition to containing specific lists of ExhaleNodes of interest, the ExhaleRoot class is responsible for comparing the parsed breathe hierarchy and rebuilding lost relationships using the Doxygen xml files. Once the graph parsing has finished, the ExhaleRoot generates all of the relevant reStructuredText documents and links them together.
The ExhaleRoot class is not designed for reuse at this time. If you want to generate a new hierarchy with a different directory or something, changing all of the right fields may be difficult and / or unsuccessful. Refer to the
explode()
function for intended usage.Danger
Zero checks are in place to enforce this usage, and if you are modifying the execution of this class and things are not working make sure you follow the ordering of those methods.
Todo
many attributes currently stored do not need to be, refactor in future release to just use the
configs
module.- Attributes
root_directory
(str)The value of the parameter
rootDirectory
.root_file_name
(str)The value of the parameter
rootFileName
.full_root_file_path
(str)The full file path of the root file (
"root_directory/root_file_name"
).class_hierarchy_file
(str)The full file path the class view hierarchy will be written to. This is incorporated into
root_file_name
using an.. include:
directive.file_hierarchy_file
(str)The full file path the file view hierarchy will be written to. This is incorporated into
root_file_name
using an.. include:
directive.unabridged_api_file
(str)The full file path the full API will be written to. This is incorporated into
root_file_name
using a.. toctree:
directive with a:maxdepth:
according to the value offullToctreeMaxDepth
.use_tree_view
(bool)The value of the parameter
createTreeView
.all_compounds
(list)A list of all the Breathe compound objects discovered along the way. Populated during
discoverAllNodes()
.all_nodes
(list)A list of all of the ExhaleNode objects created. Populated during
discoverAllNodes()
.node_by_refid
(dict)A dictionary with string ExhaleNode
refid
values, and values that are the ExhaleNode it came from. Storing it this way is convenient for when the Doxygen xml file is being parsed.class_like
(list)The full list of ExhaleNodes of kind
struct
orclass
defines
(list)The full list of ExhaleNodes of kind
define
.enums
(list)The full list of ExhaleNodes of kind
enum
.enum_values
(list)The full list of ExhaleNodes of kind
enumvalue
. Populated, not used.functions
(list)The full list of ExhaleNodes of kind
function
.dirs
(list)The full list of ExhaleNodes of kind
dir
.files
(list)The full list of ExhaleNodes of kind
file
.groups
(list)The full list of ExhaleNodes of kind
group
. Pupulated, not used.namespaces
(list)The full list of ExhaleNodes of kind
namespace
.typedefs
(list)The full list of ExhaleNodes of kind
typedef
.unions
(list)The full list of ExhaleNodes of kind
union
.variables
(list)The full list of ExhaleNodes of kind
variable
.
- parse()[source]
The first method that should be called after creating an ExhaleRoot object. The Breathe graph is parsed first, followed by the Doxygen xml documents. By the end of this method, all of the
self.<breathe_kind>
,self.all_compounds
, andself.all_nodes
lists as well as theself.node_by_refid
dictionary will be populated. Lastly, this method sorts all of the internal lists. The order of execution is exactlyPopulate
self.node_by_refid
usingself.all_nodes
.
- trackNodeIfUnseen(node)[source]
Helper method for
discoverAllNodes()
. If the node is not in self.all_nodes yet, add it to both self.all_nodes as well as the correspondingself.<breathe_kind>
list.- Parameters
node
(ExhaleNode)The node to begin tracking if not already present.
- reparentAll()[source]
Fixes some of the parental relationships lost in parsing the Breathe graph. File relationships are recovered in
fileRefDiscovery()
. This method simply calls in this order:
- reparentUnions()[source]
Helper method for
reparentAll()
. Namespaces and classes should have the unions defined in them to be in the child list of itself rather than floating around. Union nodes that are reparented (e.g. a union defined in a class) will be removed from the listself.unions
since the Breathe directive for its parent (e.g. the class) will include the documentation for the union. The consequence of this is that a union defined in a class will not appear in the full api listing of Unions.
- reparentClassLike()[source]
Helper method for
reparentAll()
. Iterates over theself.class_like
list and adds each object as a child to a namespace if the class, or struct is a member of that namespace. Many classes / structs will be reparented to a namespace node, these will remain inself.class_like
. However, if a class or struct is reparented to a different class or struct (it is a nested class / struct), it will be removed from so that the class view hierarchy is generated correctly.
- reparentDirectories()[source]
Helper method for
reparentAll()
. Adds subdirectories as children to the relevant directory ExhaleNode. If a node inself.dirs
is added as a child to a different directory node, it is removed from theself.dirs
list.
- renameToNamespaceScopes()[source]
Helper method for
reparentAll()
. Some compounds in Breathe such as functions and variables do not have the namespace name they are declared in before the name of the actual compound. This method prepends the appropriate (nested) namespace name before the name of any child that does not already have it.For example, the variable
MAX_DEPTH
declared in namespaceexternal
would have its ExhaleNode’sname
attribute changed fromMAX_DEPTH
toexternal::MAX_DEPTH
.
- reparentNamespaces()[source]
Helper method for
reparentAll()
. Adds nested namespaces as children to the relevant namespace ExhaleNode. If a node inself.namespaces
is added as a child to a different namespace node, it is removed from theself.namespaces
list. Because these are removed fromself.namespaces
, it is important thatrenameToNamespaceScopes()
is called before this method.
- fileRefDiscovery()[source]
Finds the missing components for file nodes by parsing the Doxygen xml (which is just the
doxygen_output_dir/node.refid
). Additional items parsed include adding items whoserefid
tag are used in this file, the <programlisting> for the file, what it includes and what includes it, as well as the location of the file (with respsect to the Doxygen root).Care must be taken to only include a refid found with specific tags. The parsing of the xml file was done by just looking at some example outputs. It seems to be working correctly, but there may be some subtle use cases that break it.
Warning
Some enums, classes, variables, etc declared in the file will not have their associated refid in the declaration of the file, but will be present in the <programlisting>. These are added to the files’ list of children when they are found, but this parental relationship cannot be formed if you set
XML_PROGRAMLISTING = NO
with Doxygen. An example of such an enum would be an enum declared inside of a namespace within this file.
- filePostProcess()[source]
The real name of this method should be
reparentFiles
, but to avoid confusion with what stage this must happen at it is called this instead. After thefileRefDiscovery()
method has been called, each file will have its location parsed. This method reparents files to directories accordingly, so the file view hierarchy can be complete.
- parseFunctionSignatures()[source]
Search file and namespace node XML contents for function signatures.
- sortInternals()[source]
Sort all internal lists (
class_like
,namespaces
,variables
, etc) mostly how doxygen would, alphabetical but also hierarchical (e.g. structs appear before classes in listings). Some internal lists are just sorted, and some are deep sorted (deepSortList()
).
- deepSortList(lst)[source]
For hierarchical internal lists such as
namespaces
, we want to sort both the list as well as have each child sort its children by callingtypeSort()
.- Parameters
lst
(list)The list of ExhaleNode objects to be deep sorted.
- generateFullAPI()[source]
Since we are not going to use some of the breathe directives (e.g. namespace or file), when representing the different views of the generated API we will need:
Generate a single file restructured text document for all of the nodes that have either no children, or children that are leaf nodes.
When building the view hierarchies (page, class, and file view and), provide a link to the appropriate files generated previously.
If adding onto the framework to say add another view (from future import groups) you would link from a restructured text document to one of the individually generated files using the value of
link_name
for a given ExhaleNode object.This method calls in this order:
- generateAPIRootHeader()[source]
This method creates the root library api file that will include all of the different hierarchy views and full api listing. The root API file is created and its title is written, as well as the value of
configs.afterTitleDescription
.
- generateNodeDocuments()[source]
Creates all of the reStructuredText documents related to types parsed by Doxygen. This includes all leaf-like documents (
class
,struct
,enum
,typedef
,union
,variable
, anddefine
), as well as namespace, file, and directory pages.During the reparenting phase of the parsing process, nested items were added as a child to their actual parent. For classes, structs, enums, and unions, if it was reparented to a
namespace
it will remain in its respectiveself.<breathe_kind>
list. However, if it was an internally declared child of a class or struct (nested classes, structs, enums, and unions), this node will be removed from itsself.<breathe_kind>
list to avoid duplication in the class hierarchy generation.When generating the full API, though, we will want to include all of these and therefore must call
generateSingleNodeRST()
with all of the nested items. For nested classes and structs, this is done by just callingnode.findNestedClassLike
for every node inself.class_like
. The resulting list then has all ofself.class_like
, as well as any nested classes and structs found. Withenum
andunion
, these would have been reparented to a class or struct if it was removed from the relevantself.<breathe_kind>
list. Meaning we must make sure that we genererate the single node RST documents for everything by finding the nested enums and unions fromself.class_like
, as well as everything inself.enums
andself.unions
.
- initializeNodeFilenameAndLink(node)[source]
Sets the
file_name
andlink_name
for the specified node. If the kind of this node is “file”, then this method will also set theprogram_file
as well as theprogram_link_name
fields.Since we are operating inside of a
containmentFolder
, this method will includeself.root_directory
in this path so that you can just use:with codecs.open(node.file_name, "w", "utf-8") as gen_file: # ... write the file ...
Having the
containmentFolder
is important for when we want to generate the file, but when we want to use it withinclude
ortoctree
this will need to change. Refer togerrymanderNodeFilenames()
.This method also sets the value of
node.title
, which will be used in both the reStructuredText document of the node as well as the links generated in the class view hierarchy (<a href=”…”> for thecreateTreeView = True
option).- Type
- Param
node The node that we are setting the above information for.
- generateSingleNodeRST(node)[source]
Creates the reStructuredText document for the leaf like node object.
It is assumed that the specified
node.kind
is inLEAF_LIKE_KINDS
. File, directory, and namespace nodes are treated separately.- Parameters
node
(ExhaleNode)The leaf like node being generated by this method.
- generateSinglePageDocument(node)[source]
Creates the reStructuredText document for a page.
- Parameters
node
(ExhaleNode)The “page” node being generated by this method.
- generateNamespaceNodeDocuments()[source]
Generates the reStructuredText document for every namespace, including nested namespaces that were removed from
self.namespaces
(but added as children to one of the namespaces inself.namespaces
).The documents generated do not use the Breathe namespace directive, but instead link to the relevant documents associated with this namespace.
- generateSingleNamespace(nspace)[source]
Helper method for
generateNamespaceNodeDocuments()
. Writes the reStructuredText file for the given namespace.- Parameters
nspace
(ExhaleNode)The namespace node to create the reStructuredText document for.
- generateNamespaceChildrenString(nspace)[source]
Helper method for
generateSingleNamespace()
, andgenerateFileNodeDocuments()
. Builds the body text for the namespace node document that links to all of the child namespaces, structs, classes, functions, typedefs, unions, and variables associated with this namespace.- Parameters
nspace
(ExhaleNode)The namespace node we are generating the body text for.
- Return (str)
The string to be written to the namespace node’s reStructuredText document.
- generateSortedChildListString(stream, sectionTitle, lst)[source]
Helper method for
generateNamespaceChildrenString()
. Used to build up a continuous string with all of the children separated out into titled sections.This generates a new titled section with
sectionTitle
and puts a link to every node found inlst
in this section. The newly created section is appended to the existingstream
buffer.- Parameters
stream
(StringIO)The already-open StringIO to write the result to.
sectionTitle
(str)The title of the section for this list of children.
lst
(list)A list of ExhaleNode objects that are to be linked to from this section. This method sorts
lst
in place.
- generateFileNodeDocuments()[source]
Generates the reStructuredText documents for files as well as the file’s program listing reStructuredText document if applicable. Refer to Page Level Customization for changing the output of this method. The remainder of the file lists all nodes that have been discovered to be defined (e.g. classes) or referred to (e.g. included files or files that include this file).
Todo
writing the actual file should be set in one method so that things for files, namespaces, and leaflike nodes don’t keep getting out of sync
- generateDirectoryNodeDocuments()[source]
Generates all of the directory reStructuredText documents.
- generateDirectoryNodeRST(node)[source]
Helper method for
generateDirectoryNodeDocuments()
. Generates the reStructuredText documents for the given directory node. Directory nodes will only link to files and subdirectories within it.- Parameters
node
(ExhaleNode)The directory node to generate the reStructuredText document for.
- generateAPIRootBody()[source]
Generates the root library api file’s body text. The method calls
gerrymanderNodeFilenames()
first to enable proper internal linkage between reStructuredText documents. Afterward, it callsgenerateViewHierarchies()
followed bygenerateUnabridgedAPI()
to generate both hierarchies as well as the full API listing. As a result, three files will now be ready:self.page_hierarchy_file
self.class_hierarchy_file
self.file_hierarchy_file
self.unabridged_api_file
These three files are then included into the root library file. The consequence of using an
include
directive is that Sphinx will complain about these three files never being included in anytoctree
directive. These warnings are expected, and preferred to using atoctree
because otherwise the user would have to click on the class view link from thetoctree
in order to see it. This behavior has been acceptable for me so far, but if it is causing you problems please raise an issue on GitHub and I may be able to conditionally use atoctree
if you really need it.
- gerrymanderNodeFilenames()[source]
When creating nodes, the filename needs to be relative to
conf.py
, so it will includeself.root_directory
. However, when generating the API, the file we are writing to is in the same directory as the generated node files so we need to remove the directory path from a given ExhaleNode’sfile_name
before we caninclude
it or use it in atoctree
.
- generateViewHierarchies()[source]
Wrapper method to create the view hierarchies. Currently it just calls
generatePageView()
,generateClassView()
, andgenerateDirectoryView()
— if you want to implement additional hierarchies, implement the additionaly hierarchy method and call it from here. Then make sure toinclude
it ingenerateAPIRootBody()
.
- generatePageView()[source]
Generates the pages view hierarchy, writing it to
self.page_hierarchy_file
.
- generateClassView()[source]
Generates the class view hierarchy, writing it to
self.class_hierarchy_file
.
- generateDirectoryView()[source]
Generates the file view hierarchy, writing it to
self.file_hierarchy_file
.
- generateUnabridgedAPI()[source]
Generates the unabridged (full) API listing into
self.unabridged_api_file
. This is necessary as some items may not show up in either hierarchy view, depending on:The item. For example, if a namespace has only one member which is a variable, then neither the namespace nor the variable will be declared in the class view hierarchy. It will be present in the file page it was declared in but not on the main library page.
The configurations of Doxygen. For example, see the warning in
fileRefDiscovery()
. Items whose parents cannot be rediscovered withouth the programlisting will still be documented, their link appearing in the unabridged API listing.
Currently, the API is generated in the following (somewhat arbitrary) order:
Namespaces
Classes and Structs
Enums
Unions
Functions
Variables
Defines
Typedefs
Directories
Files
- enumerateAll(subsectionTitle, lst, openFile)[source]
Helper function for
generateUnabridgedAPI()
. Simply writes a subsection toopenFile
(atoctree
to thefile_name
) of each ExhaleNode insorted(lst)
iflen(lst) > 0
. Otherwise, nothing is written to the file.- Parameters
subsectionTitle
(str)The title of this subsection, e.g.
"Namespaces"
or"Files"
.lst
(list)The list of ExhaleNodes to be enumerated in this subsection.
openFile
(File)The already open file object to write to directly. No safety checks are performed, make sure this is a real file object that has not been closed already.
- toConsole()[source]
Convenience function for printing out the entire API being generated to the console. Unused in the release, but is helpful for debugging ;)
- consoleFormat(sectionTitle, lst, fmt_spec)[source]
Helper method for
toConsole()
. Prints the givensectionTitle
and callstoConsole()
with0
as the level for every ExhaleNode inlst
.- Parameters
sectionTitle
(str)The title that will be printed with some visual separators around it.
lst
(list)The list of ExhaleNodes to print to the console.
- __weakref__
list of weak references to the object (if defined)