- make -j4
- pip3 install --requirement docs/requirements.txt
- cd docs
- - LC_ALL=C.UTF-8 SPHINXOPTS=-vv PYTHONPATH=/builds/simgrid/simgrid/docs/source/_ext/autodoxy ./Build.sh
+ - LC_ALL=C.UTF-8 SPHINXOPTS=-vv ./Build.sh
- mv build/html ../public
# - The CSS contains a reference to a font or something, not something we gonna fix on our side
# - The javasphinx output does not exist in the git, so the "edit on FramaGit" link is broken.
+"""
+This is autodoxy, a sphinx extension providing autodoc-like directives
+that are feed with Doxygen files.
+
+It is highly inspired from the autodoc_doxygen sphinx extension, but
+adapted to my own needs in SimGrid.
+https://github.com/rmcgibbo/sphinxcontrib-autodoc_doxygen
+
+Licence: MIT
+Copyright (c) 2015 Robert T. McGibbon
+Copyright (c) 2019 Martin Quinson
+"""
from __future__ import print_function, absolute_import, division
+import os.path
+import re
+import sys
+
from six import itervalues
from lxml import etree as ET
from sphinx.ext.autodoc import Documenter, AutoDirective, members_option, ALL
from sphinx.errors import ExtensionError
from sphinx.util import logging
-from . import get_doxygen_root
-from .xmlutils import format_xml_paragraph
-import sys
+##########################################################################
+# XML utils
+##########################################################################
+def format_xml_paragraph(xmlnode):
+ """Format an Doxygen XML segment (principally a detaileddescription)
+ as a paragraph for inclusion in the rst document
+
+ Parameters
+ ----------
+ xmlnode
+
+ Returns
+ -------
+ lines
+ A list of lines.
+ """
+ return [l.rstrip() for l in _DoxygenXmlParagraphFormatter().generic_visit(xmlnode).lines]
+
+
+class _DoxygenXmlParagraphFormatter(object):
+ # This class follows the model of the stdlib's ast.NodeVisitor for tree traversal
+ # where you dispatch on the element type to a different method for each node
+ # during the traverse.
+
+ # It's supposed to handle paragraphs, references, preformatted text (code blocks), and lists.
+
+ def __init__(self):
+ self.lines = ['']
+ self.continue_line = False
+
+ def visit(self, node):
+ method = 'visit_' + node.tag
+ visitor = getattr(self, method, self.generic_visit)
+ return visitor(node)
+
+ def generic_visit(self, node):
+ for child in node.getchildren():
+ self.visit(child)
+ return self
+
+ def visit_ref(self, node):
+ ref = get_doxygen_root().findall('.//*[@id="%s"]' % node.get('refid'))
+ if ref:
+ ref = ref[0]
+ if ref.tag == 'memberdef':
+ parent = ref.xpath('./ancestor::compounddef/compoundname')[0].text
+ name = ref.find('./name').text
+ real_name = parent + '::' + name
+ elif ref.tag in ('compounddef', 'enumvalue'):
+ name_node = ref.find('./name')
+ real_name = name_node.text if name_node is not None else ''
+ else:
+ raise NotImplementedError(ref.tag)
+ else:
+ real_name = None
+
+ val = [':cpp:any:`', node.text]
+ if real_name:
+ val.extend((' <', real_name, '>`'))
+ else:
+ val.append('`')
+ if node.tail is not None:
+ val.append(node.tail)
+
+ self.lines[-1] += ''.join(val)
+
+ def visit_para(self, node):
+ if node.text is not None:
+ if self.continue_line:
+ self.lines[-1] += node.text
+ else:
+ self.lines.append(node.text)
+ self.generic_visit(node)
+ self.lines.append('')
+ self.continue_line = False
+
+ def visit_verbatim(self, node):
+ if node.text is not None:
+ # remove the leading ' *' of any lines
+ lines = [re.sub('^\s*\*','', l) for l in node.text.split('\n')]
+ # Merge each paragraph together
+ text = re.sub("\n\n", "PaRaGrraphSplit", '\n'.join(lines))
+ text = re.sub('\n', '', text)
+ lines = text.split('PaRaGrraphSplit')
+
+ # merge content to the built doc
+ if self.continue_line:
+ self.lines[-1] += lines[0]
+ lines = lines[1:]
+ for l in lines:
+ self.lines.append('')
+ self.lines.append(l)
+ self.generic_visit(node)
+ self.lines.append('')
+ self.continue_line = False
+
+ def visit_parametername(self, node):
+ if 'direction' in node.attrib:
+ direction = '[%s] ' % node.get('direction')
+ else:
+ direction = ''
+
+ self.lines.append('**%s** -- %s' % (
+ node.text, direction))
+ self.continue_line = True
+
+ def visit_parameterlist(self, node):
+ lines = [l for l in type(self)().generic_visit(node).lines if l is not '']
+ self.lines.extend([':parameters:', ''] + ['* %s' % l for l in lines] + [''])
+
+ def visit_simplesect(self, node):
+ if node.get('kind') == 'return':
+ self.lines.append(':returns: ')
+ self.continue_line = True
+ self.generic_visit(node)
+
+ def visit_listitem(self, node):
+ self.lines.append(' - ')
+ self.continue_line = True
+ self.generic_visit(node)
+
+ def visit_preformatted(self, node):
+ segment = [node.text if node.text is not None else '']
+ for n in node.getchildren():
+ segment.append(n.text)
+ if n.tail is not None:
+ segment.append(n.tail)
+
+ lines = ''.join(segment).split('\n')
+ self.lines.extend(('.. code-block:: C++', ''))
+ self.lines.extend([' ' + l for l in lines])
+
+ def visit_computeroutput(self, node):
+ c = node.find('preformatted')
+ if c is not None:
+ return self.visit_preformatted(c)
+ return self.visit_preformatted(node)
+
+ def visit_xrefsect(self, node):
+ if node.find('xreftitle').text == 'Deprecated':
+ sublines = type(self)().generic_visit(node).lines
+ self.lines.extend(['.. admonition:: Deprecated'] + [' ' + s for s in sublines])
+ else:
+ raise ValueError(node)
+
+ def visit_subscript(self, node):
+ self.lines[-1] += '\ :sub:`%s` %s' % (node.text, node.tail)
+
+
+##########################################################################
+# Directives
+##########################################################################
+
class DoxygenDocumenter(Documenter):
# Variables to store the names of the object being documented. modname and fullname are redundant,
def document_members(self, all_members=False):
pass
+
+##########################################################################
+# Setup the extension
+##########################################################################
+def set_doxygen_xml(app):
+ """Load all doxygen XML files from the app config variable
+ `app.config.doxygen_xml` which should be a path to a directory
+ containing doxygen xml output
+ """
+ err = ExtensionError(
+ '[autodoxy] No doxygen xml output found in doxygen_xml="%s"' % app.config.doxygen_xml)
+
+ if not os.path.isdir(app.config.doxygen_xml):
+ raise err
+
+ 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:
+ raise err
+
+ setup.DOXYGEN_ROOT = ET.ElementTree(ET.Element('root')).getroot()
+ for file in files:
+ root = ET.parse(file).getroot()
+ for node in root:
+ setup.DOXYGEN_ROOT.append(node)
+
+
+def get_doxygen_root():
+ """Get the root element of the doxygen XML document.
+ """
+ if not hasattr(setup, 'DOXYGEN_ROOT'):
+ setup.DOXYGEN_ROOT = ET.Element("root") # dummy
+ return setup.DOXYGEN_ROOT
+
+
+def setup(app):
+ import sphinx.ext.autosummary
+
+ app.connect("builder-inited", set_doxygen_xml)
+# app.connect("builder-inited", process_generate_options)
+
+ app.setup_extension('sphinx.ext.autodoc')
+# app.setup_extension('sphinx.ext.autosummary')
+
+ app.add_autodocumenter(DoxygenClassDocumenter)
+ app.add_autodocumenter(DoxygenMethodDocumenter)
+ app.add_autodocumenter(DoxygenVariableDocumenter)
+ app.add_config_value("doxygen_xml", "", True)
+
+# app.add_directive('autodoxysummary', DoxygenAutosummary)
+# app.add_directive('autodoxyenum', DoxygenAutoEnum)
+
+ return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
+++ /dev/null
-This is autodoxy, a sphinx extension providing autodoc-like directives
-that are feed with Doxygen files.
-
-It is highly inspired from the autodoc_doxygen sphinx extension, but
-adapted to my own needs in SimGrid.
-https://github.com/rmcgibbo/sphinxcontrib-autodoc_doxygen
-
-The MIT License (MIT)
-
-Copyright (c) 2015 Robert T. McGibbon
-Copytight (c) 2019 Martin Quinson
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
+++ /dev/null
-import os.path
-from lxml import etree as ET
-from sphinx.errors import ExtensionError
-
-import sphinx.ext.autosummary
-from autodoxy import DoxygenClassDocumenter, DoxygenMethodDocumenter, DoxygenTypeDocumenter
-from autodoxy.autosummary import DoxygenAutosummary, DoxygenAutoEnum
-from autodoxy.autosummary.generate import process_generate_options
-
-def set_doxygen_xml(app):
- """Load all doxygen XML files from the app config variable
- `app.config.doxygen_xml` which should be a path to a directory
- containing doxygen xml output
- """
- err = ExtensionError(
- '[autodoxy] No doxygen xml output found in doxygen_xml="%s"' % app.config.doxygen_xml)
-
- if not os.path.isdir(app.config.doxygen_xml):
- raise err
-
- 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:
- raise err
-
- setup.DOXYGEN_ROOT = ET.ElementTree(ET.Element('root')).getroot()
- for file in files:
- root = ET.parse(file).getroot()
- for node in root:
- setup.DOXYGEN_ROOT.append(node)
-
-def get_doxygen_root():
- """Get the root element of the doxygen XML document.
- """
- if not hasattr(setup, 'DOXYGEN_ROOT'):
- setup.DOXYGEN_ROOT = ET.Element("root") # dummy
- return setup.DOXYGEN_ROOT
-
-def setup(app):
-
- app.connect("builder-inited", set_doxygen_xml)
- app.connect("builder-inited", process_generate_options)
-
- app.setup_extension('sphinx.ext.autodoc')
- app.setup_extension('sphinx.ext.autosummary')
-
- app.add_autodocumenter(DoxygenClassDocumenter)
- app.add_autodocumenter(DoxygenMethodDocumenter)
- app.add_autodocumenter(DoxygenTypeDocumenter)
- app.add_config_value("doxygen_xml", "", 'env')
- app.add_config_value('autosummary_toctree', '', 'html')
-
- app.add_directive('autodoxysummary', DoxygenAutosummary)
- app.add_directive('autodoxyenum', DoxygenAutoEnum)
-
- return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
+++ /dev/null
-import os.path
-from lxml import etree as ET
-from sphinx.errors import ExtensionError
-
-
-def set_doxygen_xml(app):
- """Load all doxygen XML files from the app config variable
- `app.config.doxygen_xml` which should be a path to a directory
- containing doxygen xml output
- """
- err = ExtensionError(
- '[autodoxy] No doxygen xml output found in doxygen_xml="%s"' % app.config.doxygen_xml)
-
- if not os.path.isdir(app.config.doxygen_xml):
- raise err
-
- 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:
- raise err
-
- setup.DOXYGEN_ROOT = ET.ElementTree(ET.Element('root')).getroot()
- for file in files:
- root = ET.parse(file).getroot()
- for node in root:
- setup.DOXYGEN_ROOT.append(node)
-
-
-def get_doxygen_root():
- """Get the root element of the doxygen XML document.
- """
- if not hasattr(setup, 'DOXYGEN_ROOT'):
- setup.DOXYGEN_ROOT = ET.Element("root") # dummy
- return setup.DOXYGEN_ROOT
-
-
-def setup(app):
- import sphinx.ext.autosummary
- from autodoxy.autodoxy import DoxygenClassDocumenter, DoxygenMethodDocumenter, DoxygenVariableDocumenter
- from autodoxy.autosummary import DoxygenAutosummary, DoxygenAutoEnum
- from autodoxy.autosummary.generate import process_generate_options
-
- app.connect("builder-inited", set_doxygen_xml)
- app.connect("builder-inited", process_generate_options)
-
- app.setup_extension('sphinx.ext.autodoc')
- app.setup_extension('sphinx.ext.autosummary')
-
- app.add_autodocumenter(DoxygenClassDocumenter)
- app.add_autodocumenter(DoxygenMethodDocumenter)
- app.add_autodocumenter(DoxygenVariableDocumenter)
- app.add_config_value("doxygen_xml", "", True)
-
- app.add_directive('autodoxysummary', DoxygenAutosummary)
- app.add_directive('autodoxyenum', DoxygenAutoEnum)
-
- return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
+++ /dev/null
-from __future__ import print_function, absolute_import, division
-
-import re
-import operator
-from functools import reduce
-from itertools import count, groupby
-
-from docutils import nodes
-from docutils.statemachine import ViewList
-from sphinx import addnodes
-from sphinx.ext.autosummary import Autosummary, autosummary_table
-
-from autodoxy import get_doxygen_root
-from autodoxy.autodoxy import DoxygenMethodDocumenter, DoxygenClassDocumenter
-from autodoxy.xmlutils import format_xml_paragraph
-
-
-def import_by_name(name, env=None, prefixes=None, i=0):
- """Get xml documentation for a class/method with a given name.
- If there are multiple classes or methods with that name, you
- can use the `i` kwarg to pick which one.
- """
- if prefixes is None:
- prefixes = [None]
-
- if env is not None:
- parent = env.ref_context.get('cpp:parent_symbol')
- parent_symbols = []
- while parent is not None and parent.identifier is not None:
- parent_symbols.insert(0, str(parent.identifier))
- parent = parent.parent
- prefixes.append('::'.join(parent_symbols))
-
- tried = []
- for prefix in prefixes:
- try:
- if prefix:
- prefixed_name = '::'.join([prefix, name])
- else:
- prefixed_name = name
- return _import_by_name(prefixed_name, i=i)
- except ImportError:
- tried.append(prefixed_name)
- raise ImportError('no module named %s' % ' or '.join(tried))
-
-
-def _import_by_name(name, i=0):
- root = get_doxygen_root()
- name = name.replace('.', '::')
-
- if '::' in name:
- xpath_query = (
- './/compoundname[text()="%s"]/../'
- 'sectiondef[@kind="public-func"]/memberdef[@kind="function"]/'
- 'name[text()="%s"]/..') % tuple(name.rsplit('::', 1))
- m = root.xpath(xpath_query)
- if len(m) > 0:
- obj = m[i]
- full_name = '.'.join(name.rsplit('::', 1))
- return full_name, obj, full_name, ''
-
- xpath_query = (
- './/compoundname[text()="%s"]/../'
- 'sectiondef[@kind="public-type"]/memberdef[@kind="enum"]/'
- 'name[text()="%s"]/..') % tuple(name.rsplit('::', 1))
- m = root.xpath(xpath_query)
- if len(m) > 0:
- obj = m[i]
- full_name = '.'.join(name.rsplit('::', 1))
- return full_name, obj, full_name, ''
-
- xpath_query = ('.//compoundname[text()="%s"]/..' % name)
- m = root.xpath(xpath_query)
- if len(m) > 0:
- obj = m[i]
- return (name, obj, name, '')
-
- raise ImportError()
-
-
-def get_documenter(obj, full_name):
- if obj.tag == 'memberdef' and obj.get('kind') == 'function':
- return DoxygenMethodDocumenter
- elif obj.tag == 'compounddef':
- return DoxygenClassDocumenter
-
- raise NotImplementedError(obj.tag)
-
-
-class DoxygenAutosummary(Autosummary):
- def get_items(self, names):
- """Try to import the given names, and return a list of
- ``[(name, signature, summary_string, real_name), ...]``.
- """
- env = self.state.document.settings.env
- items = []
-
- names_and_counts = reduce(operator.add,
- [tuple(zip(g, count())) for _, g in groupby(names)]) # type: List[(Str, Int)]
-
- for name, i in names_and_counts:
- display_name = name
- if name.startswith('~'):
- name = name[1:]
- display_name = name.split('::')[-1]
-
- try:
- real_name, obj, parent, modname = import_by_name(name, env=env, i=i)
- except ImportError:
- self.warn('failed to import %s' % name)
- items.append((name, '', '', name))
- continue
-
- self.result = ViewList() # initialize for each documenter
- documenter = get_documenter(obj, parent)(self, real_name, id=obj.get('id'))
- if not documenter.parse_name():
- self.warn('failed to parse name %s' % real_name)
- items.append((display_name, '', '', real_name))
- continue
- if not documenter.import_object():
- self.warn('failed to import object %s' % real_name)
- items.append((display_name, '', '', real_name))
- continue
- if documenter.options.members and not documenter.check_module():
- continue
- # -- Grab the signature
- sig = documenter.format_signature()
-
- # -- Grab the summary
- documenter.add_content(None)
- doc = list(documenter.process_doc([self.result.data]))
-
- while doc and not doc[0].strip():
- doc.pop(0)
-
- # If there's a blank line, then we can assume the first sentence /
- # paragraph has ended, so anything after shouldn't be part of the
- # summary
- for i, piece in enumerate(doc):
- if not piece.strip():
- doc = doc[:i]
- break
-
- # Try to find the "first sentence", which may span multiple lines
- m = re.search(r"^([A-Z].*?\.)(?:\s|$)", " ".join(doc).strip())
- if m:
- summary = m.group(1).strip()
- elif doc:
- summary = doc[0].strip()
- else:
- summary = ''
-
- items.append((display_name, sig, summary, real_name))
-
- return items
-
- def get_tablespec(self):
- table_spec = addnodes.tabular_col_spec()
- table_spec['spec'] = 'll'
-
- table = autosummary_table('')
- real_table = nodes.table('', classes=['longtable'])
- table.append(real_table)
- group = nodes.tgroup('', cols=2)
- real_table.append(group)
- group.append(nodes.colspec('', colwidth=10))
- group.append(nodes.colspec('', colwidth=90))
- body = nodes.tbody('')
- group.append(body)
-
- def append_row(*column_texts):
- row = nodes.row('')
- for text in column_texts:
- node = nodes.paragraph('')
- vl = ViewList()
- vl.append(text, '<autosummary>')
- self.state.nested_parse(vl, 0, node)
- try:
- if isinstance(node[0], nodes.paragraph):
- node = node[0]
- except IndexError:
- pass
- row.append(nodes.entry('', node))
- body.append(row)
- return table, table_spec, append_row
-
- def get_table(self, items):
- """Generate a proper list of table nodes for autosummary:: directive.
-
- *items* is a list produced by :meth:`get_items`.
- """
- table, table_spec, append_row = self.get_tablespec()
- for name, sig, summary, real_name in items:
- qualifier = 'cpp:any'
- # required for cpp autolink
- full_name = real_name.replace('.', '::')
- col1 = ':%s:`%s <%s>`' % (qualifier, name, full_name)
- col2 = summary
- append_row(col1, col2)
-
- self.result.append(' .. rubric: sdsf', 0)
- return [table_spec, table]
-
-
-class DoxygenAutoEnum(DoxygenAutosummary):
-
- def get_items(self, names):
- env = self.state.document.settings.env
- self.name = names[0]
-
- real_name, obj, parent, modname = import_by_name(self.name, env=env)
- names = [n.text for n in obj.findall('./enumvalue/name')]
- descriptions = [format_xml_paragraph(d) for d in obj.findall('./enumvalue/detaileddescription')]
- return zip(names, descriptions)
-
- def get_table(self, items):
- table, table_spec, append_row = self.get_tablespec()
- for name, description in items:
- col1 = ':strong:`' + name + '`'
- while description and not description[0].strip():
- description.pop(0)
- col2 = ' '.join(description)
- append_row(col1, col2)
- return [nodes.rubric('', 'Enum: %s' % self.name), table]
+++ /dev/null
-from __future__ import print_function, absolute_import, division
-
-import codecs
-import os
-import re
-import sys
-
-from jinja2 import FileSystemLoader
-from jinja2.sandbox import SandboxedEnvironment
-from sphinx.jinja2glue import BuiltinTemplateLoader
-from sphinx.util.osutil import ensuredir
-
-from . import import_by_name
-
-
-def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
- base_path=None, builder=None, template_dir=None):
-
- showed_sources = list(sorted(sources))
- if len(showed_sources) > 20:
- showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
- print('[autosummary] generating autosummary for: %s' %
- ', '.join(showed_sources))
-
- if output_dir:
- print('[autosummary] writing to %s' % output_dir)
-
- if base_path is not None:
- sources = [os.path.join(base_path, filename) for filename in sources]
-
- # create our own templating environment
- template_dirs = [os.path.join(os.path.dirname(__file__), 'templates')]
-
- if builder is not None:
- # allow the user to override the templates
- template_loader = BuiltinTemplateLoader()
- template_loader.init(builder, dirs=template_dirs)
- else:
- if template_dir:
- template_dirs.insert(0, template_dir)
- template_loader = FileSystemLoader(template_dirs)
- template_env = SandboxedEnvironment(loader=template_loader)
-
- # read
- items = find_autosummary_in_files(sources)
-
- # keep track of new files
- new_files = []
-
- for name, path, template_name in sorted(set(items), key=str):
- if path is None:
- # The corresponding autosummary:: directive did not have
- # a :toctree: option
- continue
-
- path = output_dir or os.path.abspath(path)
- ensuredir(path)
-
- try:
- name, obj, parent, mod_name = import_by_name(name)
- except ImportError as e:
- print('WARNING [autosummary] failed to import %r: %s' % (name, e), file=sys.stderr)
- continue
-
- fn = os.path.join(path, name + suffix).replace('::', '.')
-
- # skip it if it exists
- if os.path.isfile(fn):
- continue
-
- new_files.append(fn)
-
- if template_name is None:
- if obj.tag == 'compounddef' and obj.get('kind') == 'class':
- template_name = 'doxyclass.rst.in'
- else:
- raise NotImplementedError('No template for %s' % obj)
-
- with open(fn, 'w') as f:
- template = template_env.get_template(template_name)
- ns = {}
- if obj.tag == 'compounddef' and obj.get('kind') == 'class':
- ns['methods'] = [e.text for e in obj.findall('.//sectiondef[@kind="public-func"]/memberdef[@kind="function"]/name')]
- ns['enums'] = [e.text for e in obj.findall('.//sectiondef[@kind="public-type"]/memberdef[@kind="enum"]/name')]
- ns['objtype'] = 'class'
- else:
- raise NotImplementedError(obj)
-
- parts = name.split('::')
- mod_name, obj_name = '::'.join(parts[:-1]), parts[-1]
-
- ns['fullname'] = name
- ns['module'] = mod_name
- ns['objname'] = obj_name
- ns['name'] = parts[-1]
- ns['underline'] = len(name) * '='
-
- rendered = template.render(**ns)
- f.write(rendered)
-
- # descend recursively to new files
- if new_files:
- generate_autosummary_docs(new_files, output_dir=output_dir,
- suffix=suffix, base_path=base_path, builder=builder,
- template_dir=template_dir)
-
-
-def find_autosummary_in_files(filenames):
- """Find out what items are documented in source/*.rst.
-
- See `find_autosummary_in_lines`.
- """
- documented = []
- for filename in filenames:
- with codecs.open(filename, 'r', encoding='utf-8',
- errors='ignore') as f:
- lines = f.read().splitlines()
- documented.extend(find_autosummary_in_lines(lines,
- filename=filename))
- return documented
-
-
-def find_autosummary_in_lines(lines, module=None, filename=None):
- """Find out what items appear in autosummary:: directives in the
- given lines.
-
- Returns a list of (name, toctree, template) where *name* is a name
- of an object and *toctree* the :toctree: path of the corresponding
- autosummary directive (relative to the root of the file name), and
- *template* the value of the :template: option. *toctree* and
- *template* ``None`` if the directive does not have the
- corresponding options set.
- """
- autosummary_re = re.compile(r'^(\s*)\.\.\s+autodoxysummary::\s*')
- autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.:]*)\s*.*?')
- toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$')
- template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$')
-
- documented = []
-
- toctree = None
- template = None
- in_autosummary = False
- base_indent = ""
-
- for line in lines:
- if in_autosummary:
- m = toctree_arg_re.match(line)
- if m:
- toctree = m.group(1)
- if filename:
- toctree = os.path.join(os.path.dirname(filename),
- toctree)
- continue
-
- m = template_arg_re.match(line)
- if m:
- template = m.group(1).strip()
- continue
-
- if line.strip().startswith(':'):
- continue # skip options
-
- m = autosummary_item_re.match(line)
- if m:
- name = m.group(1).strip()
- if name.startswith('~'):
- name = name[1:]
- documented.append((name, toctree, template))
- continue
-
- if not line.strip() or line.startswith(base_indent + " "):
- continue
-
- in_autosummary = False
-
- m = autosummary_re.match(line)
- if m:
- in_autosummary = True
- base_indent = m.group(1)
- toctree = None
- template = None
- continue
-
- return documented
-
-
-def process_generate_options(app):
- genfiles = app.config.autosummary_generate
-
- if genfiles and not hasattr(genfiles, '__len__'):
- env = app.builder.env
- genfiles = [env.doc2path(x, base=None) for x in env.found_docs
- if os.path.isfile(env.doc2path(x))]
-
- if not genfiles:
- return
-
- ext = app.config.source_suffix[0]
- genfiles = [genfile + (not genfile.endswith(ext) and ext or '')
- for genfile in genfiles]
-
- generate_autosummary_docs(genfiles, builder=app.builder,
- suffix=ext, base_path=app.srcdir)
+++ /dev/null
-{{ name }}
-{{ underline }}
-
-.. autodoxyclass:: {{ fullname }}
- :members:
-
- {% if methods %}
- .. rubric:: Methods
-
- .. autodoxysummary::
- {% for item in methods %}
- ~{{ fullname }}::{{ item }}
- {%- endfor %}
- {% endif %}
-
- {% if enums %}
- {% for enum in enums %}
- .. autodoxyenum:: {{ enum }}
- {% endfor %}
- {% endif %}
\ No newline at end of file
+++ /dev/null
-from __future__ import print_function, absolute_import, division
-from . import get_doxygen_root
-import re
-
-def format_xml_paragraph(xmlnode):
- """Format an Doxygen XML segment (principally a detaileddescription)
- as a paragraph for inclusion in the rst document
-
- Parameters
- ----------
- xmlnode
-
- Returns
- -------
- lines
- A list of lines.
- """
- return [l.rstrip() for l in _DoxygenXmlParagraphFormatter().generic_visit(xmlnode).lines]
-
-
-class _DoxygenXmlParagraphFormatter(object):
- # This class follows the model of the stdlib's ast.NodeVisitor for tree traversal
- # where you dispatch on the element type to a different method for each node
- # during the traverse.
-
- # It's supposed to handle paragraphs, references, preformatted text (code blocks), and lists.
-
- def __init__(self):
- self.lines = ['']
- self.continue_line = False
-
- def visit(self, node):
- method = 'visit_' + node.tag
- visitor = getattr(self, method, self.generic_visit)
- return visitor(node)
-
- def generic_visit(self, node):
- for child in node.getchildren():
- self.visit(child)
- return self
-
- def visit_ref(self, node):
- ref = get_doxygen_root().findall('.//*[@id="%s"]' % node.get('refid'))
- if ref:
- ref = ref[0]
- if ref.tag == 'memberdef':
- parent = ref.xpath('./ancestor::compounddef/compoundname')[0].text
- name = ref.find('./name').text
- real_name = parent + '::' + name
- elif ref.tag in ('compounddef', 'enumvalue'):
- name_node = ref.find('./name')
- real_name = name_node.text if name_node is not None else ''
- else:
- raise NotImplementedError(ref.tag)
- else:
- real_name = None
-
- val = [':cpp:any:`', node.text]
- if real_name:
- val.extend((' <', real_name, '>`'))
- else:
- val.append('`')
- if node.tail is not None:
- val.append(node.tail)
-
- self.lines[-1] += ''.join(val)
-
- def visit_para(self, node):
- if node.text is not None:
- if self.continue_line:
- self.lines[-1] += node.text
- else:
- self.lines.append(node.text)
- self.generic_visit(node)
- self.lines.append('')
- self.continue_line = False
-
- def visit_verbatim(self, node):
- if node.text is not None:
- # remove the leading ' *' of any lines
- lines = [re.sub('^\s*\*','', l) for l in node.text.split('\n')]
- # Merge each paragraph together
- text = re.sub("\n\n", "PaRaGrraphSplit", '\n'.join(lines))
- text = re.sub('\n', '', text)
- lines = text.split('PaRaGrraphSplit')
-
- # merge content to the built doc
- if self.continue_line:
- self.lines[-1] += lines[0]
- lines = lines[1:]
- for l in lines:
- self.lines.append('')
- self.lines.append(l)
- self.generic_visit(node)
- self.lines.append('')
- self.continue_line = False
-
- def visit_parametername(self, node):
- if 'direction' in node.attrib:
- direction = '[%s] ' % node.get('direction')
- else:
- direction = ''
-
- self.lines.append('**%s** -- %s' % (
- node.text, direction))
- self.continue_line = True
-
- def visit_parameterlist(self, node):
- lines = [l for l in type(self)().generic_visit(node).lines if l is not '']
- self.lines.extend([':parameters:', ''] + ['* %s' % l for l in lines] + [''])
-
- def visit_simplesect(self, node):
- if node.get('kind') == 'return':
- self.lines.append(':returns: ')
- self.continue_line = True
- self.generic_visit(node)
-
- def visit_listitem(self, node):
- self.lines.append(' - ')
- self.continue_line = True
- self.generic_visit(node)
-
- def visit_preformatted(self, node):
- segment = [node.text if node.text is not None else '']
- for n in node.getchildren():
- segment.append(n.text)
- if n.tail is not None:
- segment.append(n.tail)
-
- lines = ''.join(segment).split('\n')
- self.lines.extend(('.. code-block:: C++', ''))
- self.lines.extend([' ' + l for l in lines])
-
- def visit_computeroutput(self, node):
- c = node.find('preformatted')
- if c is not None:
- return self.visit_preformatted(c)
- return self.visit_preformatted(node)
-
- def visit_xrefsect(self, node):
- if node.find('xreftitle').text == 'Deprecated':
- sublines = type(self)().generic_visit(node).lines
- self.lines.extend(['.. admonition:: Deprecated'] + [' ' + s for s in sublines])
- else:
- raise ValueError(node)
-
- def visit_subscript(self, node):
- self.lines[-1] += '\ :sub:`%s` %s' % (node.text, node.tail)
-
+++ /dev/null
-from setuptools import setup, Extension
-
-with open("README", "r") as fh:
- long_description = fh.read()
-
-setup(
- name="autodoxy",
- version="0.0.1",
- author="Martin Quinson",
-# author_email="author@example.com",
- description="A bridge between the autodoc of Python and Doxygen of C/C++",
- long_description=long_description,
- long_description_content_type="text/plain",
- url="https://framagit.org/simgrid/simgrid/docs/source/_ext/autodoxy",
- packages=setuptools.find_packages(),
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
- python_requires='>=3.6',
-)