python: Add a newline after custom classes
[libvirt-python/ericb.git] / generator.py
blob21b413772bc1eac2eb725670f4affcfc073a89ee
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
12 import re
14 if __name__ == "__main__":
15 # launched as a script
16 srcPref = os.path.dirname(sys.argv[0])
17 else:
18 # imported
19 srcPref = os.path.dirname(__file__)
21 #######################################################################
23 # That part if purely the API acquisition phase from the
24 # libvirt API description
26 #######################################################################
27 import os
28 import xml.sax
30 debug = 0
32 def getparser():
33 # Attach parser to an unmarshalling object. return both objects.
34 target = docParser()
35 parser = xml.sax.make_parser()
36 parser.setContentHandler(target)
37 return parser, target
39 class docParser(xml.sax.handler.ContentHandler):
40 def __init__(self):
41 self._methodname = None
42 self._data = []
43 self.in_function = 0
45 self.startElement = self.start
46 self.endElement = self.end
47 self.characters = self.data
49 def close(self):
50 if debug:
51 print "close"
53 def getmethodname(self):
54 return self._methodname
56 def data(self, text):
57 if debug:
58 print "data %s" % text
59 self._data.append(text)
61 def cdata(self, text):
62 if debug:
63 print "data %s" % text
64 self._data.append(text)
66 def start(self, tag, attrs):
67 if debug:
68 print "start %s, %s" % (tag, attrs)
69 if tag == 'function':
70 self._data = []
71 self.in_function = 1
72 self.function = None
73 self.function_cond = None
74 self.function_args = []
75 self.function_descr = None
76 self.function_return = None
77 self.function_file = None
78 if attrs.has_key('name'):
79 self.function = attrs['name']
80 if attrs.has_key('file'):
81 self.function_file = attrs['file']
82 elif tag == 'cond':
83 self._data = []
84 elif tag == 'info':
85 self._data = []
86 elif tag == 'arg':
87 if self.in_function == 1:
88 self.function_arg_name = None
89 self.function_arg_type = None
90 self.function_arg_info = None
91 if attrs.has_key('name'):
92 self.function_arg_name = attrs['name']
93 if self.function_arg_name == 'from':
94 self.function_arg_name = 'frm'
95 if attrs.has_key('type'):
96 self.function_arg_type = attrs['type']
97 if attrs.has_key('info'):
98 self.function_arg_info = attrs['info']
99 elif tag == 'return':
100 if self.in_function == 1:
101 self.function_return_type = None
102 self.function_return_info = None
103 self.function_return_field = None
104 if attrs.has_key('type'):
105 self.function_return_type = attrs['type']
106 if attrs.has_key('info'):
107 self.function_return_info = attrs['info']
108 if attrs.has_key('field'):
109 self.function_return_field = attrs['field']
110 elif tag == 'enum':
111 enum(attrs['type'],attrs['name'],attrs['value'])
113 def end(self, tag):
114 if debug:
115 print "end %s" % tag
116 if tag == 'function':
117 if self.function != None:
118 function(self.function, self.function_descr,
119 self.function_return, self.function_args,
120 self.function_file, self.function_cond)
121 self.in_function = 0
122 elif tag == 'arg':
123 if self.in_function == 1:
124 self.function_args.append([self.function_arg_name,
125 self.function_arg_type,
126 self.function_arg_info])
127 elif tag == 'return':
128 if self.in_function == 1:
129 self.function_return = [self.function_return_type,
130 self.function_return_info,
131 self.function_return_field]
132 elif tag == 'info':
133 str = ''
134 for c in self._data:
135 str = str + c
136 if self.in_function == 1:
137 self.function_descr = str
138 elif tag == 'cond':
139 str = ''
140 for c in self._data:
141 str = str + c
142 if self.in_function == 1:
143 self.function_cond = str
146 def function(name, desc, ret, args, file, cond):
147 functions[name] = (desc, ret, args, file, cond)
149 def enum(type, name, value):
150 if not enums.has_key(type):
151 enums[type] = {}
152 enums[type][name] = value
154 #######################################################################
156 # Some filtering rukes to drop functions/types which should not
157 # be exposed as-is on the Python interface
159 #######################################################################
161 functions_failed = []
162 functions_skipped = [
163 "virConnectListDomains"
166 skipped_modules = {
169 skipped_types = {
170 # 'int *': "usually a return type",
171 'virConnectDomainEventCallback': "No function types in python",
172 'virEventAddHandleFunc': "No function types in python",
175 #######################################################################
177 # Table of remapping to/from the python type or class to the C
178 # counterpart.
180 #######################################################################
182 py_types = {
183 'void': (None, None, None, None),
184 'int': ('i', None, "int", "int"),
185 'long': ('l', None, "long", "long"),
186 'double': ('d', None, "double", "double"),
187 'unsigned int': ('i', None, "int", "int"),
188 'unsigned long': ('l', None, "long", "long"),
189 'unsigned long long': ('l', None, "longlong", "long long"),
190 'unsigned char *': ('z', None, "charPtr", "char *"),
191 'char *': ('z', None, "charPtr", "char *"),
192 'const char *': ('z', None, "charPtrConst", "const char *"),
194 'virDomainPtr': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
195 'const virDomainPtr': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
196 'virDomain *': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
197 'const virDomain *': ('O', "virDomain", "virDomainPtr", "virDomainPtr"),
199 'virNetworkPtr': ('O', "virNetwork", "virNetworkPtr", "virNetworkPtr"),
200 'const virNetworkPtr': ('O', "virNetwork", "virNetworkPtr", "virNetworkPtr"),
201 'virNetwork *': ('O', "virNetwork", "virNetworkPtr", "virNetworkPtr"),
202 'const virNetwork *': ('O', "virNetwork", "virNetworkPtr", "virNetworkPtr"),
204 'virInterfacePtr': ('O', "virInterface", "virInterfacePtr", "virInterfacePtr"),
205 'const virInterfacePtr': ('O', "virInterface", "virInterfacePtr", "virInterfacePtr"),
206 'virInterface *': ('O', "virInterface", "virInterfacePtr", "virInterfacePtr"),
207 'const virInterface *': ('O', "virInterface", "virInterfacePtr", "virInterfacePtr"),
209 'virStoragePoolPtr': ('O', "virStoragePool", "virStoragePoolPtr", "virStoragePoolPtr"),
210 'const virStoragePoolPtr': ('O', "virStoragePool", "virStoragePoolPtr", "virStoragePoolPtr"),
211 'virStoragePool *': ('O', "virStoragePool", "virStoragePoolPtr", "virStoragePoolPtr"),
212 'const virStoragePool *': ('O', "virStoragePool", "virStoragePoolPtr", "virStoragePoolPtr"),
214 'virStorageVolPtr': ('O', "virStorageVol", "virStorageVolPtr", "virStorageVolPtr"),
215 'const virStorageVolPtr': ('O', "virStorageVol", "virStorageVolPtr", "virStorageVolPtr"),
216 'virStorageVol *': ('O', "virStorageVol", "virStorageVolPtr", "virStorageVolPtr"),
217 'const virStorageVol *': ('O', "virStorageVol", "virStorageVolPtr", "virStorageVolPtr"),
219 'virConnectPtr': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
220 'const virConnectPtr': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
221 'virConnect *': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
222 'const virConnect *': ('O', "virConnect", "virConnectPtr", "virConnectPtr"),
224 'virNodeDevicePtr': ('O', "virNodeDevice", "virNodeDevicePtr", "virNodeDevicePtr"),
225 'const virNodeDevicePtr': ('O', "virNodeDevice", "virNodeDevicePtr", "virNodeDevicePtr"),
226 'virNodeDevice *': ('O', "virNodeDevice", "virNodeDevicePtr", "virNodeDevicePtr"),
227 'const virNodeDevice *': ('O', "virNodeDevice", "virNodeDevicePtr", "virNodeDevicePtr"),
229 'virSecretPtr': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
230 'const virSecretPtr': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
231 'virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
232 'const virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
234 'virStreamPtr': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
235 'const virStreamPtr': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
236 'virStream *': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
237 'const virStream *': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
240 py_return_types = {
243 unknown_types = {}
245 foreign_encoding_args = (
248 #######################################################################
250 # This part writes the C <-> Python stubs libvirt.[ch] and
251 # the table libvirt-export.c to add when registrering the Python module
253 #######################################################################
255 # Class methods which are written by hand in libvir.c but the Python-level
256 # code is still automatically generated (so they are not in skip_function()).
257 skip_impl = (
258 'virConnectListDomainsID',
259 'virConnectListDefinedDomains',
260 'virConnectListNetworks',
261 'virConnectListDefinedNetworks',
262 'virConnectListInterfaces',
263 'virConnectListDefinedInterfaces',
264 'virConnectListSecrets',
265 'virConnectListStoragePools',
266 'virConnectListDefinedStoragePools',
267 'virConnectListStorageVols',
268 'virConnectListDefinedStorageVols',
269 'virConnGetLastError',
270 'virGetLastError',
271 'virDomainGetInfo',
272 'virNodeGetInfo',
273 'virDomainGetUUID',
274 'virDomainGetUUIDString',
275 'virDomainLookupByUUID',
276 'virNetworkGetUUID',
277 'virNetworkGetUUIDString',
278 'virNetworkLookupByUUID',
279 'virDomainGetAutostart',
280 'virNetworkGetAutostart',
281 'virDomainBlockStats',
282 'virDomainInterfaceStats',
283 'virNodeGetCellsFreeMemory',
284 'virDomainGetSchedulerType',
285 'virDomainGetSchedulerParameters',
286 'virDomainSetSchedulerParameters',
287 'virDomainGetVcpus',
288 'virDomainPinVcpu',
289 'virSecretGetValue',
290 'virSecretSetValue',
291 'virSecretGetUUID',
292 'virSecretGetUUIDString',
293 'virSecretLookupByUUID',
294 'virStreamRecv',
295 'virStreamSend',
296 'virStoragePoolGetUUID',
297 'virStoragePoolGetUUIDString',
298 'virStoragePoolLookupByUUID',
299 'virStoragePoolGetInfo',
300 'virStorageVolGetInfo',
301 'virStoragePoolGetAutostart',
302 'virStoragePoolListVolumes',
303 'virDomainBlockPeek',
304 'virDomainMemoryPeek',
305 'virEventRegisterImpl',
306 'virNodeListDevices',
307 'virNodeDeviceListCaps',
311 # These are functions which the generator skips completly - no python
312 # or C code is generated. Generally should not be used for any more
313 # functions than those already listed
314 skip_function = (
315 'virConnectListDomains', # Python API is called virConectListDomainsID for unknown reasons
316 'virConnSetErrorFunc', # Not used in Python API XXX is this a bug ?
317 'virResetError', # Not used in Python API XXX is this a bug ?
318 'virConnectGetVersion', # Not used in Python API XXX is this a bug ?
319 'virGetVersion', # Python C code is manually written
320 'virSetErrorFunc', # Python API is called virRegisterErrorHandler for unknown reasons
321 'virConnCopyLastError', # Python API is called virConnGetLastError instead
322 'virCopyLastError', # Python API is called virGetLastError instead
323 'virConnectOpenAuth', # Python C code is manually written
324 'virDefaultErrorFunc', # Python virErrorFuncHandler impl calls this from C
325 'virDomainGetSecurityLabel', # Needs investigation...
326 'virNodeGetSecurityModel', # Needs investigation...
327 'virConnectDomainEventRegister', # overridden in virConnect.py
328 'virConnectDomainEventDeregister', # overridden in virConnect.py
329 'virSaveLastError', # We have our own python error wrapper
330 'virFreeError', # Only needed if we use virSaveLastError
331 'virStreamEventAddCallback',
332 'virStreamRecvAll',
333 'virStreamSendAll',
334 'virStreamRef',
335 'virStreamFree',
337 # These have no use for bindings users.
338 "virConnectRef",
339 "virDomainRef",
340 "virInterfaceRef",
341 "virNetworkRef",
342 "virNodeDeviceRef",
343 "virSecretRef",
344 "virStoragePoolRef",
345 "virStorageVolRef",
347 # This functions shouldn't be called via the bindings (and even the docs
348 # contain an explicit warning to that effect). The equivalent should be
349 # implemented in pure python for each class
350 "virDomainGetConnect",
351 "virInterfaceGetConnect",
352 "virNetworkGetConnect",
353 "virSecretGetConnect",
354 "virStoragePoolGetConnect",
355 "virStorageVolGetConnect",
359 def print_function_wrapper(name, output, export, include):
360 global py_types
361 global unknown_types
362 global functions
363 global skipped_modules
365 try:
366 (desc, ret, args, file, cond) = functions[name]
367 except:
368 print "failed to get function %s infos"
369 return
371 if skipped_modules.has_key(file):
372 return 0
373 if name in skip_function:
374 return 0
375 if name in skip_impl:
376 # Don't delete the function entry in the caller.
377 return 1
379 c_call = "";
380 format=""
381 format_args=""
382 c_args=""
383 c_return=""
384 c_convert=""
385 num_bufs=0
386 for arg in args:
387 # This should be correct
388 if arg[1][0:6] == "const ":
389 arg[1] = arg[1][6:]
390 c_args = c_args + " %s %s;\n" % (arg[1], arg[0])
391 if py_types.has_key(arg[1]):
392 (f, t, n, c) = py_types[arg[1]]
393 if (f == 'z') and (name in foreign_encoding_args) and (num_bufs == 0):
394 f = 't#'
395 if f != None:
396 format = format + f
397 if t != None:
398 format_args = format_args + ", &pyobj_%s" % (arg[0])
399 c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0])
400 c_convert = c_convert + \
401 " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0],
402 arg[1], t, arg[0]);
403 else:
404 format_args = format_args + ", &%s" % (arg[0])
405 if f == 't#':
406 format_args = format_args + ", &py_buffsize%d" % num_bufs
407 c_args = c_args + " int py_buffsize%d;\n" % num_bufs
408 num_bufs = num_bufs + 1
409 if c_call != "":
410 c_call = c_call + ", ";
411 c_call = c_call + "%s" % (arg[0])
412 else:
413 if skipped_types.has_key(arg[1]):
414 return 0
415 if unknown_types.has_key(arg[1]):
416 lst = unknown_types[arg[1]]
417 lst.append(name)
418 else:
419 unknown_types[arg[1]] = [name]
420 return -1
421 if format != "":
422 format = format + ":%s" % (name)
424 if ret[0] == 'void':
425 if file == "python_accessor":
426 if args[1][1] == "char *":
427 c_call = "\n free(%s->%s);\n" % (
428 args[0][0], args[1][0], args[0][0], args[1][0])
429 c_call = c_call + " %s->%s = (%s)strdup((const xmlChar *)%s);\n" % (args[0][0],
430 args[1][0], args[1][1], args[1][0])
431 else:
432 c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0],
433 args[1][0])
434 else:
435 c_call = "\n %s(%s);\n" % (name, c_call);
436 ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n"
437 elif py_types.has_key(ret[0]):
438 (f, t, n, c) = py_types[ret[0]]
439 c_return = " %s c_retval;\n" % (ret[0])
440 if file == "python_accessor" and ret[2] != None:
441 c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2])
442 else:
443 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
444 ret_convert = " py_retval = libvirt_%sWrap((%s) c_retval);\n" % (n,c)
445 ret_convert = ret_convert + " return(py_retval);\n"
446 elif py_return_types.has_key(ret[0]):
447 (f, t, n, c) = py_return_types[ret[0]]
448 c_return = " %s c_retval;\n" % (ret[0])
449 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
450 ret_convert = " py_retval = libvirt_%sWrap((%s) c_retval);\n" % (n,c)
451 ret_convert = ret_convert + " return(py_retval);\n"
452 else:
453 if skipped_types.has_key(ret[0]):
454 return 0
455 if unknown_types.has_key(ret[0]):
456 lst = unknown_types[ret[0]]
457 lst.append(name)
458 else:
459 unknown_types[ret[0]] = [name]
460 return -1
462 if cond != None and cond != "":
463 include.write("#if %s\n" % cond)
464 export.write("#if %s\n" % cond)
465 output.write("#if %s\n" % cond)
467 include.write("PyObject * ")
468 include.write("libvirt_%s(PyObject *self, PyObject *args);\n" % (name));
470 export.write(" { (char *)\"%s\", libvirt_%s, METH_VARARGS, NULL },\n" %
471 (name, name))
473 if file == "python":
474 # Those have been manually generated
475 if cond != None and cond != "":
476 include.write("#endif\n");
477 export.write("#endif\n");
478 output.write("#endif\n");
479 return 1
480 if file == "python_accessor" and ret[0] != "void" and ret[2] is None:
481 # Those have been manually generated
482 if cond != None and cond != "":
483 include.write("#endif\n");
484 export.write("#endif\n");
485 output.write("#endif\n");
486 return 1
488 output.write("PyObject *\n")
489 output.write("libvirt_%s(PyObject *self ATTRIBUTE_UNUSED," % (name))
490 output.write(" PyObject *args")
491 if format == "":
492 output.write(" ATTRIBUTE_UNUSED")
493 output.write(") {\n")
494 if ret[0] != 'void':
495 output.write(" PyObject *py_retval;\n")
496 if c_return != "":
497 output.write(c_return)
498 if c_args != "":
499 output.write(c_args)
500 if format != "":
501 output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" %
502 (format, format_args))
503 output.write(" return(NULL);\n")
504 if c_convert != "":
505 output.write(c_convert)
507 output.write("LIBVIRT_BEGIN_ALLOW_THREADS;\n");
508 output.write(c_call);
509 output.write("LIBVIRT_END_ALLOW_THREADS;\n");
510 output.write(ret_convert)
511 output.write("}\n\n")
512 if cond != None and cond != "":
513 include.write("#endif /* %s */\n" % cond)
514 export.write("#endif /* %s */\n" % cond)
515 output.write("#endif /* %s */\n" % cond)
516 return 1
518 def buildStubs():
519 global py_types
520 global py_return_types
521 global unknown_types
523 try:
524 f = open(os.path.join(srcPref,"libvirt-api.xml"))
525 data = f.read()
526 (parser, target) = getparser()
527 parser.feed(data)
528 parser.close()
529 except IOError, msg:
530 try:
531 f = open(os.path.join(srcPref,"..","docs","libvirt-api.xml"))
532 data = f.read()
533 (parser, target) = getparser()
534 parser.feed(data)
535 parser.close()
536 except IOError, msg:
537 print file, ":", msg
538 sys.exit(1)
540 n = len(functions.keys())
541 print "Found %d functions in libvirt-api.xml" % (n)
543 py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject")
544 try:
545 f = open(os.path.join(srcPref,"libvirt-override-api.xml"))
546 data = f.read()
547 (parser, target) = getparser()
548 parser.feed(data)
549 parser.close()
550 except IOError, msg:
551 print file, ":", msg
554 print "Found %d functions in libvirt-override-api.xml" % (
555 len(functions.keys()) - n)
556 nb_wrap = 0
557 failed = 0
558 skipped = 0
560 include = open("libvirt.h", "w")
561 include.write("/* Generated */\n\n")
562 export = open("libvirt-export.c", "w")
563 export.write("/* Generated */\n\n")
564 wrapper = open("libvirt.c", "w")
565 wrapper.write("/* Generated */\n\n")
566 wrapper.write("#include <Python.h>\n")
567 wrapper.write("#include <libvirt/libvirt.h>\n")
568 wrapper.write("#include \"typewrappers.h\"\n")
569 wrapper.write("#include \"libvirt.h\"\n\n")
570 for function in functions.keys():
571 ret = print_function_wrapper(function, wrapper, export, include)
572 if ret < 0:
573 failed = failed + 1
574 functions_failed.append(function)
575 del functions[function]
576 if ret == 0:
577 skipped = skipped + 1
578 functions_skipped.append(function)
579 del functions[function]
580 if ret == 1:
581 nb_wrap = nb_wrap + 1
582 include.close()
583 export.close()
584 wrapper.close()
586 print "Generated %d wrapper functions" % nb_wrap
588 print "Missing type converters: "
589 for type in unknown_types.keys():
590 print "%s:%d " % (type, len(unknown_types[type])),
591 print
593 for f in functions_failed:
594 print "ERROR: failed %s" % f
596 if failed > 0:
597 return -1
598 return 0
600 #######################################################################
602 # This part writes part of the Python front-end classes based on
603 # mapping rules between types and classes and also based on function
604 # renaming to get consistent function names at the Python level
606 #######################################################################
609 # The type automatically remapped to generated classes
611 classes_type = {
612 "virDomainPtr": ("._o", "virDomain(self,_obj=%s)", "virDomain"),
613 "virDomain *": ("._o", "virDomain(self, _obj=%s)", "virDomain"),
614 "virNetworkPtr": ("._o", "virNetwork(self, _obj=%s)", "virNetwork"),
615 "virNetwork *": ("._o", "virNetwork(self, _obj=%s)", "virNetwork"),
616 "virInterfacePtr": ("._o", "virInterface(self, _obj=%s)", "virInterface"),
617 "virInterface *": ("._o", "virInterface(self, _obj=%s)", "virInterface"),
618 "virStoragePoolPtr": ("._o", "virStoragePool(self, _obj=%s)", "virStoragePool"),
619 "virStoragePool *": ("._o", "virStoragePool(self, _obj=%s)", "virStoragePool"),
620 "virStorageVolPtr": ("._o", "virStorageVol(self, _obj=%s)", "virStorageVol"),
621 "virStorageVol *": ("._o", "virStorageVol(self, _obj=%s)", "virStorageVol"),
622 "virNodeDevicePtr": ("._o", "virNodeDevice(self, _obj=%s)", "virNodeDevice"),
623 "virNodeDevice *": ("._o", "virNodeDevice(self, _obj=%s)", "virNodeDevice"),
624 "virSecretPtr": ("._o", "virSecret(self, _obj=%s)", "virSecret"),
625 "virSecret *": ("._o", "virSecret(self, _obj=%s)", "virSecret"),
626 "virStreamPtr": ("._o", "virStream(self, _obj=%s)", "virStream"),
627 "virStream *": ("._o", "virStream(self, _obj=%s)", "virStream"),
628 "virConnectPtr": ("._o", "virConnect(_obj=%s)", "virConnect"),
629 "virConnect *": ("._o", "virConnect(_obj=%s)", "virConnect"),
632 converter_type = {
635 primary_classes = ["virDomain", "virNetwork", "virInterface",
636 "virStoragePool", "virStorageVol",
637 "virConnect", "virNodeDevice", "virSecret",
638 "virStream"]
640 classes_ancestor = {
642 classes_destructors = {
643 "virDomain": "virDomainFree",
644 "virNetwork": "virNetworkFree",
645 "virInterface": "virInterfaceFree",
646 "virStoragePool": "virStoragePoolFree",
647 "virStorageVol": "virStorageVolFree",
648 "virNodeDevice" : "virNodeDeviceFree",
649 "virSecret": "virSecretFree",
650 # We hand-craft __del__ for this one
651 #"virStream": "virStreamFree",
654 class_skip_connect_impl = {
655 "virConnect" : True
659 functions_noexcept = {
660 'virDomainGetID': True,
661 'virDomainGetName': True,
662 'virNetworkGetName': True,
663 'virInterfaceGetName': True,
664 'virStoragePoolGetName': True,
665 'virStorageVolGetName': True,
666 'virStorageVolGetkey': True,
667 'virNodeDeviceGetName': True,
668 'virNodeDeviceGetParent': True,
669 'virSecretGetUsageType': True,
670 'virSecretGetUsageID': True,
673 reference_keepers = {
676 function_classes = {}
678 function_classes["None"] = []
680 function_post = {}
682 # Functions returning an integral type which need special rules to
683 # check for errors and raise exceptions.
684 functions_int_exception_test = {
685 'virDomainGetMaxMemory': "%s == 0",
687 functions_int_default_test = "%s == -1"
689 def is_integral_type (name):
690 return not re.search ("^(unsigned)? ?(int|long)$", name) is None
692 # Functions returning lists which need special rules to check for errors
693 # and raise exceptions.
694 functions_list_exception_test = {
696 functions_list_default_test = "%s is None"
698 def is_list_type (name):
699 whitelist = [ "virDomainBlockStats",
700 "virDomainInterfaceStats" ]
702 return name[-1:] == "*" or name in whitelist
704 def nameFixup(name, classe, type, file):
705 # avoid a desastrous clash
706 listname = classe + "List"
707 ll = len(listname)
708 l = len(classe)
709 if name[0:l] == listname:
710 func = name[l:]
711 func = string.lower(func[0:1]) + func[1:]
712 elif name[0:16] == "virNetworkDefine":
713 func = name[3:]
714 func = string.lower(func[0:1]) + func[1:]
715 elif name[0:19] == "virNetworkCreateXML":
716 func = name[3:]
717 func = string.lower(func[0:1]) + func[1:]
718 elif name[0:16] == "virNetworkLookup":
719 func = name[3:]
720 func = string.lower(func[0:1]) + func[1:]
721 elif name[0:18] == "virInterfaceDefine":
722 func = name[3:]
723 func = string.lower(func[0:1]) + func[1:]
724 elif name[0:21] == "virInterfaceCreateXML":
725 func = name[3:]
726 func = string.lower(func[0:1]) + func[1:]
727 elif name[0:18] == "virInterfaceLookup":
728 func = name[3:]
729 func = string.lower(func[0:1]) + func[1:]
730 elif name[0:15] == "virSecretDefine":
731 func = name[3:]
732 func = string.lower(func[0:1]) + func[1:]
733 elif name[0:15] == "virSecretLookup":
734 func = name[3:]
735 func = string.lower(func[0:1]) + func[1:]
736 elif name[0:20] == "virStoragePoolDefine":
737 func = name[3:]
738 func = string.lower(func[0:1]) + func[1:]
739 elif name[0:23] == "virStoragePoolCreateXML":
740 func = name[3:]
741 func = string.lower(func[0:1]) + func[1:]
742 elif name[0:20] == "virStoragePoolLookup":
743 func = name[3:]
744 func = string.lower(func[0:1]) + func[1:]
745 elif name[0:19] == "virStorageVolDefine":
746 func = name[3:]
747 func = string.lower(func[0:1]) + func[1:]
748 elif name[0:19] == "virStorageVolLookup":
749 func = name[3:]
750 func = string.lower(func[0:1]) + func[1:]
751 elif name[0:12] == "virDomainGet":
752 func = name[12:]
753 func = string.lower(func[0:1]) + func[1:]
754 elif name[0:9] == "virDomain":
755 func = name[9:]
756 func = string.lower(func[0:1]) + func[1:]
757 elif name[0:13] == "virNetworkGet":
758 func = name[13:]
759 func = string.lower(func[0:1]) + func[1:]
760 elif name[0:10] == "virNetwork":
761 func = name[10:]
762 func = string.lower(func[0:1]) + func[1:]
763 elif name[0:15] == "virInterfaceGet":
764 func = name[15:]
765 func = string.lower(func[0:1]) + func[1:]
766 elif name[0:12] == "virInterface":
767 func = name[12:]
768 func = string.lower(func[0:1]) + func[1:]
769 elif name[0:12] == 'virSecretGet':
770 func = name[12:]
771 func = string.lower(func[0:1]) + func[1:]
772 elif name[0:9] == 'virSecret':
773 func = name[9:]
774 func = string.lower(func[0:1]) + func[1:]
775 elif name[0:12] == 'virStreamNew':
776 func = "newStream"
777 elif name[0:9] == 'virStream':
778 func = name[9:]
779 func = string.lower(func[0:1]) + func[1:]
780 elif name[0:17] == "virStoragePoolGet":
781 func = name[17:]
782 func = string.lower(func[0:1]) + func[1:]
783 elif name[0:14] == "virStoragePool":
784 func = name[14:]
785 func = string.lower(func[0:1]) + func[1:]
786 elif name[0:16] == "virStorageVolGet":
787 func = name[16:]
788 func = string.lower(func[0:1]) + func[1:]
789 elif name[0:13] == "virStorageVol":
790 func = name[13:]
791 func = string.lower(func[0:1]) + func[1:]
792 elif name[0:13] == "virNodeDevice":
793 if name[13:16] == "Get":
794 func = string.lower(name[16]) + name[17:]
795 elif name[13:19] == "Lookup" or name[13:19] == "Create":
796 func = string.lower(name[3]) + name[4:]
797 else:
798 func = string.lower(name[13]) + name[14:]
799 elif name[0:7] == "virNode":
800 func = name[7:]
801 func = string.lower(func[0:1]) + func[1:]
802 elif name[0:10] == "virConnect":
803 func = name[10:]
804 func = string.lower(func[0:1]) + func[1:]
805 elif name[0:3] == "xml":
806 func = name[3:]
807 func = string.lower(func[0:1]) + func[1:]
808 else:
809 func = name
810 if func == "iD":
811 func = "ID"
812 if func == "uUID":
813 func = "UUID"
814 if func == "uUIDString":
815 func = "UUIDString"
816 if func == "oSType":
817 func = "OSType"
818 if func == "xMLDesc":
819 func = "XMLDesc"
820 if func == "mACString":
821 func = "MACString"
823 return func
826 def functionCompare(info1, info2):
827 (index1, func1, name1, ret1, args1, file1) = info1
828 (index2, func2, name2, ret2, args2, file2) = info2
829 if file1 == file2:
830 if func1 < func2:
831 return -1
832 if func1 > func2:
833 return 1
834 if file1 == "python_accessor":
835 return -1
836 if file2 == "python_accessor":
837 return 1
838 if file1 < file2:
839 return -1
840 if file1 > file2:
841 return 1
842 return 0
844 def writeDoc(name, args, indent, output):
845 if functions[name][0] is None or functions[name][0] == "":
846 return
847 val = functions[name][0]
848 val = string.replace(val, "NULL", "None");
849 output.write(indent)
850 output.write('"""')
851 i = string.find(val, "\n")
852 while i >= 0:
853 str = val[0:i+1]
854 val = val[i+1:]
855 output.write(str)
856 i = string.find(val, "\n")
857 output.write(indent)
858 output.write(val)
859 output.write(' """\n')
861 def buildWrappers():
862 global ctypes
863 global py_types
864 global py_return_types
865 global unknown_types
866 global functions
867 global function_classes
868 global classes_type
869 global classes_list
870 global converter_type
871 global primary_classes
872 global converter_type
873 global classes_ancestor
874 global converter_type
875 global primary_classes
876 global classes_ancestor
877 global classes_destructors
878 global functions_noexcept
880 for type in classes_type.keys():
881 function_classes[classes_type[type][2]] = []
884 # Build the list of C types to look for ordered to start
885 # with primary classes
887 ctypes = []
888 classes_list = []
889 ctypes_processed = {}
890 classes_processed = {}
891 for classe in primary_classes:
892 classes_list.append(classe)
893 classes_processed[classe] = ()
894 for type in classes_type.keys():
895 tinfo = classes_type[type]
896 if tinfo[2] == classe:
897 ctypes.append(type)
898 ctypes_processed[type] = ()
899 for type in classes_type.keys():
900 if ctypes_processed.has_key(type):
901 continue
902 tinfo = classes_type[type]
903 if not classes_processed.has_key(tinfo[2]):
904 classes_list.append(tinfo[2])
905 classes_processed[tinfo[2]] = ()
907 ctypes.append(type)
908 ctypes_processed[type] = ()
910 for name in functions.keys():
911 found = 0;
912 (desc, ret, args, file, cond) = functions[name]
913 for type in ctypes:
914 classe = classes_type[type][2]
916 if name[0:3] == "vir" and len(args) >= 1 and args[0][1] == type:
917 found = 1
918 func = nameFixup(name, classe, type, file)
919 info = (0, func, name, ret, args, file)
920 function_classes[classe].append(info)
921 elif name[0:3] == "vir" and len(args) >= 2 and args[1][1] == type \
922 and file != "python_accessor":
923 found = 1
924 func = nameFixup(name, classe, type, file)
925 info = (1, func, name, ret, args, file)
926 function_classes[classe].append(info)
927 if found == 1:
928 continue
929 func = nameFixup(name, "None", file, file)
930 info = (0, func, name, ret, args, file)
931 function_classes['None'].append(info)
933 classes = open("libvirt.py", "w")
935 extra = open(os.path.join(srcPref,"libvirt-override.py"), "r")
936 classes.write("#!/usr/bin/python -i\n")
937 classes.write("#\n")
938 classes.write("# WARNING WARNING WARNING WARNING\n")
939 classes.write("#\n")
940 classes.write("# This file is automatically written by generator.py. Any changes\n")
941 classes.write("# made here will be lost.\n")
942 classes.write("#\n")
943 classes.write("# To change the manually written methods edit libvirt-override.py\n")
944 classes.write("# To change the automatically written methods edit generator.py\n")
945 classes.write("#\n")
946 classes.write("# WARNING WARNING WARNING WARNING\n")
947 classes.write("#\n")
948 classes.writelines(extra.readlines())
949 classes.write("#\n")
950 classes.write("# WARNING WARNING WARNING WARNING\n")
951 classes.write("#\n")
952 classes.write("# Automatically written part of python bindings for libvirt\n")
953 classes.write("#\n")
954 classes.write("# WARNING WARNING WARNING WARNING\n")
955 extra.close()
957 if function_classes.has_key("None"):
958 flist = function_classes["None"]
959 flist.sort(functionCompare)
960 oldfile = ""
961 for info in flist:
962 (index, func, name, ret, args, file) = info
963 if file != oldfile:
964 classes.write("#\n# Functions from module %s\n#\n\n" % file)
965 oldfile = file
966 classes.write("def %s(" % func)
967 n = 0
968 for arg in args:
969 if n != 0:
970 classes.write(", ")
971 classes.write("%s" % arg[0])
972 n = n + 1
973 classes.write("):\n")
974 writeDoc(name, args, ' ', classes);
976 for arg in args:
977 if classes_type.has_key(arg[1]):
978 classes.write(" if %s is None: %s__o = None\n" %
979 (arg[0], arg[0]))
980 classes.write(" else: %s__o = %s%s\n" %
981 (arg[0], arg[0], classes_type[arg[1]][0]))
982 if ret[0] != "void":
983 classes.write(" ret = ");
984 else:
985 classes.write(" ");
986 classes.write("libvirtmod.%s(" % name)
987 n = 0
988 for arg in args:
989 if n != 0:
990 classes.write(", ");
991 classes.write("%s" % arg[0])
992 if classes_type.has_key(arg[1]):
993 classes.write("__o");
994 n = n + 1
995 classes.write(")\n");
997 if ret[0] != "void":
998 if classes_type.has_key(ret[0]):
1000 # Raise an exception
1002 if functions_noexcept.has_key(name):
1003 classes.write(" if ret is None:return None\n");
1004 else:
1005 classes.write(
1006 " if ret is None:raise libvirtError('%s() failed')\n" %
1007 (name))
1009 classes.write(" return ");
1010 classes.write(classes_type[ret[0]][1] % ("ret"));
1011 classes.write("\n");
1013 # For functions returning an integral type there are
1014 # several things that we can do, depending on the
1015 # contents of functions_int_*:
1016 elif is_integral_type (ret[0]):
1017 if not functions_noexcept.has_key (name):
1018 if functions_int_exception_test.has_key (name):
1019 test = functions_int_exception_test[name]
1020 else:
1021 test = functions_int_default_test
1022 classes.write ((" if " + test +
1023 ": raise libvirtError ('%s() failed')\n") %
1024 ("ret", name))
1025 classes.write(" return ret\n")
1027 elif is_list_type (ret[0]):
1028 if not functions_noexcept.has_key (name):
1029 if functions_list_exception_test.has_key (name):
1030 test = functions_list_exception_test[name]
1031 else:
1032 test = functions_list_default_test
1033 classes.write ((" if " + test +
1034 ": raise libvirtError ('%s() failed')\n") %
1035 ("ret", name))
1036 classes.write(" return ret\n")
1038 else:
1039 classes.write(" return ret\n")
1041 classes.write("\n");
1043 for classname in classes_list:
1044 if classname == "None":
1045 pass
1046 else:
1047 if classes_ancestor.has_key(classname):
1048 classes.write("class %s(%s):\n" % (classname,
1049 classes_ancestor[classname]))
1050 classes.write(" def __init__(self, _obj=None):\n")
1051 if reference_keepers.has_key(classname):
1052 rlist = reference_keepers[classname]
1053 for ref in rlist:
1054 classes.write(" self.%s = None\n" % ref[1])
1055 classes.write(" self._o = _obj\n")
1056 classes.write(" %s.__init__(self, _obj=_obj)\n\n" % (
1057 classes_ancestor[classname]))
1058 else:
1059 classes.write("class %s:\n" % (classname))
1060 if classname in [ "virDomain", "virNetwork", "virInterface", "virStoragePool",
1061 "virStorageVol", "virNodeDevice", "virSecret","virStream" ]:
1062 classes.write(" def __init__(self, conn, _obj=None):\n")
1063 else:
1064 classes.write(" def __init__(self, _obj=None):\n")
1065 if reference_keepers.has_key(classname):
1066 list = reference_keepers[classname]
1067 for ref in list:
1068 classes.write(" self.%s = None\n" % ref[1])
1069 if classname in [ "virDomain", "virNetwork", "virInterface",
1070 "virNodeDevice", "virSecret", "virStream" ]:
1071 classes.write(" self._conn = conn\n")
1072 elif classname in [ "virStorageVol", "virStoragePool" ]:
1073 classes.write(" self._conn = conn\n" + \
1074 " if not isinstance(conn, virConnect):\n" + \
1075 " self._conn = conn._conn\n")
1076 classes.write(" if _obj != None:self._o = _obj;return\n")
1077 classes.write(" self._o = None\n\n");
1078 destruct=None
1079 if classes_destructors.has_key(classname):
1080 classes.write(" def __del__(self):\n")
1081 classes.write(" if self._o != None:\n")
1082 classes.write(" libvirtmod.%s(self._o)\n" %
1083 classes_destructors[classname]);
1084 classes.write(" self._o = None\n\n");
1085 destruct=classes_destructors[classname]
1087 if not class_skip_connect_impl.has_key(classname):
1088 # Build python safe 'connect' method
1089 classes.write(" def connect(self):\n")
1090 classes.write(" return self._conn\n\n")
1092 flist = function_classes[classname]
1093 flist.sort(functionCompare)
1094 oldfile = ""
1095 for info in flist:
1096 (index, func, name, ret, args, file) = info
1098 # Do not provide as method the destructors for the class
1099 # to avoid double free
1101 if name == destruct:
1102 continue;
1103 if file != oldfile:
1104 if file == "python_accessor":
1105 classes.write(" # accessors for %s\n" % (classname))
1106 else:
1107 classes.write(" #\n")
1108 classes.write(" # %s functions from module %s\n" % (
1109 classname, file))
1110 classes.write(" #\n\n")
1111 oldfile = file
1112 classes.write(" def %s(self" % func)
1113 n = 0
1114 for arg in args:
1115 if n != index:
1116 classes.write(", %s" % arg[0])
1117 n = n + 1
1118 classes.write("):\n")
1119 writeDoc(name, args, ' ', classes);
1120 n = 0
1121 for arg in args:
1122 if classes_type.has_key(arg[1]):
1123 if n != index:
1124 classes.write(" if %s is None: %s__o = None\n" %
1125 (arg[0], arg[0]))
1126 classes.write(" else: %s__o = %s%s\n" %
1127 (arg[0], arg[0], classes_type[arg[1]][0]))
1128 n = n + 1
1129 if ret[0] != "void":
1130 classes.write(" ret = ");
1131 else:
1132 classes.write(" ");
1133 classes.write("libvirtmod.%s(" % name)
1134 n = 0
1135 for arg in args:
1136 if n != 0:
1137 classes.write(", ");
1138 if n != index:
1139 classes.write("%s" % arg[0])
1140 if classes_type.has_key(arg[1]):
1141 classes.write("__o");
1142 else:
1143 classes.write("self");
1144 if classes_type.has_key(arg[1]):
1145 classes.write(classes_type[arg[1]][0])
1146 n = n + 1
1147 classes.write(")\n");
1149 if name == "virConnectClose":
1150 classes.write(" self._o = None\n")
1152 # For functions returning object types:
1153 if ret[0] != "void":
1154 if classes_type.has_key(ret[0]):
1156 # Raise an exception
1158 if functions_noexcept.has_key(name):
1159 classes.write(
1160 " if ret is None:return None\n");
1161 else:
1162 if classname == "virConnect":
1163 classes.write(
1164 " if ret is None:raise libvirtError('%s() failed', conn=self)\n" %
1165 (name))
1166 elif classname == "virDomain":
1167 classes.write(
1168 " if ret is None:raise libvirtError('%s() failed', dom=self)\n" %
1169 (name))
1170 elif classname == "virNetwork":
1171 classes.write(
1172 " if ret is None:raise libvirtError('%s() failed', net=self)\n" %
1173 (name))
1174 elif classname == "virInterface":
1175 classes.write(
1176 " if ret is None:raise libvirtError('%s() failed', net=self)\n" %
1177 (name))
1178 elif classname == "virStoragePool":
1179 classes.write(
1180 " if ret is None:raise libvirtError('%s() failed', pool=self)\n" %
1181 (name))
1182 elif classname == "virStorageVol":
1183 classes.write(
1184 " if ret is None:raise libvirtError('%s() failed', vol=self)\n" %
1185 (name))
1186 else:
1187 classes.write(
1188 " if ret is None:raise libvirtError('%s() failed')\n" %
1189 (name))
1192 # generate the returned class wrapper for the object
1194 classes.write(" __tmp = ");
1195 classes.write(classes_type[ret[0]][1] % ("ret"));
1196 classes.write("\n");
1199 # Sometime one need to keep references of the source
1200 # class in the returned class object.
1201 # See reference_keepers for the list
1203 tclass = classes_type[ret[0]][2]
1204 if reference_keepers.has_key(tclass):
1205 list = reference_keepers[tclass]
1206 for pref in list:
1207 if pref[0] == classname:
1208 classes.write(" __tmp.%s = self\n" %
1209 pref[1])
1211 # Post-processing - just before we return.
1212 if function_post.has_key(name):
1213 classes.write(" %s\n" %
1214 (function_post[name]));
1217 # return the class
1219 classes.write(" return __tmp\n");
1220 elif converter_type.has_key(ret[0]):
1222 # Raise an exception
1224 if functions_noexcept.has_key(name):
1225 classes.write(
1226 " if ret is None:return None");
1228 # Post-processing - just before we return.
1229 if function_post.has_key(name):
1230 classes.write(" %s\n" %
1231 (function_post[name]));
1233 classes.write(" return ");
1234 classes.write(converter_type[ret[0]] % ("ret"));
1235 classes.write("\n");
1237 # For functions returning an integral type there
1238 # are several things that we can do, depending on
1239 # the contents of functions_int_*:
1240 elif is_integral_type (ret[0]):
1241 if not functions_noexcept.has_key (name):
1242 if functions_int_exception_test.has_key (name):
1243 test = functions_int_exception_test[name]
1244 else:
1245 test = functions_int_default_test
1246 if classname == "virConnect":
1247 classes.write ((" if " + test +
1248 ": raise libvirtError ('%s() failed', conn=self)\n") %
1249 ("ret", name))
1250 elif classname == "virDomain":
1251 classes.write ((" if " + test +
1252 ": raise libvirtError ('%s() failed', dom=self)\n") %
1253 ("ret", name))
1254 elif classname == "virNetwork":
1255 classes.write ((" if " + test +
1256 ": raise libvirtError ('%s() failed', net=self)\n") %
1257 ("ret", name))
1258 elif classname == "virInterface":
1259 classes.write ((" if " + test +
1260 ": raise libvirtError ('%s() failed', net=self)\n") %
1261 ("ret", name))
1262 elif classname == "virStoragePool":
1263 classes.write ((" if " + test +
1264 ": raise libvirtError ('%s() failed', pool=self)\n") %
1265 ("ret", name))
1266 elif classname == "virStorageVol":
1267 classes.write ((" if " + test +
1268 ": raise libvirtError ('%s() failed', vol=self)\n") %
1269 ("ret", name))
1270 else:
1271 classes.write ((" if " + test +
1272 ": raise libvirtError ('%s() failed')\n") %
1273 ("ret", name))
1275 # Post-processing - just before we return.
1276 if function_post.has_key(name):
1277 classes.write(" %s\n" %
1278 (function_post[name]));
1280 classes.write (" return ret\n")
1282 elif is_list_type (ret[0]):
1283 if not functions_noexcept.has_key (name):
1284 if functions_list_exception_test.has_key (name):
1285 test = functions_list_exception_test[name]
1286 else:
1287 test = functions_list_default_test
1288 if classname == "virConnect":
1289 classes.write ((" if " + test +
1290 ": raise libvirtError ('%s() failed', conn=self)\n") %
1291 ("ret", name))
1292 elif classname == "virDomain":
1293 classes.write ((" if " + test +
1294 ": raise libvirtError ('%s() failed', dom=self)\n") %
1295 ("ret", name))
1296 elif classname == "virNetwork":
1297 classes.write ((" if " + test +
1298 ": raise libvirtError ('%s() failed', net=self)\n") %
1299 ("ret", name))
1300 elif classname == "virInterface":
1301 classes.write ((" if " + test +
1302 ": raise libvirtError ('%s() failed', net=self)\n") %
1303 ("ret", name))
1304 elif classname == "virStoragePool":
1305 classes.write ((" if " + test +
1306 ": raise libvirtError ('%s() failed', pool=self)\n") %
1307 ("ret", name))
1308 elif classname == "virStorageVol":
1309 classes.write ((" if " + test +
1310 ": raise libvirtError ('%s() failed', vol=self)\n") %
1311 ("ret", name))
1312 else:
1313 classes.write ((" if " + test +
1314 ": raise libvirtError ('%s() failed')\n") %
1315 ("ret", name))
1317 # Post-processing - just before we return.
1318 if function_post.has_key(name):
1319 classes.write(" %s\n" %
1320 (function_post[name]));
1322 classes.write (" return ret\n")
1324 else:
1325 # Post-processing - just before we return.
1326 if function_post.has_key(name):
1327 classes.write(" %s\n" %
1328 (function_post[name]));
1330 classes.write(" return ret\n");
1332 classes.write("\n");
1333 # Append "<classname>.py" to class def, iff it exists
1334 try:
1335 extra = open(os.path.join(srcPref,"libvirt-override-" + classname + ".py"), "r")
1336 classes.write (" #\n")
1337 classes.write (" # %s methods from %s.py (hand coded)\n" % (classname,classname))
1338 classes.write (" #\n")
1339 classes.writelines(extra.readlines())
1340 classes.write("\n")
1341 extra.close()
1342 except:
1343 pass
1346 # Generate enum constants
1348 for type,enum in enums.items():
1349 classes.write("# %s\n" % type)
1350 items = enum.items()
1351 items.sort(lambda i1,i2: cmp(long(i1[1]),long(i2[1])))
1352 for name,value in items:
1353 classes.write("%s = %s\n" % (name,value))
1354 classes.write("\n");
1356 classes.close()
1358 if buildStubs() < 0:
1359 sys.exit(1)
1360 buildWrappers()
1361 sys.exit(0)