d07d2bc9d0
Removed RefDoc macros, instead made all the normal Docstring macros take an extra parameter to be used for the optional details postion of the docstring. The intent is that the docstrings put in the generated .py files checked in to CVS and delivered in releases will be only a paragraph or two, but when used for generating the epydoc reference docs they can optionally contain a lot more details. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@27216 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()
|