from six import itervalues
from lxml import etree as ET
-from sphinx.ext.autodoc import Documenter, AutoDirective, members_option, ALL
+from sphinx.ext.autodoc import Documenter, members_option, ALL
+try:
+ from sphinx.ext.autodoc import AutoDirective
+ sphinxVersion = 1
+except ImportError:
+ sphinxVersion = 2
from sphinx.errors import ExtensionError
from sphinx.util import logging
self.continue_line = True
def visit_parameterlist(self, node):
- lines = [l for l in type(self)().generic_visit(node).lines if l is not '']
+ lines = [l for l in type(self)().generic_visit(node).lines if l != '']
self.lines.extend([':parameters:', ''] + ['* %s' % l for l in lines] + [''])
def visit_simplesect(self, node):
'members': members_option,
}
- def __init__(self, directive, name, indent=u'', id=None):
+ def __init__(self, directive, name, indent=u'', my_id = None):
super(DoxygenDocumenter, self).__init__(directive, name, indent)
- if id is not None:
- self.parse_id(id)
+ if my_id is not None:
+ self.parse_id(my_id)
- def parse_id(self, id):
+ def parse_id(self, id_to_parse):
return False
def parse_name(self):
if '::' in self.name:
parts = self.name.split('::')
+ self.klassname = parts[-2]
self.objname = parts[-1]
else:
self.objname = self.name
+ self.klassname = ""
return True
directive = getattr(self, 'directivetype', self.objtype)
name = self.format_name()
sourcename = self.get_sourcename()
+ #print('.. %s:%s:: %s%s' % (domain, directive, name, sig))
self.add_line(u'.. %s:%s:: %s%s' % (domain, directive, name, sig),
sourcename)
# document non-skipped members
memberdocumenters = []
for (mname, member, isattr) in self.filter_members(members, want_all):
- classes = [cls for cls in itervalues(AutoDirective._registry)
- if cls.can_document_member(member, mname, isattr, self)]
+ if sphinxVersion >= 2:
+ classes = [cls for cls in itervalues(self.env.app.registry.documenters)
+ if cls.can_document_member(member, mname, isattr, self)]
+ else:
+ classes = [cls for cls in itervalues(AutoDirective._registry)
+ if cls.can_document_member(member, mname, isattr, self)]
if not classes:
# don't know how to document this member
continue
xpath_query = './/compoundname[text()="%s"]/..' % self.fullname
match = get_doxygen_root().xpath(xpath_query)
if len(match) != 1:
- raise ExtensionError('[autodoxy] could not find class (fullname="%s"). I tried'
+ raise ExtensionError('[autodoxy] could not find class (fullname="%s"). I tried '
'the following xpath: "%s"' % (self.fullname, xpath_query))
self.object = match[0]
def format_name(self):
return self.fullname
- def get_doc(self, encoding):
+ def get_doc(self, encoding=None): # This method is called with 1 parameter in Sphinx 2.x and 2 parameters in Sphinx 1.x
detaileddescription = self.object.find('detaileddescription')
doc = [format_xml_paragraph(detaileddescription)]
return doc
if want_all:
return False, ((m.find('name').text, m) for m in all_members)
- else:
- if not self.options.members:
- return False, []
- else:
- return False, ((m.find('name').text, m) for m in all_members
- if m.find('name').text in self.options.members)
+ if not self.options.members:
+ return False, []
+ return False, ((m.find('name').text, m) for m in all_members if m.find('name').text in self.options.members)
def filter_members(self, members, want_all):
ret = []
# Uncomment to view the generated rst for the class.
# print('\n'.join(self.directive.result))
+autodoxy_requalified_identifiers = []
+def fix_namespaces(str):
+ for unqualified,fullyqualif in autodoxy_requalified_identifiers:
+ p = re.compile("(^| ){:s}".format(unqualified))
+ str = p.sub(' {:s}'.format(fullyqualif), str)
+ return str
+
class DoxygenMethodDocumenter(DoxygenDocumenter):
objtype = 'doxymethod'
directivetype = 'function'
return True
return False
- def parse_id(self, id):
- xp = './/*[@id="%s"]' % id
+ def parse_id(self, id_to_parse):
+ xp = './/*[@id="%s"]' % id_to_parse
match = get_doxygen_root().xpath(xp)
- if len(match) > 0:
+ if match:
match = match[0]
self.fullname = match.find('./definition').text.split()[-1]
self.modname = self.fullname
# classname or method name
return True
- (obj, meth) = self.fullname.rsplit('::', 1)
+ if '::' in self.fullname:
+ (obj, meth) = self.fullname.rsplit('::', 1)
+ # 'public-func' and 'public-static-func' are for classes while 'func' alone is for namespaces
+ prefix = './/compoundname[text()="{:s}"]/../sectiondef[@kind="public-func" or @kind="public-static-func" or @kind="func"]'.format(obj)
+ obj = "{:s}::".format(obj)
+ else:
+ meth = self.fullname
+ prefix = './'
+ obj = ''
- xpath_query_noparam = ('.//compoundname[text()="{:s}"]/../sectiondef[@kind="public-func" or @kind="public-static-func"]'
- '/memberdef[@kind="function"]/name[text()="{:s}"]/..').format(obj, meth)
+ xpath_query_noparam = ('{:s}/memberdef[@kind="function"]/name[text()="{:s}"]/..').format(prefix, meth)
xpath_query = ""
-# print("fullname {}".format(self.fullname))
if self.argsstring != None:
- xpath_query = ('.//compoundname[text()="{:s}"]/../sectiondef[@kind="public-func" or @kind="public-static-func"]'
- '/memberdef[@kind="function" and argsstring/text()="{:s}"]/name[text()="{:s}"]/..').format(obj,self.argsstring,meth)
+ xpath_query = ('{:s}/memberdef[@kind="function" and argsstring/text()="{:s}"]/name[text()="{:s}"]/..').format(prefix,self.argsstring,meth)
else:
xpath_query = xpath_query_noparam
match = get_doxygen_root().xpath(xpath_query)
- if len(match) == 0:
+ if not match:
logger = logging.getLogger(__name__)
if self.argsstring != None:
candidates = get_doxygen_root().xpath(xpath_query_noparam)
if len(candidates) == 1:
- logger.warning("[autodoxy] Using method '{}::{}{}' instead of '{}::{}{}'. You may want to drop your specification of the signature, or to fix it."
- .format(obj, meth, candidates[0].find('argsstring').text, obj, meth, self.argsstring))
+ logger.warning("[autodoxy] Using method '{}{}{}' instead of '{}{}{}'. You may want to drop your specification of the signature, or to fix it."
+ .format(obj, meth, candidates[0].find('argsstring').text, obj, meth, self.argsstring))
self.object = candidates[0]
return True
- logger.warning("[autodoxy] WARNING: Could not find method {}::{}{}".format(obj, meth, self.argsstring))
+ logger.warning("[autodoxy] WARNING: Could not find method {}{}{}".format(obj, meth, self.argsstring))
+ if not candidates:
+ logger.warning("[autodoxy] WARNING: (no candidate found)")
for cand in candidates:
- logger.warning("[autodoxy] WARNING: Existing candidate: {}::{}{}".format(obj, meth, cand.find('argsstring').text))
+ logger.warning("[autodoxy] WARNING: Existing candidate: {}{}{}".format(obj, meth, cand.find('argsstring').text))
else:
- logger.warning("[autodoxy] WARNING: could not find method {}::{} in Doxygen files".format(obj, meth))
+ logger.warning("[autodoxy] WARNING: Could not find method {}{} in Doxygen files\nQuery: {}".format(obj, meth, xpath_query))
return False
self.object = match[0]
return True
- def get_doc(self, encoding):
+ def get_doc(self, encoding=None): # This method is called with 1 parameter in Sphinx 2.x and 2 parameters in Sphinx 1.x
detaileddescription = self.object.find('detaileddescription')
doc = [format_xml_paragraph(detaileddescription)]
return doc
rtype = rtype_el.text
# print("rtype: {}".format(rtype))
- signame = (rtype and (rtype + ' ') or '') + self.objname
+ signame = fix_namespaces((rtype and (rtype + ' ') or '') + self.klassname + "::"+ self.objname )
+# print("signame: '{}'".format(signame))
return self.format_template_name() + signame
def format_template_name(self):
types = [e.text for e in self.object.findall('templateparamlist/param/type')]
- if len(types) == 0:
+ if not types:
return ''
ret = 'template <%s>' % ','.join(types)
# print ("template: {}".format(ret))
return ret
def format_signature(self):
- args = self.object.find('argsstring').text
+ args = fix_namespaces(self.object.find('argsstring').text)
+# print ("signature: {}".format(args))
return args
def document_members(self, all_members=False):
'/memberdef[@kind="variable"]/name[text()="{:s}"]/..').format(obj, var)
# print("fullname {}".format(self.fullname))
match = get_doxygen_root().xpath(xpath_query)
- if len(match) == 0:
+ if not match:
logger = logging.getLogger(__name__)
logger.warning("[autodoxy] WARNING: could not find variable {}::{} in Doxygen files".format(obj, var))
self.object = match[0]
return True
- def parse_id(self, id):
- xp = './/*[@id="%s"]' % id
+ def parse_id(self, id_to_parse):
+ xp = './/*[@id="%s"]' % id_to_parse
match = get_doxygen_root().xpath(xp)
- if len(match) > 0:
+ if match:
match = match[0]
self.fullname = match.find('./definition').text.split()[-1]
self.modname = self.fullname
else:
rtype = rtype_el.text
- # print("rtype: {}".format(rtype))
- signame = (rtype and (rtype + ' ') or '') + self.objname
- return self.format_template_name() + signame
+# print("rtype: {}".format(rtype))
+ signame = (rtype and (rtype + ' ') or '') + self.klassname + "::" + self.objname
+ return fix_namespaces(self.format_template_name() + signame)
- def get_doc(self, encoding):
+ def get_doc(self, encoding=None): # This method is called with 1 parameter in Sphinx 2.x and 2 parameters in Sphinx 1.x
detaileddescription = self.object.find('detaileddescription')
doc = [format_xml_paragraph(detaileddescription)]
return doc
def format_template_name(self):
types = [e.text for e in self.object.findall('templateparamlist/param/type')]
- if len(types) == 0:
+ if not types:
return ''
ret = 'template <%s>' % ','.join(types)
# print ("template: {}".format(ret))
files = [os.path.join(app.config.doxygen_xml, f)
for f in os.listdir(app.config.doxygen_xml)
if f.lower().endswith('.xml') and not f.startswith('._')]
- if len(files) == 0:
+ if not files:
raise err
setup.DOXYGEN_ROOT = ET.ElementTree(ET.Element('root')).getroot()
- for file in files:
- root = ET.parse(file).getroot()
+ for current_file in files:
+ root = ET.parse(current_file).getroot()
for node in root:
setup.DOXYGEN_ROOT.append(node)
+ if app.config.autodoxy_requalified_identifiers is not None:
+ global autodoxy_requalified_identifiers
+ autodoxy_requalified_identifiers = app.config.autodoxy_requalified_identifiers
def get_doxygen_root():
"""Get the root element of the doxygen XML document.
app.add_autodocumenter(DoxygenMethodDocumenter)
app.add_autodocumenter(DoxygenVariableDocumenter)
app.add_config_value("doxygen_xml", "", True)
+ app.add_config_value("autodoxy_requalified_identifiers", [], True)
# app.add_directive('autodoxysummary', DoxygenAutosummary)
# app.add_directive('autodoxyenum', DoxygenAutoEnum)