blob: 80dca7bbbbd8211ea080b94f958f3f4daa4886ef [file] [log] [blame]
Daniel Veillardd2897fd2002-01-30 16:37:32 +00001#!/usr/bin/python -u
2#
3# generate python wrappers from the XML API description
4#
5
6functions = {}
7
Daniel Veillard36ed5292002-01-30 23:49:06 +00008import string
Daniel Veillard1971ee22002-01-31 20:29:19 +00009
10#######################################################################
11#
12# That part if purely the API acquisition phase from the
13# XML API description
14#
15#######################################################################
16import os
Daniel Veillardd2897fd2002-01-30 16:37:32 +000017import xmllib
18try:
19 import sgmlop
20except ImportError:
21 sgmlop = None # accelerator not available
22
23debug = 0
24
25if sgmlop:
26 class FastParser:
27 """sgmlop based XML parser. this is typically 15x faster
28 than SlowParser..."""
29
30 def __init__(self, target):
31
32 # setup callbacks
33 self.finish_starttag = target.start
34 self.finish_endtag = target.end
35 self.handle_data = target.data
36
37 # activate parser
38 self.parser = sgmlop.XMLParser()
39 self.parser.register(self)
40 self.feed = self.parser.feed
41 self.entity = {
42 "amp": "&", "gt": ">", "lt": "<",
43 "apos": "'", "quot": '"'
44 }
45
46 def close(self):
47 try:
48 self.parser.close()
49 finally:
50 self.parser = self.feed = None # nuke circular reference
51
52 def handle_entityref(self, entity):
53 # <string> entity
54 try:
55 self.handle_data(self.entity[entity])
56 except KeyError:
57 self.handle_data("&%s;" % entity)
58
59else:
60 FastParser = None
61
62
63class SlowParser(xmllib.XMLParser):
64 """slow but safe standard parser, based on the XML parser in
65 Python's standard library."""
66
67 def __init__(self, target):
68 self.unknown_starttag = target.start
69 self.handle_data = target.data
70 self.unknown_endtag = target.end
71 xmllib.XMLParser.__init__(self)
72
73def getparser(target = None):
74 # get the fastest available parser, and attach it to an
75 # unmarshalling object. return both objects.
76 if target == None:
77 target = docParser()
78 if FastParser:
79 return FastParser(target), target
80 return SlowParser(target), target
81
82class docParser:
83 def __init__(self):
84 self._methodname = None
85 self._data = []
86 self.in_function = 0
87
88 def close(self):
89 if debug:
90 print "close"
91
92 def getmethodname(self):
93 return self._methodname
94
95 def data(self, text):
96 if debug:
97 print "data %s" % text
98 self._data.append(text)
99
100 def start(self, tag, attrs):
101 if debug:
102 print "start %s, %s" % (tag, attrs)
103 if tag == 'function':
104 self._data = []
105 self.in_function = 1
106 self.function = None
107 self.function_args = []
108 self.function_descr = None
109 self.function_return = None
110 self.function_file = None
111 if attrs.has_key('name'):
112 self.function = attrs['name']
113 if attrs.has_key('file'):
114 self.function_file = attrs['file']
115 elif tag == 'info':
116 self._data = []
117 elif tag == 'arg':
118 if self.in_function == 1:
119 self.function_arg_name = None
120 self.function_arg_type = None
121 self.function_arg_info = None
122 if attrs.has_key('name'):
123 self.function_arg_name = attrs['name']
124 if attrs.has_key('type'):
125 self.function_arg_type = attrs['type']
126 if attrs.has_key('info'):
127 self.function_arg_info = attrs['info']
128 elif tag == 'return':
129 if self.in_function == 1:
130 self.function_return_type = None
131 self.function_return_info = None
132 if attrs.has_key('type'):
133 self.function_return_type = attrs['type']
134 if attrs.has_key('info'):
135 self.function_return_info = attrs['info']
136
137
138 def end(self, tag):
139 if debug:
140 print "end %s" % tag
141 if tag == 'function':
142 if self.function != None:
143 function(self.function, self.function_descr,
144 self.function_return, self.function_args,
145 self.function_file)
146 self.in_function = 0
147 elif tag == 'arg':
148 if self.in_function == 1:
149 self.function_args.append([self.function_arg_name,
150 self.function_arg_type,
151 self.function_arg_info])
152 elif tag == 'return':
153 if self.in_function == 1:
154 self.function_return = [self.function_return_type,
155 self.function_return_info]
156 elif tag == 'info':
157 str = ''
158 for c in self._data:
159 str = str + c
160 if self.in_function == 1:
161 self.function_descr = str
162
163
164def function(name, desc, ret, args, file):
165 global functions
166
167 functions[name] = (desc, ret, args, file)
168
Daniel Veillard1971ee22002-01-31 20:29:19 +0000169#######################################################################
170#
171# Some filtering rukes to drop functions/types which should not
172# be exposed as-is on the Python interface
173#
174#######################################################################
Daniel Veillard36ed5292002-01-30 23:49:06 +0000175
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000176skipped_modules = {
177 'xmlmemory': None,
Daniel Veillard96fe0952002-01-30 20:52:23 +0000178 'DOCBparser': None,
179 'SAX': None,
180 'hash': None,
181 'list': None,
182 'threads': None,
Daniel Veillard1971ee22002-01-31 20:29:19 +0000183 'xpointer': None,
Daniel Veillard96fe0952002-01-30 20:52:23 +0000184}
185skipped_types = {
186 'int *': "usually a return type",
187 'xmlSAXHandlerPtr': "not the proper interface for SAX",
188 'htmlSAXHandlerPtr': "not the proper interface for SAX",
189 'xmlParserCtxtPtr': "not the proper interface for the parser",
190 'htmlParserCtxtPtr': "not the proper interface for the parser",
191 'xmlRMutexPtr': "thread specific, skipped",
192 'xmlMutexPtr': "thread specific, skipped",
193 'xmlGlobalStatePtr': "thread specific, skipped",
194 'xmlListPtr': "internal representation not suitable for python",
195 'xmlBufferPtr': "internal representation not suitable for python",
196 'FILE *': None,
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000197}
Daniel Veillard1971ee22002-01-31 20:29:19 +0000198
199#######################################################################
200#
201# Table of remapping to/from the python type or class to the C
202# counterpart.
203#
204#######################################################################
205
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000206py_types = {
Daniel Veillard96fe0952002-01-30 20:52:23 +0000207 'void': (None, None, None, None),
208 'int': ('i', None, "int", "int"),
209 'long': ('i', None, "int", "int"),
210 'double': ('d', None, "double", "double"),
211 'unsigned int': ('i', None, "int", "int"),
212 'xmlChar': ('c', None, "int", "int"),
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000213 'unsigned char *': ('z', None, "charPtr", "char *"),
214 'char *': ('z', None, "charPtr", "char *"),
215 'const char *': ('z', None, "charPtr", "char *"),
216 'xmlChar *': ('z', None, "xmlCharPtr", "xmlChar *"),
217 'const xmlChar *': ('z', None, "xmlCharPtr", "xmlChar *"),
Daniel Veillard96fe0952002-01-30 20:52:23 +0000218 'xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
219 'const xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
220 'xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
221 'const xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
222 'xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
223 'const xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
224 'xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
225 'const xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
226 'xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
227 'const xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
228 'xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
229 'const xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
230 'xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
231 'const xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
232 'xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
233 'const xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
Daniel Veillard1971ee22002-01-31 20:29:19 +0000234 'xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
235 'const xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
236 'xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
237 'const xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
238 'xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
239 'const xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
240 'xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
241 'const xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
242 'xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
243 'const xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
244 'xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
245 'const xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
Daniel Veillard96fe0952002-01-30 20:52:23 +0000246 'xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
247 'const xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
248 'xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
249 'const xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
250 'htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
251 'const htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
252 'htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
253 'const htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
254 'htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
255 'const htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
256 'htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
257 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
Daniel Veillard1971ee22002-01-31 20:29:19 +0000258 'xmlXPathContextPtr': ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"),
259 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"),
260}
261
262py_return_types = {
263 'xmlXPathObjectPtr': ('O', "foo", "xmlXPathObjectPtr", "xmlXPathObjectPtr"),
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000264}
265
266unknown_types = {}
267
Daniel Veillard1971ee22002-01-31 20:29:19 +0000268#######################################################################
269#
270# This part writes the C <-> Python stubs libxml2-py.[ch] and
271# the table libxml2-export.c to add when registrering the Python module
272#
273#######################################################################
274
275def skip_function(name):
276 if name[0:12] == "xmlXPathWrap":
277 return 1
278# if name[0:11] == "xmlXPathNew":
279# return 1
280 return 0
281
Daniel Veillard96fe0952002-01-30 20:52:23 +0000282def print_function_wrapper(name, output, export, include):
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000283 global py_types
284 global unknown_types
285 global functions
286 global skipped_modules
287
288 try:
289 (desc, ret, args, file) = functions[name]
290 except:
291 print "failed to get function %s infos"
292 return
293
294 if skipped_modules.has_key(file):
295 return 0
Daniel Veillard1971ee22002-01-31 20:29:19 +0000296 if skip_function(name) == 1:
297 return 0
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000298
299 c_call = "";
300 format=""
301 format_args=""
302 c_args=""
303 c_return=""
Daniel Veillard96fe0952002-01-30 20:52:23 +0000304 c_convert=""
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000305 for arg in args:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000306 # This should be correct
307 if arg[1][0:6] == "const ":
308 arg[1] = arg[1][6:]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000309 c_args = c_args + " %s %s;\n" % (arg[1], arg[0])
310 if py_types.has_key(arg[1]):
Daniel Veillard96fe0952002-01-30 20:52:23 +0000311 (f, t, n, c) = py_types[arg[1]]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000312 if f != None:
313 format = format + f
314 if t != None:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000315 format_args = format_args + ", &pyobj_%s" % (arg[0])
316 c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0])
317 c_convert = c_convert + \
318 " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0],
319 arg[1], t, arg[0]);
320 else:
321 format_args = format_args + ", &%s" % (arg[0])
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000322 if c_call != "":
323 c_call = c_call + ", ";
324 c_call = c_call + "%s" % (arg[0])
325 else:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000326 if skipped_types.has_key(arg[1]):
327 return 0
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000328 if unknown_types.has_key(arg[1]):
329 lst = unknown_types[arg[1]]
330 lst.append(name)
331 else:
332 unknown_types[arg[1]] = [name]
333 return -1
334 if format != "":
335 format = format + ":%s" % (name)
336
337 if ret[0] == 'void':
338 c_call = "\n %s(%s);\n" % (name, c_call);
339 ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n"
340 elif py_types.has_key(ret[0]):
Daniel Veillard96fe0952002-01-30 20:52:23 +0000341 (f, t, n, c) = py_types[ret[0]]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000342 c_return = " %s c_retval;\n" % (ret[0])
343 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
Daniel Veillard96fe0952002-01-30 20:52:23 +0000344 ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c)
345 ret_convert = ret_convert + " return(py_retval);\n"
Daniel Veillard1971ee22002-01-31 20:29:19 +0000346 elif py_return_types.has_key(ret[0]):
347 (f, t, n, c) = py_return_types[ret[0]]
348 c_return = " %s c_retval;\n" % (ret[0])
349 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
350 ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c)
351 ret_convert = ret_convert + " return(py_retval);\n"
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000352 else:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000353 if skipped_types.has_key(ret[0]):
354 return 0
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000355 if unknown_types.has_key(ret[0]):
356 lst = unknown_types[ret[0]]
357 lst.append(name)
358 else:
359 unknown_types[ret[0]] = [name]
360 return -1
361
Daniel Veillard96fe0952002-01-30 20:52:23 +0000362 include.write("PyObject * ")
363 include.write("libxml_%s(PyObject *self, PyObject *args);\n" % (name))
Daniel Veillard9589d452002-02-02 10:28:17 +0000364
Daniel Veillard96fe0952002-01-30 20:52:23 +0000365 export.write(" { \"%s\", libxml_%s, METH_VARARGS },\n" % (name, name))
Daniel Veillard9589d452002-02-02 10:28:17 +0000366
367 if file == "python":
368 # Those have been manually generated
369 return 1
370
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000371 output.write("PyObject *\n")
372 output.write("libxml_%s(PyObject *self, PyObject *args) {\n" % (name))
373 if ret[0] != 'void':
374 output.write(" PyObject *py_retval;\n")
375 if c_return != "":
376 output.write(c_return)
377 if c_args != "":
378 output.write(c_args)
379 if format != "":
380 output.write("\n if (!PyArg_ParseTuple(args, \"%s\"%s))\n" %
381 (format, format_args))
382 output.write(" return(NULL);\n")
Daniel Veillard96fe0952002-01-30 20:52:23 +0000383 if c_convert != "":
384 output.write(c_convert)
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000385
386 output.write(c_call)
387 output.write(ret_convert)
388 output.write("}\n\n")
389 return 1
390
391try:
Daniel Veillard63276972002-01-31 23:49:05 +0000392 f = open("../doc/libxml2-api.xml")
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000393 data = f.read()
394 (parser, target) = getparser()
395 parser.feed(data)
396 parser.close()
397except IOError, msg:
398 print file, ":", msg
399
Daniel Veillard9589d452002-02-02 10:28:17 +0000400n = len(functions.keys())
401print "Found %d functions in libxml2-api.xml" % (n)
402
403py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject")
404try:
405 f = open("libxml2-python-api.xml")
406 data = f.read()
407 (parser, target) = getparser()
408 parser.feed(data)
409 parser.close()
410except IOError, msg:
411 print file, ":", msg
412
413
414print "Found %d functions in libxml2-python-api.xml" % (
415 len(functions.keys()) - n)
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000416nb_wrap = 0
417failed = 0
418skipped = 0
419
Daniel Veillard96fe0952002-01-30 20:52:23 +0000420include = open("libxml2-py.h", "w")
421include.write("/* Generated */\n\n")
422export = open("libxml2-export.c", "w")
423export.write("/* Generated */\n\n")
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000424wrapper = open("libxml2-py.c", "w")
425wrapper.write("/* Generated */\n\n")
426wrapper.write("#include <Python.h>\n")
427wrapper.write("#include <libxml/tree.h>\n")
428wrapper.write("#include \"libxml_wrap.h\"\n")
429wrapper.write("#include \"libxml2-py.h\"\n\n")
430for function in functions.keys():
Daniel Veillard96fe0952002-01-30 20:52:23 +0000431 ret = print_function_wrapper(function, wrapper, export, include)
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000432 if ret < 0:
433 failed = failed + 1
Daniel Veillard36ed5292002-01-30 23:49:06 +0000434 del functions[function]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000435 if ret == 0:
436 skipped = skipped + 1
Daniel Veillard36ed5292002-01-30 23:49:06 +0000437 del functions[function]
438 if ret == 1:
439 nb_wrap = nb_wrap + 1
Daniel Veillard96fe0952002-01-30 20:52:23 +0000440include.close()
441export.close()
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000442wrapper.close()
443
444print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
445 failed, skipped);
446print "Missing type converters: %s" % (unknown_types.keys())
Daniel Veillard36ed5292002-01-30 23:49:06 +0000447
Daniel Veillard1971ee22002-01-31 20:29:19 +0000448#######################################################################
449#
450# This part writes part of the Python front-end classes based on
451# mapping rules between types and classes and also based on function
452# renaming to get consistent function names at the Python level
453#
454#######################################################################
455
456#
457# The type automatically remapped to generated classes
458#
459classes_type = {
460 "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
461 "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
462 "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
463 "xmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
464 "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
465 "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
466 "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
467 "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
468 "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
469 "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
470 "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
471 "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
472 "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
473 "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
474 "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
475 "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
476 "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
477 "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
478 "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
479}
480
481converter_type = {
482 "xmlXPathObjectPtr": "xpathObjectRet(%s)",
483}
484
485primary_classes = ["xmlNode", "xmlDoc"]
486
487classes_ancestor = {
488 "xmlNode" : "xmlCore",
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000489 "xmlDtd" : "xmlNode",
490 "xmlDoc" : "xmlNode",
491 "xmlAttr" : "xmlNode",
492 "xmlNs" : "xmlNode",
493 "xmlEntity" : "xmlNode",
494 "xmlElement" : "xmlNode",
495 "xmlAttribute" : "xmlNode",
Daniel Veillard1971ee22002-01-31 20:29:19 +0000496}
497classes_destructors = {
498 "xpathContext": "xmlXPathFreeContext",
499}
500
Daniel Veillard36ed5292002-01-30 23:49:06 +0000501function_classes = {}
Daniel Veillard1971ee22002-01-31 20:29:19 +0000502
503function_classes["None"] = []
504for type in classes_type.keys():
505 function_classes[classes_type[type][2]] = []
506
507#
508# Build the list of C types to look for ordered to start with primary classes
509#
510ctypes = []
Daniel Veillard9589d452002-02-02 10:28:17 +0000511classes_list = []
Daniel Veillard1971ee22002-01-31 20:29:19 +0000512ctypes_processed = {}
Daniel Veillard9589d452002-02-02 10:28:17 +0000513classes_processed = {}
Daniel Veillard1971ee22002-01-31 20:29:19 +0000514for classe in primary_classes:
Daniel Veillard9589d452002-02-02 10:28:17 +0000515 classes_list.append(classe)
516 classes_processed[classe] = ()
Daniel Veillard1971ee22002-01-31 20:29:19 +0000517 for type in classes_type.keys():
518 tinfo = classes_type[type]
519 if tinfo[2] == classe:
520 ctypes.append(type)
521 ctypes_processed[type] = ()
522for type in classes_type.keys():
523 if ctypes_processed.has_key(type):
524 continue
525 tinfo = classes_type[type]
Daniel Veillard9589d452002-02-02 10:28:17 +0000526 if not classes_processed.has_key(tinfo[2]):
527 classes_list.append(tinfo[2])
528 classes_processed[tinfo[2]] = ()
529
Daniel Veillard1971ee22002-01-31 20:29:19 +0000530 ctypes.append(type)
531 ctypes_processed[type] = ()
532
533def nameFixup(function, classe, type):
534 listname = classe + "List"
535 ll = len(listname)
536 l = len(classe)
537 if name[0:l] == listname:
538 func = name[l:]
539 func = string.lower(func[0:1]) + func[1:]
540 elif name[0:l] == classe:
541 func = name[l:]
542 func = string.lower(func[0:1]) + func[1:]
Daniel Veillard9589d452002-02-02 10:28:17 +0000543 elif name[0:7] == "libxml_":
544 func = name[7:]
545 func = string.lower(func[0:1]) + func[1:]
Daniel Veillard1971ee22002-01-31 20:29:19 +0000546 elif name[0:6] == "xmlGet":
547 func = name[6:]
548 func = string.lower(func[0:1]) + func[1:]
549 elif name[0:3] == "xml":
Daniel Veillard36ed5292002-01-30 23:49:06 +0000550 func = name[3:]
551 func = string.lower(func[0:1]) + func[1:]
Daniel Veillard36ed5292002-01-30 23:49:06 +0000552 else:
Daniel Veillard1971ee22002-01-31 20:29:19 +0000553 func = name
554 if func[0:5] == "xPath":
555 func = "xpath" + func[5:]
556 elif func[0:4] == "xPtr":
557 func = "xpointer" + func[4:]
558 elif func[0:8] == "xInclude":
559 func = "xinclude" + func[8:]
560 elif func[0:2] == "iD":
561 func = "ID" + func[2:]
562 elif func[0:3] == "uRI":
563 func = "URI" + func[3:]
564 elif func[0:4] == "uTF8":
565 func = "UTF8" + func[4:]
566 return func
Daniel Veillard36ed5292002-01-30 23:49:06 +0000567
Daniel Veillard1971ee22002-01-31 20:29:19 +0000568for name in functions.keys():
569 found = 0;
570 (desc, ret, args, file) = functions[name]
571 for type in ctypes:
572 classe = classes_type[type][2]
573
574 if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == type:
575 found = 1
576 func = nameFixup(name, classe, type)
577 info = (0, func, name, ret, args, file)
578 function_classes[classe].append(info)
579 elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == type:
580 found = 1
581 func = nameFixup(name, classe, type)
582 info = (1, func, name, ret, args, file)
583 function_classes[classe].append(info)
584 elif name[0:4] == "html" and len(args) >= 1 and args[0][1] == type:
585 found = 1
586 func = nameFixup(name, classe, type)
587 info = (0, func, name, ret, args, file)
588 function_classes[classe].append(info)
589 elif name[0:4] == "html" and len(args) >= 2 and args[1][1] == type:
590 found = 1
591 func = nameFixup(name, classe, type)
592 info = (1, func, name, ret, args, file)
593 function_classes[classe].append(info)
594 if found == 1:
595 break
596 if found == 1:
597 continue
598 if name[0:8] == "xmlXPath":
599 continue
600 if name[0:6] == "xmlStr":
601 continue
602 if name[0:10] == "xmlCharStr":
603 continue
604 func = nameFixup(name, "None", file)
605 info = (0, func, name, ret, args, file)
606 function_classes['None'].append(info)
Daniel Veillard36ed5292002-01-30 23:49:06 +0000607
608classes = open("libxml2class.py", "w")
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000609txt = open("libxml2class.txt", "w")
610txt.write(" Generated Classes for libxml2-python\n\n")
Daniel Veillard36ed5292002-01-30 23:49:06 +0000611
Daniel Veillard1971ee22002-01-31 20:29:19 +0000612def functionCompare(info1, info2):
613 (index1, func1, name1, ret1, args1, file1) = info1
614 (index2, func2, name2, ret2, args2, file2) = info2
615 if file1 < file2:
616 return -1
617 if file1 > file2:
618 return 1
619 if func1 < func2:
620 return -1
621 if func1 > func2:
622 return 1
623 return 0
624
625def writeDoc(name, args, indent, output):
626 if functions[name][0] == None or functions[name][0] == "":
627 return
628 val = functions[name][0]
629 val = string.replace(val, "NULL", "None");
630 output.write(indent)
631 output.write('"""')
632 while len(val) > 60:
633 str = val[0:60]
634 i = string.rfind(str, " ");
635 if i < 0:
636 i = 60
637 str = val[0:i]
638 val = val[i:]
639 output.write(str)
640 output.write('\n ');
641 output.write(indent)
642 output.write(val);
643 output.write('"""\n')
644
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000645txt.write("#\n# Global functions of the module\n#\n\n")
Daniel Veillard36ed5292002-01-30 23:49:06 +0000646if function_classes.has_key("None"):
Daniel Veillard1971ee22002-01-31 20:29:19 +0000647 flist = function_classes["None"]
648 flist.sort(functionCompare)
649 oldfile = ""
650 for info in flist:
Daniel Veillard36ed5292002-01-30 23:49:06 +0000651 (index, func, name, ret, args, file) = info
Daniel Veillard1971ee22002-01-31 20:29:19 +0000652 if file != oldfile:
653 classes.write("#\n# Functions from module %s\n#\n\n" % file)
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000654 txt.write("\n# functions from module %s\n" % file)
Daniel Veillard1971ee22002-01-31 20:29:19 +0000655 oldfile = file
Daniel Veillard36ed5292002-01-30 23:49:06 +0000656 classes.write("def %s(" % func)
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000657 txt.write("%s()\n" % func);
Daniel Veillard36ed5292002-01-30 23:49:06 +0000658 n = 0
659 for arg in args:
660 if n != 0:
661 classes.write(", ")
662 classes.write("%s" % arg[0])
663 n = n + 1
664 classes.write("):\n")
Daniel Veillard1971ee22002-01-31 20:29:19 +0000665 writeDoc(name, args, ' ', classes);
Daniel Veillard36ed5292002-01-30 23:49:06 +0000666 if ret[0] != "void":
667 classes.write(" ret = ");
668 else:
669 classes.write(" ");
670 classes.write("_libxml.%s(" % name)
671 n = 0
672 for arg in args:
673 if n != 0:
674 classes.write(", ");
675 classes.write("%s" % arg[0])
676 if classes_type.has_key(arg[1]):
677 classes.write(classes_type[arg[1]][0])
678 n = n + 1
679 classes.write(")\n");
680 if ret[0] != "void":
681 if classes_type.has_key(ret[0]):
682 classes.write(" if ret == None: return None\n");
683 classes.write(" return ");
684 classes.write(classes_type[ret[0]][1] % ("ret"));
685 classes.write("\n");
686 else:
687 classes.write(" return ret\n");
688 classes.write("\n");
689
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000690txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
Daniel Veillard9589d452002-02-02 10:28:17 +0000691for classname in classes_list:
Daniel Veillard36ed5292002-01-30 23:49:06 +0000692 if classname == "None":
693 pass
694 else:
Daniel Veillard1971ee22002-01-31 20:29:19 +0000695 if classes_ancestor.has_key(classname):
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000696 txt.write("\n\nClass %s(%s)\n" % (classname,
697 classes_ancestor[classname]))
Daniel Veillard1971ee22002-01-31 20:29:19 +0000698 classes.write("class %s(%s):\n" % (classname,
699 classes_ancestor[classname]))
Daniel Veillard36ed5292002-01-30 23:49:06 +0000700 classes.write(" def __init__(self, _obj=None):\n")
701 classes.write(" self._o = None\n")
Daniel Veillard1971ee22002-01-31 20:29:19 +0000702 classes.write(" %s.__init__(self, _obj=_obj)\n\n" % (
703 classes_ancestor[classname]))
Daniel Veillard36ed5292002-01-30 23:49:06 +0000704 else:
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000705 txt.write("Class %s()\n" % (classname))
Daniel Veillard1971ee22002-01-31 20:29:19 +0000706 classes.write("class %s:\n" % (classname))
Daniel Veillard36ed5292002-01-30 23:49:06 +0000707 classes.write(" def __init__(self, _obj=None):\n")
708 classes.write(" if _obj != None:self._o = _obj;return\n")
709 classes.write(" self._o = None\n\n");
Daniel Veillard1971ee22002-01-31 20:29:19 +0000710 if classes_destructors.has_key(classname):
711 classes.write(" def __del__(self):\n")
712 classes.write(" if self._o != None:\n")
713 classes.write(" _libxml.%s(self._o)\n" %
714 classes_destructors[classname]);
715 classes.write(" self._o = None\n\n");
Daniel Veillarda7340c82002-02-01 17:56:45 +0000716 classes.write(" def __repr__(self):\n")
717 format = "%s:%%s" % (classname)
718 classes.write(" return \"%s\" %% (self.name)\n\n" % (
719 format))
Daniel Veillard1971ee22002-01-31 20:29:19 +0000720 flist = function_classes[classname]
721 flist.sort(functionCompare)
722 oldfile = ""
723 for info in flist:
Daniel Veillard36ed5292002-01-30 23:49:06 +0000724 (index, func, name, ret, args, file) = info
Daniel Veillard1971ee22002-01-31 20:29:19 +0000725 if file != oldfile:
726 classes.write(" #\n")
727 classes.write(" # %s functions from module %s\n" % (
728 classname, file))
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000729 txt.write("\n # functions from module %s\n" % file)
Daniel Veillard1971ee22002-01-31 20:29:19 +0000730 classes.write(" #\n\n")
731 oldfile = file
Daniel Veillard36ed5292002-01-30 23:49:06 +0000732 classes.write(" def %s(self" % func)
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000733 txt.write(" %s()\n" % func);
Daniel Veillard36ed5292002-01-30 23:49:06 +0000734 n = 0
735 for arg in args:
736 if n != index:
737 classes.write(", %s" % arg[0])
738 n = n + 1
739 classes.write("):\n")
Daniel Veillard1971ee22002-01-31 20:29:19 +0000740 writeDoc(name, args, ' ', classes);
Daniel Veillard36ed5292002-01-30 23:49:06 +0000741 if ret[0] != "void":
742 classes.write(" ret = ");
743 else:
744 classes.write(" ");
745 classes.write("_libxml.%s(" % name)
746 n = 0
747 for arg in args:
748 if n != 0:
749 classes.write(", ");
750 if n != index:
751 classes.write("%s" % arg[0])
752 else:
753 classes.write("self");
754 if classes_type.has_key(arg[1]):
755 classes.write(classes_type[arg[1]][0])
756 n = n + 1
757 classes.write(")\n");
758 if ret[0] != "void":
759 if classes_type.has_key(ret[0]):
760 classes.write(" if ret == None: return None\n");
761 classes.write(" return ");
762 classes.write(classes_type[ret[0]][1] % ("ret"));
763 classes.write("\n");
Daniel Veillard1971ee22002-01-31 20:29:19 +0000764 elif converter_type.has_key(ret[0]):
765 classes.write(" if ret == None: return None\n");
766 classes.write(" return ");
767 classes.write(converter_type[ret[0]] % ("ret"));
768 classes.write("\n");
Daniel Veillard36ed5292002-01-30 23:49:06 +0000769 else:
770 classes.write(" return ret\n");
771 classes.write("\n");
772
Daniel Veillard253aa2c2002-02-02 09:17:16 +0000773txt.close()
Daniel Veillard36ed5292002-01-30 23:49:06 +0000774classes.close()