* src/libvirt.c: fixing a bug before the release of 0.0.5
[libvirt-python/ericb.git] / generator.py
blobd9fa809146dfbe96dd5610a3369660bd958abe24
1 #!/usr/bin/python -u
3 # generate python wrappers from the XML API description
6 functions = {}
7 enums = {} # { enumType: { enumConstant: enumValue } }
9 import os
10 import sys
11 import string
13 if __name__ == "__main__":
14 # launched as a script
15 srcPref = os.path.dirname(sys.argv[0])
16 else:
17 # imported
18 srcPref = os.path.dirname(__file__)
20 #######################################################################
22 # That part if purely the API acquisition phase from the
23 # libvirt API description
25 #######################################################################
26 import os
27 import xmllib
28 try:
29 import sgmlop
30 except ImportError:
31 sgmlop = None # accelerator not available
33 debug = 0
35 if sgmlop:
36 class FastParser:
37 """sgmlop based XML parser. this is typically 15x faster
38 than SlowParser..."""
40 def __init__(self, target):
42 # setup callbacks
43 self.finish_starttag = target.start
44 self.finish_endtag = target.end
45 self.handle_data = target.data
47 # activate parser
48 self.parser = sgmlop.XMLParser()
49 self.parser.register(self)
50 self.feed = self.parser.feed
51 self.entity = {
52 "amp": "&", "gt": ">", "lt": "<",
53 "apos": "'", "quot": '"'
56 def close(self):
57 try:
58 self.parser.close()
59 finally:
60 self.parser = self.feed = None # nuke circular reference
62 def handle_entityref(self, entity):
63 # <string> entity
64 try:
65 self.handle_data(self.entity[entity])
66 except KeyError:
67 self.handle_data("&%s;" % entity)
69 else:
70 FastParser = None
73 class SlowParser(xmllib.XMLParser):
74 """slow but safe standard parser, based on the XML parser in
75 Python's standard library."""
77 def __init__(self, target):
78 self.unknown_starttag = target.start
79 self.handle_data = target.data
80 self.unknown_endtag = target.end
81 xmllib.XMLParser.__init__(self)
83 def getparser(target = None):
84 # get the fastest available parser, and attach it to an
85 # unmarshalling object. return both objects.
86 if target is None:
87 target = docParser()
88 if FastParser:
89 return FastParser(target), target
90 return SlowParser(target), target
92 class docParser:
93 def __init__(self):
94 self._methodname = None
95 self._data = []
96 self.in_function = 0
98 def close(self):
99 if debug:
100 print "close"
102 def getmethodname(self):
103 return self._methodname
105 def data(self, text):
106 if debug:
107 print "data %s" % text
108 self._data.append(text)
110 def start(self, tag, attrs):
111 if debug:
112 print "start %s, %s" % (tag, attrs)
113 if tag == 'function':
114 self._data = []
115 self.in_function = 1
116 self.function = None
117 self.function_cond = None
118 self.function_args = []
119 self.function_descr = None
120 self.function_return = None
121 self.function_file = None
122 if attrs.has_key('name'):
123 self.function = attrs['name']
124 if attrs.has_key('file'):
125 self.function_file = attrs['file']
126 elif tag == 'cond':
127 self._data = []
128 elif tag == 'info':
129 self._data = []
130 elif tag == 'arg':
131 if self.in_function == 1:
132 self.function_arg_name = None
133 self.function_arg_type = None
134 self.function_arg_info = None
135 if attrs.has_key('name'):
136 self.function_arg_name = attrs['name']
137 if self.function_arg_name == 'from':
138 self.function_arg_name = 'frm'
139 if attrs.has_key('type'):
140 self.function_arg_type = attrs['type']
141 if attrs.has_key('info'):
142 self.function_arg_info = attrs['info']
143 elif tag == 'return':
144 if self.in_function == 1:
145 self.function_return_type = None
146 self.function_return_info = None
147 self.function_return_field = None
148 if attrs.has_key('type'):
149 self.function_return_type = attrs['type']
150 if attrs.has_key('info'):
151 self.function_return_info = attrs['info']
152 if attrs.has_key('field'):
153 self.function_return_field = attrs['field']
154 elif tag == 'enum':
155 enum(attrs['type'],attrs['name'],attrs['value'])
157 def end(self, tag):
158 if debug:
159 print "end %s" % tag
160 if tag == 'function':
161 if self.function != None:
162 function(self.function, self.function_descr,
163 self.function_return, self.function_args,
164 self.function_file, self.function_cond)
165 self.in_function = 0
166 elif tag == 'arg':
167 if self.in_function == 1:
168 self.function_args.append([self.function_arg_name,
169 self.function_arg_type,
170 self.function_arg_info])
171 elif tag == 'return':
172 if self.in_function == 1:
173 self.function_return = [self.function_return_type,
174 self.function_return_info,
175 self.function_return_field]
176 elif tag == 'info':
177 str = ''
178 for c in self._data:
179 str = str + c
180 if self.in_function == 1:
181 self.function_descr = str
182 elif tag == 'cond':
183 str = ''
184 for c in self._data:
185 str = str + c
186 if self.in_function == 1:
187 self.function_cond = str
190 def function(name, desc, ret, args, file, cond):
191 functions[name] = (desc, ret, args, file, cond)
193 def enum(type, name, value):
194 if not enums.has_key(type):
195 enums[type] = {}
196 enums[type][name] = value
198 #######################################################################
200 # Some filtering rukes to drop functions/types which should not
201 # be exposed as-is on the Python interface
203 #######################################################################
205 functions_failed = []
206 functions_skipped = [
207 "virConnectListDomains" , "virDomainGetUUID"
210 skipped_modules = {
213 skipped_types = {
214 'int *': "usually a return type",
217 #######################################################################
219 # Table of remapping to/from the python type or class to the C
220 # counterpart.
222 #######################################################################
224 py_types = {
225 'void': (None, None, None, None),
226 'int': ('i', None, "int", "int"),
227 'long': ('i', None, "int", "int"),
228 'double': ('d', None, "double", "double"),
229 'unsigned int': ('i', None, "int", "int"),
230 'unsigned long': ('i', None, "int", "int"),
231 'unsigned char *': ('z', None, "charPtr", "char *"),
232 'char *': ('z', None, "charPtr", "char *"),
233 'const char *': ('z', None, "charPtrConst", "const char *"),
234 'virDomainPtr': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
235 'const virDomainPtr': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
236 'virDomain *': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
237 'const virDomain *': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
238 'virConnectPtr': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
239 'const virConnectPtr': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
240 'virConnect *': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
241 'const virConnect *': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
244 py_return_types = {
247 unknown_types = {}
249 foreign_encoding_args = (
252 #######################################################################
254 # This part writes the C <-> Python stubs libxml2-py.[ch] and
255 # the table libxml2-export.c to add when registrering the Python module
257 #######################################################################
259 # Class methods which are written by hand in libvir.c but the Python-level
260 # code is still automatically generated (so they are not in skip_function()).
261 skip_impl = (
262 'virConnectListDomainsID',
263 'virDomainGetInfo',
264 'virDomainGetUUID',
267 def skip_function(name):
268 if name == "virConnectClose":
269 return 1
270 if name == "virDomainFree":
271 return 1
273 return 0
275 def print_function_wrapper(name, output, export, include):
276 global py_types
277 global unknown_types
278 global functions
279 global skipped_modules
281 try:
282 (desc, ret, args, file, cond) = functions[name]
283 except:
284 print "failed to get function %s infos"
285 return
287 if skipped_modules.has_key(file):
288 return 0
289 if skip_function(name) == 1:
290 return 0
291 if name in skip_impl:
292 # Don't delete the function entry in the caller.
293 return 1
295 c_call = "";
296 format=""
297 format_args=""
298 c_args=""
299 c_return=""
300 c_convert=""
301 num_bufs=0
302 for arg in args:
303 # This should be correct
304 if arg[1][0:6] == "const ":
305 arg[1] = arg[1][6:]
306 c_args = c_args + " %s %s;\n" % (arg[1], arg[0])
307 if py_types.has_key(arg[1]):
308 (f, t, n, c) = py_types[arg[1]]
309 if (f == 'z') and (name in foreign_encoding_args) and (num_bufs == 0):
310 f = 't#'
311 if f != None:
312 format = format + f
313 if t != None:
314 format_args = format_args + ", &pyobj_%s" % (arg[0])
315 c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0])
316 c_convert = c_convert + \
317 " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0],
318 arg[1], t, arg[0]);
319 else:
320 format_args = format_args + ", &%s" % (arg[0])
321 if f == 't#':
322 format_args = format_args + ", &py_buffsize%d" % num_bufs
323 c_args = c_args + " int py_buffsize%d;\n" % num_bufs
324 num_bufs = num_bufs + 1
325 if c_call != "":
326 c_call = c_call + ", ";
327 c_call = c_call + "%s" % (arg[0])
328 else:
329 if skipped_types.has_key(arg[1]):
330 return 0
331 if unknown_types.has_key(arg[1]):
332 lst = unknown_types[arg[1]]
333 lst.append(name)
334 else:
335 unknown_types[arg[1]] = [name]
336 return -1
337 if format != "":
338 format = format + ":%s" % (name)
340 if ret[0] == 'void':
341 if file == "python_accessor":
342 if args[1][1] == "char *":
343 c_call = "\n if (%s->%s != NULL) free(%s->%s);\n" % (
344 args[0][0], args[1][0], args[0][0], args[1][0])
345 c_call = c_call + " %s->%s = (%s)strdup((const xmlChar *)%s);\n" % (args[0][0],
346 args[1][0], args[1][1], args[1][0])
347 else:
348 c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0],
349 args[1][0])
350 else:
351 c_call = "\n %s(%s);\n" % (name, c_call);
352 ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n"
353 elif py_types.has_key(ret[0]):
354 (f, t, n, c) = py_types[ret[0]]
355 c_return = " %s c_retval;\n" % (ret[0])
356 if file == "python_accessor" and ret[2] != None:
357 c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2])
358 else:
359 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
360 ret_convert = " py_retval = libvirt_%sWrap((%s) c_retval);\n" % (n,c)
361 ret_convert = ret_convert + " return(py_retval);\n"
362 elif py_return_types.has_key(ret[0]):
363 (f, t, n, c) = py_return_types[ret[0]]
364 c_return = " %s c_retval;\n" % (ret[0])
365 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
366 ret_convert = " py_retval = libvirt_%sWrap((%s) c_retval);\n" % (n,c)
367 ret_convert = ret_convert + " return(py_retval);\n"
368 else:
369 if skipped_types.has_key(ret[0]):
370 return 0
371 if unknown_types.has_key(ret[0]):
372 lst = unknown_types[ret[0]]
373 lst.append(name)
374 else:
375 unknown_types[ret[0]] = [name]
376 return -1
378 if cond != None and cond != "":
379 include.write("#if %s\n" % cond)
380 export.write("#if %s\n" % cond)
381 output.write("#if %s\n" % cond)
383 include.write("PyObject * ")
384 include.write("libvirt_%s(PyObject *self, PyObject *args);\n" % (name));
386 export.write(" { (char *)\"%s\", libvirt_%s, METH_VARARGS, NULL },\n" %
387 (name, name))
389 if file == "python":
390 # Those have been manually generated
391 if cond != None and cond != "":
392 include.write("#endif\n");
393 export.write("#endif\n");
394 output.write("#endif\n");
395 return 1
396 if file == "python_accessor" and ret[0] != "void" and ret[2] is None:
397 # Those have been manually generated
398 if cond != None and cond != "":
399 include.write("#endif\n");
400 export.write("#endif\n");
401 output.write("#endif\n");
402 return 1
404 output.write("PyObject *\n")
405 output.write("libvirt_%s(PyObject *self ATTRIBUTE_UNUSED," % (name))
406 output.write(" PyObject *args")
407 if format == "":
408 output.write(" ATTRIBUTE_UNUSED")
409 output.write(") {\n")
410 if ret[0] != 'void':
411 output.write(" PyObject *py_retval;\n")
412 if c_return != "":
413 output.write(c_return)
414 if c_args != "":
415 output.write(c_args)
416 if format != "":
417 output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" %
418 (format, format_args))
419 output.write(" return(NULL);\n")
420 if c_convert != "":
421 output.write(c_convert)
423 output.write(c_call)
424 output.write(ret_convert)
425 output.write("}\n\n")
426 if cond != None and cond != "":
427 include.write("#endif /* %s */\n" % cond)
428 export.write("#endif /* %s */\n" % cond)
429 output.write("#endif /* %s */\n" % cond)
430 return 1
432 def buildStubs():
433 global py_types
434 global py_return_types
435 global unknown_types
437 try:
438 f = open(os.path.join(srcPref,"libvirt-api.xml"))
439 data = f.read()
440 (parser, target) = getparser()
441 parser.feed(data)
442 parser.close()
443 except IOError, msg:
444 try:
445 f = open(os.path.join(srcPref,"..","docs","libvirt-api.xml"))
446 data = f.read()
447 (parser, target) = getparser()
448 parser.feed(data)
449 parser.close()
450 except IOError, msg:
451 print file, ":", msg
452 sys.exit(1)
454 n = len(functions.keys())
455 print "Found %d functions in libvirt-api.xml" % (n)
457 py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject")
458 try:
459 f = open(os.path.join(srcPref,"libvirt-python-api.xml"))
460 data = f.read()
461 (parser, target) = getparser()
462 parser.feed(data)
463 parser.close()
464 except IOError, msg:
465 print file, ":", msg
468 print "Found %d functions in libvirt-python-api.xml" % (
469 len(functions.keys()) - n)
470 nb_wrap = 0
471 failed = 0
472 skipped = 0
474 include = open("libvirt-py.h", "w")
475 include.write("/* Generated */\n\n")
476 export = open("libvirt-export.c", "w")
477 export.write("/* Generated */\n\n")
478 wrapper = open("libvirt-py.c", "w")
479 wrapper.write("/* Generated */\n\n")
480 wrapper.write("#include <Python.h>\n")
481 wrapper.write("#include <libvirt.h>\n")
482 wrapper.write("#include \"libvirt_wrap.h\"\n")
483 wrapper.write("#include \"libvirt-py.h\"\n\n")
484 for function in functions.keys():
485 ret = print_function_wrapper(function, wrapper, export, include)
486 if ret < 0:
487 failed = failed + 1
488 functions_failed.append(function)
489 del functions[function]
490 if ret == 0:
491 skipped = skipped + 1
492 functions_skipped.append(function)
493 del functions[function]
494 if ret == 1:
495 nb_wrap = nb_wrap + 1
496 include.close()
497 export.close()
498 wrapper.close()
500 print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
501 failed, skipped);
502 print "Missing type converters: "
503 for type in unknown_types.keys():
504 print "%s:%d " % (type, len(unknown_types[type])),
505 print
507 #######################################################################
509 # This part writes part of the Python front-end classes based on
510 # mapping rules between types and classes and also based on function
511 # renaming to get consistent function names at the Python level
513 #######################################################################
516 # The type automatically remapped to generated classes
518 classes_type = {
519 "virDomainPtr": ("._o", "virDomain(_obj=%s)", "virDomain"),
520 "virDomain *": ("._o", "virDomain(_obj=%s)", "virDomain"),
521 "virConnectPtr": ("._o", "virConnect(_obj=%s)", "virConnect"),
522 "virConnect *": ("._o", "virConnect(_obj=%s)", "virConnect"),
525 converter_type = {
528 primary_classes = ["virDomain", "virConnect"]
530 classes_ancestor = {
532 classes_destructors = {
533 "virDomain": "virDomainFree",
534 "virConnect": "virConnectClose",
537 functions_noexcept = {
540 reference_keepers = {
543 function_classes = {}
545 function_classes["None"] = []
547 function_post = {
548 'virDomainDestroy': "self._o = None",
551 def nameFixup(name, classe, type, file):
552 listname = classe + "List"
553 ll = len(listname)
554 l = len(classe)
555 if name[0:l] == listname:
556 func = name[l:]
557 func = string.lower(func[0:1]) + func[1:]
558 elif name[0:12] == "virDomainGet":
559 func = name[12:]
560 func = string.lower(func[0:1]) + func[1:]
561 elif name[0:9] == "virDomain":
562 func = name[9:]
563 func = string.lower(func[0:1]) + func[1:]
564 elif name[0:10] == "virConnect":
565 func = name[10:]
566 func = string.lower(func[0:1]) + func[1:]
567 elif name[0:3] == "xml":
568 func = name[3:]
569 func = string.lower(func[0:1]) + func[1:]
570 else:
571 func = name
572 if func == "iD":
573 func = "ID"
574 if func == "uUID":
575 func = "UUID"
576 if func == "oSType":
577 func = "OSType"
578 if func == "xMLDesc":
579 func = "XMLDesc"
580 return func
583 def functionCompare(info1, info2):
584 (index1, func1, name1, ret1, args1, file1) = info1
585 (index2, func2, name2, ret2, args2, file2) = info2
586 if file1 == file2:
587 if func1 < func2:
588 return -1
589 if func1 > func2:
590 return 1
591 if file1 == "python_accessor":
592 return -1
593 if file2 == "python_accessor":
594 return 1
595 if file1 < file2:
596 return -1
597 if file1 > file2:
598 return 1
599 return 0
601 def writeDoc(name, args, indent, output):
602 if functions[name][0] is None or functions[name][0] == "":
603 return
604 val = functions[name][0]
605 val = string.replace(val, "NULL", "None");
606 output.write(indent)
607 output.write('"""')
608 while len(val) > 60:
609 str = val[0:60]
610 i = string.rfind(str, " ");
611 if i < 0:
612 i = 60
613 str = val[0:i]
614 val = val[i:]
615 output.write(str)
616 output.write('\n ');
617 output.write(indent)
618 output.write(val);
619 output.write(' """\n')
621 def buildWrappers():
622 global ctypes
623 global py_types
624 global py_return_types
625 global unknown_types
626 global functions
627 global function_classes
628 global classes_type
629 global classes_list
630 global converter_type
631 global primary_classes
632 global converter_type
633 global classes_ancestor
634 global converter_type
635 global primary_classes
636 global classes_ancestor
637 global classes_destructors
638 global functions_noexcept
640 for type in classes_type.keys():
641 function_classes[classes_type[type][2]] = []
644 # Build the list of C types to look for ordered to start
645 # with primary classes
647 ctypes = []
648 classes_list = []
649 ctypes_processed = {}
650 classes_processed = {}
651 for classe in primary_classes:
652 classes_list.append(classe)
653 classes_processed[classe] = ()
654 for type in classes_type.keys():
655 tinfo = classes_type[type]
656 if tinfo[2] == classe:
657 ctypes.append(type)
658 ctypes_processed[type] = ()
659 for type in classes_type.keys():
660 if ctypes_processed.has_key(type):
661 continue
662 tinfo = classes_type[type]
663 if not classes_processed.has_key(tinfo[2]):
664 classes_list.append(tinfo[2])
665 classes_processed[tinfo[2]] = ()
667 ctypes.append(type)
668 ctypes_processed[type] = ()
670 for name in functions.keys():
671 found = 0;
672 (desc, ret, args, file, cond) = functions[name]
673 for type in ctypes:
674 classe = classes_type[type][2]
676 if name[0:3] == "vir" and len(args) >= 1 and args[0][1] == type:
677 found = 1
678 func = nameFixup(name, classe, type, file)
679 info = (0, func, name, ret, args, file)
680 function_classes[classe].append(info)
681 elif name[0:3] == "vir" and len(args) >= 2 and args[1][1] == type \
682 and file != "python_accessor":
683 found = 1
684 func = nameFixup(name, classe, type, file)
685 info = (1, func, name, ret, args, file)
686 function_classes[classe].append(info)
687 if found == 1:
688 continue
689 func = nameFixup(name, "None", file, file)
690 info = (0, func, name, ret, args, file)
691 function_classes['None'].append(info)
693 classes = open("libvirt.py", "w")
694 classes.write("""#!/usr/bin/python -u
696 # Those are the autogenerated Python bindings for libvirt.
697 # Check python/generator.py in the source distribution of libvirt
698 # to find out more about the generation process
700 """)
702 classes.write("import libvirtmod\n")
703 classes.write("import types\n\n")
705 txt = open("libvirtclass.txt", "w")
706 txt.write(" Generated Classes for libvir-python\n\n")
708 txt.write("#\n# Global functions of the module\n#\n\n")
709 if function_classes.has_key("None"):
710 flist = function_classes["None"]
711 flist.sort(functionCompare)
712 oldfile = ""
713 for info in flist:
714 (index, func, name, ret, args, file) = info
715 if file != oldfile:
716 classes.write("#\n# Functions from module %s\n#\n\n" % file)
717 txt.write("\n# functions from module %s\n" % file)
718 oldfile = file
719 classes.write("def %s(" % func)
720 txt.write("%s()\n" % func);
721 n = 0
722 for arg in args:
723 if n != 0:
724 classes.write(", ")
725 classes.write("%s" % arg[0])
726 n = n + 1
727 classes.write("):\n")
728 writeDoc(name, args, ' ', classes);
730 for arg in args:
731 if classes_type.has_key(arg[1]):
732 classes.write(" if %s is None: %s__o = None\n" %
733 (arg[0], arg[0]))
734 classes.write(" else: %s__o = %s%s\n" %
735 (arg[0], arg[0], classes_type[arg[1]][0]))
736 if ret[0] != "void":
737 classes.write(" ret = ");
738 else:
739 classes.write(" ");
740 classes.write("libvirtmod.%s(" % name)
741 n = 0
742 for arg in args:
743 if n != 0:
744 classes.write(", ");
745 classes.write("%s" % arg[0])
746 if classes_type.has_key(arg[1]):
747 classes.write("__o");
748 n = n + 1
749 classes.write(")\n");
750 if ret[0] != "void":
751 if classes_type.has_key(ret[0]):
753 # Raise an exception
755 if functions_noexcept.has_key(name):
756 classes.write(" if ret is None:return None\n");
757 classes.write(" return ");
758 classes.write(classes_type[ret[0]][1] % ("ret"));
759 classes.write("\n");
760 else:
761 classes.write(" return ret\n");
762 classes.write("\n");
764 txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
765 for classname in classes_list:
766 if classname == "None":
767 pass
768 else:
769 if classes_ancestor.has_key(classname):
770 txt.write("\n\nClass %s(%s)\n" % (classname,
771 classes_ancestor[classname]))
772 classes.write("class %s(%s):\n" % (classname,
773 classes_ancestor[classname]))
774 classes.write(" def __init__(self, _obj=None):\n")
775 if reference_keepers.has_key(classname):
776 rlist = reference_keepers[classname]
777 for ref in rlist:
778 classes.write(" self.%s = None\n" % ref[1])
779 classes.write(" self._o = _obj\n")
780 classes.write(" %s.__init__(self, _obj=_obj)\n\n" % (
781 classes_ancestor[classname]))
782 else:
783 txt.write("Class %s()\n" % (classname))
784 classes.write("class %s:\n" % (classname))
785 classes.write(" def __init__(self, _obj=None):\n")
786 if reference_keepers.has_key(classname):
787 list = reference_keepers[classname]
788 for ref in list:
789 classes.write(" self.%s = None\n" % ref[1])
790 classes.write(" if _obj != None:self._o = _obj;return\n")
791 classes.write(" self._o = None\n\n");
792 destruct=None
793 if classes_destructors.has_key(classname):
794 classes.write(" def __del__(self):\n")
795 classes.write(" if self._o != None:\n")
796 classes.write(" libvirtmod.%s(self._o)\n" %
797 classes_destructors[classname]);
798 classes.write(" self._o = None\n\n");
799 destruct=classes_destructors[classname]
800 flist = function_classes[classname]
801 flist.sort(functionCompare)
802 oldfile = ""
803 for info in flist:
804 (index, func, name, ret, args, file) = info
806 # Do not provide as method the destructors for the class
807 # to avoid double free
809 if name == destruct:
810 continue;
811 if file != oldfile:
812 if file == "python_accessor":
813 classes.write(" # accessors for %s\n" % (classname))
814 txt.write(" # accessors\n")
815 else:
816 classes.write(" #\n")
817 classes.write(" # %s functions from module %s\n" % (
818 classname, file))
819 txt.write("\n # functions from module %s\n" % file)
820 classes.write(" #\n\n")
821 oldfile = file
822 classes.write(" def %s(self" % func)
823 txt.write(" %s()\n" % func);
824 n = 0
825 for arg in args:
826 if n != index:
827 classes.write(", %s" % arg[0])
828 n = n + 1
829 classes.write("):\n")
830 writeDoc(name, args, ' ', classes);
831 n = 0
832 for arg in args:
833 if classes_type.has_key(arg[1]):
834 if n != index:
835 classes.write(" if %s is None: %s__o = None\n" %
836 (arg[0], arg[0]))
837 classes.write(" else: %s__o = %s%s\n" %
838 (arg[0], arg[0], classes_type[arg[1]][0]))
839 n = n + 1
840 if ret[0] != "void":
841 classes.write(" ret = ");
842 else:
843 classes.write(" ");
844 classes.write("libvirtmod.%s(" % name)
845 n = 0
846 for arg in args:
847 if n != 0:
848 classes.write(", ");
849 if n != index:
850 classes.write("%s" % arg[0])
851 if classes_type.has_key(arg[1]):
852 classes.write("__o");
853 else:
854 classes.write("self");
855 if classes_type.has_key(arg[1]):
856 classes.write(classes_type[arg[1]][0])
857 n = n + 1
858 classes.write(")\n");
859 if function_post.has_key(name):
860 classes.write(" %s\n" % (function_post[name]));
861 if ret[0] != "void":
862 if classes_type.has_key(ret[0]):
864 # Raise an exception
866 if functions_noexcept.has_key(name):
867 classes.write(
868 " if ret is None:return None\n");
871 # generate the returned class wrapper for the object
873 classes.write(" __tmp = ");
874 classes.write(classes_type[ret[0]][1] % ("ret"));
875 classes.write("\n");
878 # Sometime one need to keep references of the source
879 # class in the returned class object.
880 # See reference_keepers for the list
882 tclass = classes_type[ret[0]][2]
883 if reference_keepers.has_key(tclass):
884 list = reference_keepers[tclass]
885 for pref in list:
886 if pref[0] == classname:
887 classes.write(" __tmp.%s = self\n" %
888 pref[1])
890 # return the class
892 classes.write(" return __tmp\n");
893 elif converter_type.has_key(ret[0]):
895 # Raise an exception
897 if functions_noexcept.has_key(name):
898 classes.write(
899 " if ret is None:return None");
900 classes.write(" return ");
901 classes.write(converter_type[ret[0]] % ("ret"));
902 classes.write("\n");
903 else:
904 classes.write(" return ret\n");
905 classes.write("\n");
908 # Generate enum constants
910 for type,enum in enums.items():
911 classes.write("# %s\n" % type)
912 items = enum.items()
913 items.sort(lambda i1,i2: cmp(long(i1[1]),long(i2[1])))
914 for name,value in items:
915 classes.write("%s = %s\n" % (name,value))
916 classes.write("\n");
918 if len(functions_skipped) != 0:
919 txt.write("\nFunctions skipped:\n")
920 for function in functions_skipped:
921 txt.write(" %s\n" % function)
922 if len(functions_failed) != 0:
923 txt.write("\nFunctions failed:\n")
924 for function in functions_failed:
925 txt.write(" %s\n" % function)
926 txt.close()
927 classes.close()
929 buildStubs()
930 buildWrappers()