wxWidgets/wxPython/docs/bin/simplify.py
Robin Dunn d07d2bc9d0 Some docstring additions, reformats and epydoc markup.
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
2004-05-12 00:17:48 +00:00

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()