Ejemplo n.º 1
0
def index_items(item_type, items):
    return """
%s:

.. toctree::
    :maxdepth: 1

%s
""" % (item_type, indent("\n".join(sorted(items)), 4))
Ejemplo n.º 2
0
def index_items(item_type, items):
    return """
%s:

.. toctree::
    :maxdepth: 1

%s
""" % (item_type, indent("\n".join(sorted(items)), 4))
Ejemplo n.º 3
0
def generate_cpp_module(module, documentation, classnames, output_dir):

    print indent("Generating documentation for %s ... " % module, 0)

    # Generate index file for this module
    module_index = templates.generate_module_index(module)
    index_filename = os.path.join(output_dir, "index.rst")
    open_write_close(index_filename, module_index)

    # Generate .rst for each header file in this module
    for (header, doc) in documentation:

        #print indent("Generating documentation for %s" % header, 2)
        rst_filename = os.path.join(output_dir, header.split(".")[0] + ".rst")
        header_rst = generate_header_rst_file(module, header, doc, classnames)
        open_write_close(rst_filename, header_rst)

    return
Ejemplo n.º 4
0
def generate_cpp_module(module, documentation, classnames, output_dir):

    print indent("Generating documentation for %s ... " % module, 0)

    # Generate index file for this module
    module_index = templates.generate_module_index(module)
    index_filename = os.path.join(output_dir, "index.rst")
    open_write_close(index_filename, module_index)

    # Generate .rst for each header file in this module
    for (header, doc) in documentation:

        #print indent("Generating documentation for %s" % header, 2)
        rst_filename = os.path.join(output_dir, header.split(".")[0] + ".rst")
        header_rst = generate_header_rst_file(module, header, doc,
                                              classnames)
        open_write_close(rst_filename, header_rst)

    return
Ejemplo n.º 5
0
def write_class_doc(classname, parents, comment, function_documentation,
                    classnames):

    output = []
    base_indent = 0
    if classname is not None:
        base_indent = 4
        output += [".. cpp:class:: %s\n" % classname]

        if parents is not None:
            output += [indent("*Parent class(es)*\n", 4)]
            for parent in parents:
                output += [indent("* :cpp:class:`%s`\n" % parent, 8)]

        if comment is not None:
            comment = add_links(comment, classnames, ":cpp:class:") #NB
            output += [indent(comment, 4)] + ["\n"]

    else:
        output += ["\n"]

    for (signature, comment) in function_documentation:

        # Handle indentation of signature # Hm?
        if "\n" in signature:
            lines = signature.split("\n")
            signature = ("\n".join([lines[0]]
                                   + [(len(".. cpp.function::") + 1)*" " + l
                                      for l in lines[1:]]))
        # Add crosslinks in comment
        comment = add_links(comment, classnames, ":cpp:class:")

        output += [indent(".. cpp:function:: %s\n" % signature, base_indent)]
        output += [indent(comment, base_indent + 4), "\n"]

    text = "\n".join(output)
    return text
Ejemplo n.º 6
0
def write_class_doc(classname, parents, comment, function_documentation,
                    classnames):

    output = []
    base_indent = 0
    if classname is not None:
        base_indent = 4
        output += [".. cpp:class:: %s\n" % classname]

        if parents is not None:
            output += [indent("*Parent class(es)*\n", 4)]
            for parent in parents:
                output += [indent("* :cpp:class:`%s`\n" % parent, 8)]

        if comment is not None:
            comment = add_links(comment, classnames, ":cpp:class:")  #NB
            output += [indent(comment, 4)] + ["\n"]

    else:
        output += ["\n"]

    for (signature, comment) in function_documentation:

        # Handle indentation of signature # Hm?
        if "\n" in signature:
            lines = signature.split("\n")
            signature = ("\n".join([lines[0]] +
                                   [(len(".. cpp.function::") + 1) * " " + l
                                    for l in lines[1:]]))
        # Add crosslinks in comment
        comment = add_links(comment, classnames, ":cpp:class:")

        output += [indent(".. cpp:function:: %s\n" % signature, base_indent)]
        output += [indent(comment, base_indent + 4), "\n"]

    text = "\n".join(output)
    return text
def replace_example(text, classname, signature):
    """Replace the C++ example code with the Python equivalent.
    Currently we can only handle one block/section of example code per function.
    """
    # Check if we need to manipulate comment.
    if not "*Example*" in text:
        return text
    # Check if we have example code in the dictionary
    examplecode = ".. note::\n\n    No example code available for this function."
    if not classname in codesnippets:
        output(" " * 6 + "No example code for class: '%s'" % classname)
    elif not signature in codesnippets[classname]:
        output(" " * 6 +
               "No example code for (class, function): ('%s', '%s')" %
               (classname, signature))
    else:
        examplecode = codesnippets[classname][signature]

    # Remove leading and trailing new lines in example code.
    lines = examplecode.split("\n")
    while lines and not lines[0].strip():
        del lines[0]
    while lines and not lines[-1].strip():
        del lines[-1]
    examplecode = "\n".join(lines)

    # NOTE: KBO: We currently only handle 1 example block
    new_text = []
    example = False
    indentation = 0
    # Loop comment lines
    for l in text.split("\n"):
        # When we get to the lines containing the example, add the header and
        # codeblock.
        if not example and "*Example*" in l:
            example = True
            indentation = len(l) - len(l.lstrip())
            new_text.append(l)
            new_text += indent(examplecode, indentation + 4).split("\n")
        elif example and l.strip() and len(l) - len(l.lstrip()) <= indentation:
            example = False
            new_text.append(l)
        # Skip lines as long as we're inside the example block.
        elif example:
            continue
        else:
            new_text.append(l)
    return "\n".join(new_text)
