]> git.saurik.com Git - wxWidgets.git/blame - wxPython/docs/bin/simplify.py
Added XML simplification scripts for generating the wxPython metadata xml.
[wxWidgets.git] / wxPython / docs / bin / simplify.py
CommitLineData
685d8985
RD
1#!/usr/bin/python
2#---------------------------------------------------------------------------
3#
4# Like simplify.xsl but using Python so a few non-standard conversions can
5# also be done. (Currently it is still about the same as simplify.xsl...)
6#
7#---------------------------------------------------------------------------
8
9import sys
10import os
11import libxml2
12
13
14DEST="docs/xml/wxPython-metadata.xml"
15SRC="docs/xml-raw"
16
17
18
19def getModuleNames():
20 """
21 Get the list of extension modules from setup.py
22 """
23 import setup
24 names = [e.name[1:] for e in setup.wxpExtensions]
25 return names
26
27
28
29def getAttr(node, name):
30 """
31 Get a value by name from the <attribute> elements in the SWIG XML output
32 """
33 path = "./attributelist/attribute[@name='%s']/@value" % name
34 n = node.xpathEval2(path)
35 if len(n):
36 return n[0].content
37 else:
38 return None
39
40
41
42
43
44def processModule(newDocNode, modulename):
45 """
46 Start processing a new XML file, create a module element and then
47 find the include elements
48 """
49 filename = os.path.join(SRC, "%s_swig.xml" % modulename)
50 print filename
51
52 doc = libxml2.parseFile(filename)
53 topNode = doc.getRootElement()
54
55 # make a module element
56 name = getAttr(topNode, "module")
57 assert name == modulename # sanity check
58
59 moduleNode = libxml2.newNode("module")
60 moduleNode.setProp("name", name)
61 newDocNode.addChild(moduleNode)
62
63 node = topNode.children
64 while node is not None:
65 if node.name == "include":
66 processInclude(moduleNode, node, 0)
67 node = node.next
68
69 doc.freeDoc()
70
71
72
73def processInclude(moduleNode, includeNode, level):
74 """
75 Almost everything we are interested in is inside an <include>,
76 which may also be nested.
77 """
78
79 # check first for imports
80 for node in includeNode.xpathEval2("import"):
81 try:
82 modNode = node.xpathEval2("module")[0]
83 name = getAttr(modNode, "name")
84 impNode = libxml2.newNode("import")
85 impNode.setProp("name", name)
86 moduleNode.addChild(impNode)
87 except IndexError:
88 pass
89
90 # then look through the child nodes for other things we need
91 node = includeNode.children
92 while node is not None:
93 if node.name == "insert":
94 processInsert(moduleNode, node, level)
95
96 elif node.name == "class":
97 processClass(moduleNode, node, level)
98
99 elif node.name == "cdecl" and getAttr(node, "view") == "globalfunctionHandler":
100 func = libxml2.newNode("method")
101 func.setProp("name", getAttr(node, "sym_name"))
102 func.setProp("oldname", getAttr(node, "name"))
103 func.setProp("type", getAttr(node, "type"))
104 doCheckOverloaded(func, node)
105 doDocStrings(func, node)
106 doParamList(func, node)
107 moduleNode.addChild(func)
108
109
110 elif node.name == "include":
111 processInclude(moduleNode, node, level+1)
112
113 node = node.next
114
115
116
117def processInsert(parentNode, insertNode, level):
118 """
119 Check for pythoncode
120 """
121 if getAttr(insertNode, "section") == "python":
122 code = getAttr(insertNode, "code")
123 node = libxml2.newNode("pythoncode")
124 node.addChild(libxml2.newText(code))
125 parentNode.addChild(node)
126
127
128
129def processClass(parentNode, classNode, level):
130 """
131 Handle classes, constructors, methods, etc.
132 """
133 # make class element
134 klass = libxml2.newNode("class")
135 klass.setProp("name", getAttr(classNode, "sym_name"))
136 klass.setProp("oldname", getAttr(classNode, "name"))
137 klass.setProp("module", getAttr(classNode, "module"))
138 doDocStrings(klass, classNode)
139 parentNode.addChild(klass)
140
141 # check for baseclass(es)
142 for node in classNode.xpathEval2("attributelist/baselist/base"):
143 baseclass = libxml2.newNode("baseclass")
144 baseclass.setProp("name", node.prop("name"))
145 klass.addChild(baseclass)
146
147 # check for constructors/destructors
148 for type in ["constructor", "destructor"]:
149 for node in classNode.xpathEval2("%s | extend/%s" % (type, type)):
150 func = libxml2.newNode(type)
151 func.setProp("name", getAttr(node, "sym_name"))
152 if parentNode.name != "destructor":
153 doCheckOverloaded(func, node)
154 doDocStrings(func, node)
155 doParamList(func, node)
156 klass.addChild(func)
157
158 # check for cdecl's. In class scope we are interested in methods,
159 # static methods, or properties
160 for node in classNode.xpathEval2("cdecl | extend/cdecl"):
161 view = getAttr(node, "view")
162 if view == "memberfunctionHandler":
163 func = libxml2.newNode("method")
164 func.setProp("name", getAttr(node, "sym_name"))
165 func.setProp("type", getAttr(node, "type"))
166 doCheckOverloaded(func, node)
167 doDocStrings(func, node)
168 doParamList(func, node)
169 klass.addChild(func)
170
171 elif view == "staticmemberfunctionHandler":
172 func = libxml2.newNode("staticmethod")
173 func.setProp("name", getAttr(node, "sym_name"))
174 func.setProp("type", getAttr(node, "type"))
175 doCheckOverloaded(func, node)
176 doDocStrings(func, node)
177 doParamList(func, node)
178 klass.addChild(func)
179
180 elif view == "variableHandler":
181 prop = libxml2.newNode("property")
182 prop.setProp("name", getAttr(node, "sym_name"))
183 prop.setProp("type", getAttr(node, "type"))
184 if getAttr(node, "feature_immutable"):
185 prop.setProp("readonly", "yes")
186 else:
187 prop.setProp("readonly", "no")
188 doDocStrings(prop, node)
189 klass.addChild(prop)
190
191
192
193def doParamList(parentNode, srcNode):
194 """
195 Convert the parameter list
196 """
197 params = srcNode.xpathEval2("attributelist/parmlist/parm")
198 if params:
199 plist = libxml2.newNode("paramlist")
200 for p in params:
201 pnode = libxml2.newNode("param")
202 pnode.setProp("name", getAttr(p, "name"))
203 pnode.setProp("type", getAttr(p, "type"))
204 pnode.setProp("default", getAttr(p, "value"))
205 plist.addChild(pnode)
206 parentNode.addChild(plist)
207
208
209
210def doCheckOverloaded(parentNode, srcNode):
211 """
212 Set an attribute indicating if the srcNode is tagged as being overloaded
213 """
214 if srcNode.xpathEval2("./attributelist/attribute[@name='sym_overloaded']"):
215 parentNode.setProp("overloaded", "yes")
216 else:
217 parentNode.setProp("overloaded", "no")
218
219
220
221def doDocStrings(parentNode, srcNode):
222 """
223 Check for the various possible docstring attributes, and attach
224 coresponding child nodes if found.
225 """
226 def makeDocElement(name, content):
227 node = libxml2.newNode(name)
228 node.addChild(libxml2.newText(content))
229 return node
230
231 autodoc = getAttr(srcNode, "python_autodoc")
232 docstr = getAttr(srcNode, "feature_docstring")
233 refdoc = getAttr(srcNode, "feature_refdoc")
234 if autodoc:
235 parentNode.addChild(makeDocElement("autodoc", autodoc))
236 if docstr:
237 parentNode.addChild(makeDocElement("docstring", docstr))
238 if refdoc:
239 parentNode.addChild(makeDocElement("refdoc", refdoc))
240
241
242
243
244
245def main():
246 if not os.path.exists(SRC):
247 print "Unable to find %s, please run this script from the root wxPython directory." % SRC
248 sys.exit(1)
249
250 newDoc = libxml2.newDoc("1.0")
251 newTopNode = libxml2.newNode("wxPython-metadata")
252 newDoc.addChild(newTopNode)
253
254 for m in getModuleNames():
255 processModule(newTopNode, m)
256
257 newDoc.saveFormatFile(DEST, True)
258
259
260#---------------------------------------------------------------------------
261
262if __name__ == "__main__":
263 main()