-#!/usr/bin/python
-#---------------------------------------------------------------------------
-#
-# Like simplify.xsl but using Python so a few non-standard conversions can
-# also be done. (Currently it is still about the same as simplify.xsl...)
-#
-#---------------------------------------------------------------------------
-
-import sys
-import os
-import libxml2
-
-
-DEST="docs/xml/wxPython-metadata.xml"
-SRC="docs/xml-raw"
-
-
-classMap = {
- 'wxString' : 'String',
- 'void' : '',
- }
-
-
-def getModuleNames():
- """
- Get the list of extension modules from setup.py
- """
- import setup
- names = [e.name[1:] for e in setup.wxpExtensions]
- return names
-
-
-
-def getAttr(node, name):
- """
- Get a value by name from the <attribute> elements in the SWIG XML output
- """
- path = "./attributelist/attribute[@name='%s']/@value" % name
- n = node.xpathEval2(path)
- if len(n):
- return n[0].content
- else:
- return None
-
-
-def fixType(typeStr):
- """
- Fixup type string, dropping the swig pointer and other flags
- """
- pos = typeStr.rfind('.')
- if pos != -1:
- typeStr = typeStr[pos+1:]
- return classMap.get(typeStr, typeStr)
-
-
-def processModule(newDocNode, modulename):
- """
- Start processing a new XML file, create a module element and then
- find the include elements
- """
- filename = os.path.join(SRC, "%s_swig.xml" % modulename)
- print filename
-
- doc = libxml2.parseFile(filename)
- topNode = doc.getRootElement()
-
- # make a module element
- name = getAttr(topNode, "module")
- ##assert name == modulename # sanity check
-
- moduleNode = libxml2.newNode("module")
- moduleNode.setProp("name", name)
- newDocNode.addChild(moduleNode)
-
- node = topNode.children
- while node is not None:
- if node.name == "include":
- processInclude(moduleNode, node)
- node = node.next
-
- doc.freeDoc()
-
-
-
-def processInclude(moduleNode, includeNode):
- """
- Almost everything we are interested in is inside an <include>,
- which may also be nested.
- """
-
- # check first for imports
- for node in includeNode.xpathEval2("import"):
- try:
- modNode = node.xpathEval2("module")[0]
- name = getAttr(modNode, "name")
- impNode = libxml2.newNode("import")
- impNode.setProp("name", name)
- moduleNode.addChild(impNode)
- except IndexError:
- pass
-
- # then look through the child nodes for other things we need
- node = includeNode.children
- while node is not None:
- if node.name == "insert":
- processInsert(moduleNode, node)
-
- elif node.name == "class":
- processClass(moduleNode, node)
-
- elif node.name == "cdecl" and getAttr(node, "view") == "globalfunctionHandler":
- func = libxml2.newNode("method")
- func.setProp("name", getAttr(node, "sym_name"))
- func.setProp("oldname", getAttr(node, "name"))
- func.setProp("type", fixType(getAttr(node, "type")))
- doCheckOverloaded(func, node)
- doDocStrings(func, node)
- doParamList(func, node)
- moduleNode.addChild(func)
-
-
- elif node.name == "include":
- processInclude(moduleNode, node)
-
- node = node.next
-
-
-
-def processInsert(parentNode, insertNode):
- """
- Check for pythoncode
- """
- if getAttr(insertNode, "section") == "python":
- code = getAttr(insertNode, "code")
- node = libxml2.newNode("pythoncode")
- node.addChild(libxml2.newText(code))
- parentNode.addChild(node)
-
-
-
-def processClass(parentNode, classNode):
- """
- Handle classes, constructors, methods, etc.
- """
- # make class element
- klass = libxml2.newNode("class")
- name = getAttr(classNode, "sym_name")
- oldname = getAttr(classNode, "name")
- classMap[oldname] = name
- klass.setProp("name", name)
- klass.setProp("oldname", oldname)
- klass.setProp("module", getAttr(classNode, "module"))
- doDocStrings(klass, classNode)
- parentNode.addChild(klass)
-
- # check for baseclass(es)
- for node in classNode.xpathEval2("attributelist/baselist/base"):
- baseclass = libxml2.newNode("baseclass")
- basename = node.prop("name")
- baseclass.setProp("name", classMap.get(basename, basename))
- klass.addChild(baseclass)
-
- # check for constructors/destructors
- for type in ["constructor", "destructor"]:
- for node in classNode.xpathEval2("%s | extend/%s" % (type, type)):
- func = libxml2.newNode(type)
- func.setProp("name", getAttr(node, "sym_name"))
- if parentNode.name != "destructor":
- doCheckOverloaded(func, node)
- doDocStrings(func, node)
- doParamList(func, node)
- klass.addChild(func)
-
- # check for cdecl's. In class scope we are interested in methods,
- # static methods, or properties
- for node in classNode.xpathEval2("cdecl | extend/cdecl"):
- view = getAttr(node, "view")
- if view == "memberfunctionHandler":
- func = libxml2.newNode("method")
- func.setProp("name", getAttr(node, "sym_name"))
- func.setProp("type", fixType(getAttr(node, "type")))
- doCheckOverloaded(func, node)
- doDocStrings(func, node)
- doParamList(func, node)
- klass.addChild(func)
-
- elif view == "staticmemberfunctionHandler":
- func = libxml2.newNode("staticmethod")
- func.setProp("name", getAttr(node, "sym_name"))
- func.setProp("type", fixType(getAttr(node, "type")))
- doCheckOverloaded(func, node)
- doDocStrings(func, node)
- doParamList(func, node)
- klass.addChild(func)
-
- elif view == "variableHandler":
- prop = libxml2.newNode("property")
- prop.setProp("name", getAttr(node, "sym_name"))
- prop.setProp("type", fixType(getAttr(node, "type")))
- if getAttr(node, "feature_immutable"):
- prop.setProp("readonly", "yes")
- else:
- prop.setProp("readonly", "no")
- doDocStrings(prop, node)
- klass.addChild(prop)
-
-
-
-def doParamList(parentNode, srcNode):
- """
- Convert the parameter list
- """
- params = srcNode.xpathEval2("attributelist/parmlist/parm")
- if params:
- plist = libxml2.newNode("paramlist")
- for p in params:
- pnode = libxml2.newNode("param")
- pnode.setProp("name", getAttr(p, "name"))
- pnode.setProp("type", fixType(getAttr(p, "type")))
- pnode.setProp("default", getAttr(p, "value"))
- plist.addChild(pnode)
- parentNode.addChild(plist)
-
-
-
-def doCheckOverloaded(parentNode, srcNode):
- """
- Set an attribute indicating if the srcNode is tagged as being overloaded
- """
- if srcNode.xpathEval2("./attributelist/attribute[@name='sym_overloaded']"):
- parentNode.setProp("overloaded", "yes")
- else:
- parentNode.setProp("overloaded", "no")
-
-
-
-def doDocStrings(parentNode, srcNode):
- """
- Check for the various possible docstring attributes, and attach
- coresponding child nodes if found.
- """
- def makeDocElement(name, content):
- node = libxml2.newNode(name)
- node.addChild(libxml2.newText(content))
- return node
-
- autodoc = getAttr(srcNode, "python_autodoc")
- docstr = getAttr(srcNode, "feature_docstring")
- if autodoc:
- parentNode.addChild(makeDocElement("autodoc", autodoc))
- if docstr:
- parentNode.addChild(makeDocElement("docstring", docstr))
-
-
-
-
-
-def main():
- if not os.path.exists(SRC):
- print "Unable to find %s, please run this script from the root wxPython directory." % SRC
- sys.exit(1)
-
- newDoc = libxml2.newDoc("1.0")
- newTopNode = libxml2.newNode("wxPython-metadata")
- newDoc.addChild(newTopNode)
-
- for m in getModuleNames():
- processModule(newTopNode, m)
-
- newDoc.saveFormatFile(DEST, True)
- print "Wrote simplified metadata to", DEST
-
-#---------------------------------------------------------------------------
-
-if __name__ == "__main__":
- main()