Ejemplo n.º 8
0
def generate_header_rst_file(module, header, documentation, classnames):

    output = []
    for (classname, parents, comment, function_documentation) in documentation:
        output += [write_class_doc(classname, parents, comment,
                                   function_documentation, classnames)]

    text = "\n".join(output)
    note = indent(templates.note_template, 4)

    dictionary = {"module": module, "header": header,
                  "prefix": header.split(".")[0].lower(),
                  "title": header, "formatting": len(header)*"=",
                  "note": note, "text": text}
    template = templates.header_cpp_template % dictionary

    return template
def write_docstrings(output_file, module, header, docs, classnames):
    """Write docstrings from a header file."""

    output_file.write(
        "// Documentation extracted from: (module=%s, header=%s)\n" %
        (module, header))

    documentation = group_overloaded_functions(docs)
    for (classname, parent, comment, func_docs, order) in documentation:
        # Create class documentation (if any) and write.
        if classname is not None and comment is not None:
            cls_doc = modify_doc(comment, classnames, classname, classname)
            output_file.write(docstring % ("dolfin::%s" % classname, cls_doc))
        # Handle functions in the correct order (according to definition in the
        # header file).
        for name in order:
            func_name = "dolfin::%s::%s" % (classname, name)
            if classname is None:
                func_name = "dolfin::%s" % name

            functions = func_docs[name]
            if not functions:
                continue
            # We've got overloaded functions.
            if len(functions) > 1:
                func_doc = "**Overloaded versions**"
                for signature, doc in functions:
                    args = get_args(signature)
                    doc = "\n\n* %s\ (%s)\n\n" % (name, ", ".join(args)) +\
                          indent(doc, 2)
                    func_doc += modify_doc(doc, classnames, classname,
                                           signature)
                output_file.write(docstring % (func_name, func_doc))
            # Single function
            else:
                # Get function (only one)
                signature, func_doc = functions[0]
                func_doc = modify_doc(func_doc, classnames, classname,
                                      signature)
                output_file.write(docstring % (func_name, func_doc))
Ejemplo n.º 10
0
def generate_header_rst_file(module, header, documentation, classnames):

    output = []
    for (classname, parents, comment, function_documentation) in documentation:
        output += [
            write_class_doc(classname, parents, comment,
                            function_documentation, classnames)
        ]

    text = "\n".join(output)
    note = indent(templates.note_template, 4)

    dictionary = {
        "module": module,
        "header": header,
        "prefix": header.split(".")[0].lower(),
        "title": header,
        "formatting": len(header) * "=",
        "note": note,
        "text": text
    }
    template = templates.header_cpp_template % dictionary

    return template
Ejemplo n.º 11
0
def map_argument_and_return_types(text, classnames):
    """Map C++ types in the *Arguments* and *Returns* sections to corresponding
    Python types using a simple dictionary.

    Current implementation assumes the following format:

    *Returns*
         type
             description

    *Arguments*
         name0 (type)
             description
         name1 (type)
             description

    possibly separated with blank lines.
    """

    new_text = text

    # Could perhaps be handled more elegantly if we rely on the formatting?
    if "*Returns*" in new_text:
        # Get lines and find line number with *Returns*
        lines = new_text.split("\n")
        r_index = ["*Returns*" in l for l in lines].index(True)
        arg = False
        for e, l in enumerate(lines):
            if e > r_index and not arg:
                # First none blank line contains our argument
                if l.strip():
                    arg = True
                    indentation = len(l) - len(l.lstrip())
                    lines[e] = indent(map_cpp_type(l.strip(), classnames),
                                      indentation)
        new_text = "\n".join(lines)

    if "*Arguments*" in new_text:
        # Get lines and find line number with *Arguments*
        lines = new_text.split("\n")
        a_index = ["*Arguments*" in l for l in lines].index(True)
        a_indent = len(lines[a_index]) - len(lines[a_index].lstrip())
        n_indent = 0
        for e, l in enumerate(lines):
            if e > a_index and l.strip():
                indentation = len(l) - len(l.lstrip())
                # End of argument block
                if indentation <= a_indent:
                    break
                # Determine indentation of lines with argument names
                # first non blank line determines this
                if n_indent == 0:
                    n_indent = indentation
                # Get type of arguments defined in lines with name and type
                if indentation == n_indent:
                    n, t = l.split("(")
                    n = n.strip()
                    t = t.split(")")[0]
                    lines[e] = indent(
                        "%s (%s)" % (n, map_cpp_type(t.strip(), classnames)),
                        n_indent)

        new_text = "\n".join(lines)

    return new_text