git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@27703 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			277 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			277 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/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()
 |