summaryrefslogtreecommitdiff
path: root/tools/docdump/makedocs.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/docdump/makedocs.py')
-rw-r--r--tools/docdump/makedocs.py382
1 files changed, 0 insertions, 382 deletions
diff --git a/tools/docdump/makedocs.py b/tools/docdump/makedocs.py
deleted file mode 100644
index be57891abc..0000000000
--- a/tools/docdump/makedocs.py
+++ /dev/null
@@ -1,382 +0,0 @@
-#!/usr/bin/python3
-# -*- coding: utf-8 -*-
-
-#
-# makedocs.py: Generate documentation for Open Project Wiki
-# Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur.
-# Contributor: Jorge Araya Navarro <elcorreo@deshackra.com>
-#
-
-# IMPORTANT NOTICE:
-# If you are going to modify anything from this file, please be sure to follow
-# the Style Guide for Python Code or often called "PEP8". To do this
-# automagically just install autopep8:
-#
-# $ sudo pip3 install autopep8
-#
-# and run:
-#
-# $ autopep8 makedocs.py
-#
-# Before committing your changes. Also be sure to delete any trailing
-# whitespace you may left.
-#
-# TODO:
-# * Refactor code.
-# * Adapt this script for generating content in other markup formats like
-# DokuWiki, Markdown, etc.
-#
-# Also check other TODO entries in this script for more information on what is
-# left to do.
-import argparse
-import gettext
-import logging
-import re
-from itertools import zip_longest
-from os import path, listdir
-from xml.etree import ElementTree
-
-
-# add an option to change the verbosity
-logging.basicConfig(level=logging.INFO)
-
-
-def getxmlfloc():
- """ Returns the supposed location of the XML file
- """
- filepath = path.dirname(path.abspath(__file__))
- return path.join(filepath, "class_list.xml")
-
-
-def langavailable():
- """ Return a list of languages available for translation
- """
- filepath = path.join(
- path.dirname(path.abspath(__file__)), "locales")
- files = listdir(filepath)
- choices = [x for x in files]
- choices.insert(0, "none")
- return choices
-
-
-desc = "Generates documentation from a XML file to different markup languages"
-
-parser = argparse.ArgumentParser(description=desc)
-parser.add_argument("--input", dest="xmlfp", default=getxmlfloc(),
- help="Input XML file, default: {}".format(getxmlfloc()))
-parser.add_argument("--output-dir", dest="outputdir", required=True,
- help="Output directory for generated files")
-parser.add_argument("--language", choices=langavailable(), default="none",
- help=("Choose the language of translation"
- " for the output files. Default is English (none). "
- "Note: This is NOT for the documentation itself!"))
-# TODO: add an option for outputting different markup formats
-
-args = parser.parse_args()
-# Let's check if the file and output directory exists
-if not path.isfile(args.xmlfp):
- logging.critical("File not found: {}".format(args.xmlfp))
- exit(1)
-elif not path.isdir(args.outputdir):
- logging.critical("Path does not exist: {}".format(args.outputdir))
- exit(1)
-
-_ = gettext.gettext
-if args.language != "none":
- lang = gettext.translation(domain="makedocs",
- localedir="locales",
- languages=[args.language])
- lang.install()
-
- _ = lang.gettext
-
-# Strings
-C_LINK = _("\"<code>{gclass}</code>(Go to page of class"
- " {gclass})\":/class_{lkclass}")
-MC_LINK = _("\"<code>{gclass}.{method}</code>(Go "
- "to page {gclass}, section {method})\""
- ":/class_{lkclass}#{lkmethod}")
-TM_JUMP = _("\"<code>{method}</code>(Jump to method"
- " {method})\":#{lkmethod}")
-GTC_LINK = _(" \"{rtype}(Go to page of class {rtype})\":/class_{link} ")
-DFN_JUMP = _("\"*{funcname}*(Jump to description for"
- " node {funcname})\":#{link} <b>(</b> ")
-M_ARG_DEFAULT = C_LINK + " {name}={default}"
-M_ARG = C_LINK + " {name}"
-
-OPENPROJ_INH = _("h4. Inherits: ") + C_LINK + "\n\n"
-
-
-def tb(string):
- """ Return a byte representation of a string
- """
- return bytes(string, "UTF-8")
-
-
-def sortkey(c):
- """ Symbols are first, letters second
- """
- if "_" == c.attrib["name"][0]:
- return "A"
- else:
- return c.attrib["name"]
-
-
-def toOP(text):
- """ Convert commands in text to Open Project commands
- """
- # TODO: Make this capture content between [command] ... [/command]
- groups = re.finditer((r'\[html (?P<command>/?\w+/?)(\]| |=)?(\]| |=)?(?P<a'
- 'rg>\w+)?(\]| |=)?(?P<value>"[^"]+")?/?\]'), text)
- alignstr = ""
- for group in groups:
- gd = group.groupdict()
- if gd["command"] == "br/":
- text = text.replace(group.group(0), "\n\n", 1)
- elif gd["command"] == "div":
- if gd["value"] == '"center"':
- alignstr = ("{display:block; margin-left:auto;"
- " margin-right:auto;}")
- elif gd["value"] == '"left"':
- alignstr = "<"
- elif gd["value"] == '"right"':
- alignstr = ">"
- text = text.replace(group.group(0), "\n\n", 1)
- elif gd["command"] == "/div":
- alignstr = ""
- text = text.replace(group.group(0), "\n\n", 1)
- elif gd["command"] == "img":
- text = text.replace(group.group(0), "!{align}{src}!".format(
- align=alignstr, src=gd["value"].strip('"')), 1)
- elif gd["command"] == "b" or gd["command"] == "/b":
- text = text.replace(group.group(0), "*", 1)
- elif gd["command"] == "i" or gd["command"] == "/i":
- text = text.replace(group.group(0), "_", 1)
- elif gd["command"] == "u" or gd["command"] == "/u":
- text = text.replace(group.group(0), "+", 1)
- # Process other non-html commands
- groups = re.finditer((r'\[method ((?P<class>[aA0-zZ9_]+)(?:\.))'
- r'?(?P<method>[aA0-zZ9_]+)\]'), text)
- for group in groups:
- gd = group.groupdict()
- if gd["class"]:
- replacewith = (MC_LINK.format(gclass=gd["class"],
- method=gd["method"],
- lkclass=gd["class"].lower(),
- lkmethod=gd["method"].lower()))
- else:
- # The method is located in the same wiki page
- replacewith = (TM_JUMP.format(method=gd["method"],
- lkmethod=gd["method"].lower()))
-
- text = text.replace(group.group(0), replacewith, 1)
- # Finally, [Classes] are around brackets, make them direct links
- groups = re.finditer(r'\[(?P<class>[az0-AZ0_]+)\]', text)
- for group in groups:
- gd = group.groupdict()
- replacewith = (C_LINK.
- format(gclass=gd["class"],
- lkclass=gd["class"].lower()))
- text = text.replace(group.group(0), replacewith, 1)
-
- return text + "\n\n"
-
-
-def mkfn(node, is_signal=False):
- """ Return a string containing a unsorted item for a function
- """
- finalstr = ""
- name = node.attrib["name"]
- rtype = node.find("return")
- if rtype:
- rtype = rtype.attrib["type"]
- else:
- rtype = "void"
- # write the return type and the function name first
- finalstr += "* "
- # return type
- if not is_signal:
- if rtype != "void":
- finalstr += GTC_LINK.format(
- rtype=rtype,
- link=rtype.lower())
- else:
- finalstr += " void "
-
- # function name
- if not is_signal:
- finalstr += DFN_JUMP.format(
- funcname=name,
- link=name.lower())
- else:
- # Signals have no description
- finalstr += "*{funcname}* <b>(</b>".format(funcname=name)
- # loop for the arguments of the function, if any
- args = []
- for arg in sorted(
- node.iter(tag="argument"),
- key=lambda a: int(a.attrib["index"])):
-
- ntype = arg.attrib["type"]
- nname = arg.attrib["name"]
-
- if "default" in arg.attrib:
- args.insert(-1, M_ARG_DEFAULT.format(
- gclass=ntype,
- lkclass=ntype.lower(),
- name=nname,
- default=arg.attrib["default"]))
- else:
- # No default value present
- args.insert(-1, M_ARG.format(gclass=ntype,
- lkclass=ntype.lower(), name=nname))
- # join the arguments together
- finalstr += ", ".join(args)
- # and, close the function with a )
- finalstr += " <b>)</b>"
- # write the qualifier, if any
- if "qualifiers" in node.attrib:
- qualifier = node.attrib["qualifiers"]
- finalstr += " " + qualifier
-
- finalstr += "\n"
-
- return finalstr
-
-# Let's begin
-tree = ElementTree.parse(args.xmlfp)
-root = tree.getroot()
-
-# Check version attribute exists in <doc>
-if "version" not in root.attrib:
- logging.critical(_("<doc>'s version attribute missing"))
- exit(1)
-
-version = root.attrib["version"]
-classes = sorted(root, key=sortkey)
-# first column is always longer, second column of classes should be shorter
-zclasses = zip_longest(classes[:int(len(classes) / 2 + 1)],
- classes[int(len(classes) / 2 + 1):],
- fillvalue="")
-
-# We write the class_list file and also each class file at once
-with open(path.join(args.outputdir, "class_list.txt"), "wb") as fcl:
- # Write header of table
- fcl.write(tb("|^.\n"))
- fcl.write(tb(_("|_. Index symbol |_. Class name "
- "|_. Index symbol |_. Class name |\n")))
- fcl.write(tb("|-.\n"))
-
- indexletterl = ""
- indexletterr = ""
- for gdclassl, gdclassr in zclasses:
- # write a row #
- # write the index symbol column, left
- if indexletterl != gdclassl.attrib["name"][0]:
- indexletterl = gdclassl.attrib["name"][0]
- fcl.write(tb("| *{}* |".format(indexletterl.upper())))
- else:
- # empty cell
- fcl.write(tb("| |"))
- # write the class name column, left
- fcl.write(tb(C_LINK.format(
- gclass=gdclassl.attrib["name"],
- lkclass=gdclassl.attrib["name"].lower())))
-
- # write the index symbol column, right
- if isinstance(gdclassr, ElementTree.Element):
- if indexletterr != gdclassr.attrib["name"][0]:
- indexletterr = gdclassr.attrib["name"][0]
- fcl.write(tb("| *{}* |".format(indexletterr.upper())))
- else:
- # empty cell
- fcl.write(tb("| |"))
- # We are dealing with an empty string
- else:
- # two empty cell
- fcl.write(tb("| | |\n"))
- # We won't get the name of the class since there is no ElementTree
- # object for the right side of the tuple, so we iterate the next
- # tuple instead
- continue
-
- # write the class name column (if any), right
- fcl.write(tb(C_LINK.format(
- gclass=gdclassl.attrib["name"],
- lkclass=gdclassl.attrib["name"].lower()) + "|\n"))
-
- # row written #
- # now, let's write each class page for each class
- for gdclass in [gdclassl, gdclassr]:
- if not isinstance(gdclass, ElementTree.Element):
- continue
-
- classname = gdclass.attrib["name"]
- with open(path.join(args.outputdir, "{}.txt".format(
- classname.lower())), "wb") as clsf:
- # First level header with the name of the class
- clsf.write(tb("h1. {}\n\n".format(classname)))
- # lay the attributes
- if "inherits" in gdclass.attrib:
- inh = gdclass.attrib["inherits"].strip()
- clsf.write(tb(OPENPROJ_INH.format(gclass=inh,
- lkclass=inh.lower())))
- if "category" in gdclass.attrib:
- clsf.write(tb(_("h4. Category: {}\n\n").
- format(gdclass.attrib["category"].strip())))
- # lay child nodes
- briefd = gdclass.find("brief_description")
- if briefd.text.strip():
- clsf.write(tb(_("h2. Brief Description\n\n")))
- clsf.write(tb(toOP(briefd.text.strip()) +
- _("\"read more\":#more\n\n")))
-
- # Write the list of member functions of this class
- methods = gdclass.find("methods")
- if methods and len(methods) > 0:
- clsf.write(tb(_("\nh3. Member Functions\n\n")))
- for method in methods.iter(tag='method'):
- clsf.write(tb(mkfn(method)))
-
- signals = gdclass.find("signals")
- if signals and len(signals) > 0:
- clsf.write(tb(_("\nh3. Signals\n\n")))
- for signal in signals.iter(tag='signal'):
- clsf.write(tb(mkfn(signal, True)))
- # TODO: <members> tag is necessary to process? it does not
- # exists in class_list.xml file.
-
- consts = gdclass.find("constants")
- if consts and len(consts) > 0:
- clsf.write(tb(_("\nh3. Numeric Constants\n\n")))
- for const in sorted(consts, key=lambda k:
- k.attrib["name"]):
- if const.text.strip():
- clsf.write(tb("* *{name}* = *{value}* - {desc}\n".
- format(
- name=const.attrib["name"],
- value=const.attrib["value"],
- desc=const.text.strip())))
- else:
- # Constant have no description
- clsf.write(tb("* *{name}* = *{value}*\n".
- format(
- name=const.attrib["name"],
- value=const.attrib["value"])))
- descrip = gdclass.find("description")
- clsf.write(tb(_("\nh3(#more). Description\n\n")))
- if descrip.text:
- clsf.write(tb(descrip.text.strip() + "\n"))
- else:
- clsf.write(tb(_("_Nothing here, yet..._\n")))
-
- # and finally, the description for each method
- if methods and len(methods) > 0:
- clsf.write(tb(_("\nh3. Member Function Description\n\n")))
- for method in methods.iter(tag='method'):
- clsf.write(tb("h4(#{n}). {name}\n\n".format(
- n=method.attrib["name"].lower(),
- name=method.attrib["name"])))
- clsf.write(tb(mkfn(method) + "\n"))
- clsf.write(tb(toOP(method.find(
- "description").text.strip())))