2005-12-19 19:34:11 +03:00
#!/usr/bin/python -u
#
# generate python wrappers from the XML API description
#
functions = { }
enums = { } # { enumType: { enumConstant: enumValue } }
import os
import sys
import string
2007-03-28 15:24:14 +04:00
import re
2005-12-19 19:34:11 +03:00
if __name__ == " __main__ " :
# launched as a script
srcPref = os . path . dirname ( sys . argv [ 0 ] )
else :
# imported
srcPref = os . path . dirname ( __file__ )
#######################################################################
#
# That part if purely the API acquisition phase from the
2006-02-09 20:45:11 +03:00
# libvirt API description
2005-12-19 19:34:11 +03:00
#
#######################################################################
import os
import xmllib
try :
import sgmlop
except ImportError :
sgmlop = None # accelerator not available
debug = 0
if sgmlop :
class FastParser :
""" sgmlop based XML parser. this is typically 15x faster
than SlowParser . . . """
def __init__ ( self , target ) :
# setup callbacks
self . finish_starttag = target . start
self . finish_endtag = target . end
self . handle_data = target . data
# activate parser
self . parser = sgmlop . XMLParser ( )
self . parser . register ( self )
self . feed = self . parser . feed
self . entity = {
" amp " : " & " , " gt " : " > " , " lt " : " < " ,
" apos " : " ' " , " quot " : ' " '
}
def close ( self ) :
try :
self . parser . close ( )
finally :
self . parser = self . feed = None # nuke circular reference
def handle_entityref ( self , entity ) :
# <string> entity
try :
self . handle_data ( self . entity [ entity ] )
except KeyError :
self . handle_data ( " & %s ; " % entity )
else :
FastParser = None
class SlowParser ( xmllib . XMLParser ) :
""" slow but safe standard parser, based on the XML parser in
Python ' s standard library. " " "
def __init__ ( self , target ) :
self . unknown_starttag = target . start
self . handle_data = target . data
self . unknown_endtag = target . end
xmllib . XMLParser . __init__ ( self )
def getparser ( target = None ) :
# get the fastest available parser, and attach it to an
# unmarshalling object. return both objects.
if target is None :
target = docParser ( )
if FastParser :
return FastParser ( target ) , target
return SlowParser ( target ) , target
class docParser :
def __init__ ( self ) :
self . _methodname = None
self . _data = [ ]
self . in_function = 0
def close ( self ) :
if debug :
print " close "
def getmethodname ( self ) :
return self . _methodname
def data ( self , text ) :
if debug :
print " data %s " % text
self . _data . append ( text )
def start ( self , tag , attrs ) :
if debug :
print " start %s , %s " % ( tag , attrs )
if tag == ' function ' :
self . _data = [ ]
self . in_function = 1
self . function = None
self . function_cond = None
self . function_args = [ ]
self . function_descr = None
self . function_return = None
self . function_file = None
if attrs . has_key ( ' name ' ) :
self . function = attrs [ ' name ' ]
if attrs . has_key ( ' file ' ) :
self . function_file = attrs [ ' file ' ]
elif tag == ' cond ' :
self . _data = [ ]
elif tag == ' info ' :
self . _data = [ ]
elif tag == ' arg ' :
if self . in_function == 1 :
self . function_arg_name = None
self . function_arg_type = None
self . function_arg_info = None
if attrs . has_key ( ' name ' ) :
self . function_arg_name = attrs [ ' name ' ]
2006-01-26 15:11:32 +03:00
if self . function_arg_name == ' from ' :
self . function_arg_name = ' frm '
2005-12-19 19:34:11 +03:00
if attrs . has_key ( ' type ' ) :
self . function_arg_type = attrs [ ' type ' ]
if attrs . has_key ( ' info ' ) :
self . function_arg_info = attrs [ ' info ' ]
elif tag == ' return ' :
if self . in_function == 1 :
self . function_return_type = None
self . function_return_info = None
self . function_return_field = None
if attrs . has_key ( ' type ' ) :
self . function_return_type = attrs [ ' type ' ]
if attrs . has_key ( ' info ' ) :
self . function_return_info = attrs [ ' info ' ]
if attrs . has_key ( ' field ' ) :
self . function_return_field = attrs [ ' field ' ]
elif tag == ' enum ' :
enum ( attrs [ ' type ' ] , attrs [ ' name ' ] , attrs [ ' value ' ] )
def end ( self , tag ) :
if debug :
print " end %s " % tag
if tag == ' function ' :
if self . function != None :
function ( self . function , self . function_descr ,
self . function_return , self . function_args ,
self . function_file , self . function_cond )
self . in_function = 0
elif tag == ' arg ' :
if self . in_function == 1 :
self . function_args . append ( [ self . function_arg_name ,
self . function_arg_type ,
self . function_arg_info ] )
elif tag == ' return ' :
if self . in_function == 1 :
self . function_return = [ self . function_return_type ,
self . function_return_info ,
self . function_return_field ]
elif tag == ' info ' :
str = ' '
for c in self . _data :
str = str + c
if self . in_function == 1 :
self . function_descr = str
elif tag == ' cond ' :
str = ' '
for c in self . _data :
str = str + c
if self . in_function == 1 :
self . function_cond = str
def function ( name , desc , ret , args , file , cond ) :
functions [ name ] = ( desc , ret , args , file , cond )
def enum ( type , name , value ) :
if not enums . has_key ( type ) :
enums [ type ] = { }
enums [ type ] [ name ] = value
#######################################################################
#
# Some filtering rukes to drop functions/types which should not
# be exposed as-is on the Python interface
#
#######################################################################
2006-01-31 13:24:12 +03:00
functions_failed = [ ]
2006-02-23 14:26:17 +03:00
functions_skipped = [
2006-02-24 15:26:56 +03:00
" virConnectListDomains "
2006-02-23 14:26:17 +03:00
]
2006-01-31 13:24:12 +03:00
2005-12-19 19:34:11 +03:00
skipped_modules = {
}
skipped_types = {
2008-01-21 18:55:53 +03:00
# 'int *': "usually a return type",
2005-12-19 19:34:11 +03:00
}
#######################################################################
#
# Table of remapping to/from the python type or class to the C
# counterpart.
#
#######################################################################
py_types = {
' void ' : ( None , None , None , None ) ,
' int ' : ( ' i ' , None , " int " , " int " ) ,
2006-08-04 17:36:07 +04:00
' long ' : ( ' l ' , None , " long " , " long " ) ,
2005-12-19 19:34:11 +03:00
' double ' : ( ' d ' , None , " double " , " double " ) ,
' unsigned int ' : ( ' i ' , None , " int " , " int " ) ,
2006-08-04 17:36:07 +04:00
' unsigned long ' : ( ' l ' , None , " long " , " long " ) ,
2008-01-21 18:41:15 +03:00
' unsigned long long ' : ( ' l ' , None , " longlong " , " long long " ) ,
2005-12-19 19:34:11 +03:00
' unsigned char * ' : ( ' z ' , None , " charPtr " , " char * " ) ,
' char * ' : ( ' z ' , None , " charPtr " , " char * " ) ,
' const char * ' : ( ' z ' , None , " charPtrConst " , " const char * " ) ,
' virDomainPtr ' : ( ' O ' , " virDomain " , " virDomainPtr " , " virDomainPtr " ) ,
' const virDomainPtr ' : ( ' O ' , " virDomain " , " virDomainPtr " , " virDomainPtr " ) ,
' virDomain * ' : ( ' O ' , " virDomain " , " virDomainPtr " , " virDomainPtr " ) ,
' const virDomain * ' : ( ' O ' , " virDomain " , " virDomainPtr " , " virDomainPtr " ) ,
2007-03-09 18:42:50 +03:00
' virNetworkPtr ' : ( ' O ' , " virNetwork " , " virNetworkPtr " , " virNetworkPtr " ) ,
' const virNetworkPtr ' : ( ' O ' , " virNetwork " , " virNetworkPtr " , " virNetworkPtr " ) ,
' virNetwork * ' : ( ' O ' , " virNetwork " , " virNetworkPtr " , " virNetworkPtr " ) ,
' const virNetwork * ' : ( ' O ' , " virNetwork " , " virNetworkPtr " , " virNetworkPtr " ) ,
2005-12-19 19:34:11 +03:00
' virConnectPtr ' : ( ' O ' , " virConnect " , " virConnectPtr " , " virConnectPtr " ) ,
' const virConnectPtr ' : ( ' O ' , " virConnect " , " virConnectPtr " , " virConnectPtr " ) ,
' virConnect * ' : ( ' O ' , " virConnect " , " virConnectPtr " , " virConnectPtr " ) ,
' const virConnect * ' : ( ' O ' , " virConnect " , " virConnectPtr " , " virConnectPtr " ) ,
}
py_return_types = {
}
unknown_types = { }
foreign_encoding_args = (
)
#######################################################################
#
2006-02-28 15:17:00 +03:00
# This part writes the C <-> Python stubs libvirt2-py.[ch] and
2005-12-19 19:34:11 +03:00
# the table libxml2-export.c to add when registrering the Python module
#
#######################################################################
# Class methods which are written by hand in libvir.c but the Python-level
# code is still automatically generated (so they are not in skip_function()).
skip_impl = (
2006-01-31 13:24:12 +03:00
' virConnectListDomainsID ' ,
2006-11-16 03:17:10 +03:00
' virConnectListDefinedDomains ' ,
2007-03-09 18:42:50 +03:00
' virConnectListNetworks ' ,
' virConnectListDefinedNetworks ' ,
2006-11-08 02:18:56 +03:00
' virConnGetLastError ' ,
' virGetLastError ' ,
2006-01-31 13:24:12 +03:00
' virDomainGetInfo ' ,
2006-03-29 16:46:03 +04:00
' virNodeGetInfo ' ,
2006-02-23 14:26:17 +03:00
' virDomainGetUUID ' ,
2006-02-24 15:26:56 +03:00
' virDomainLookupByUUID ' ,
2007-03-09 18:42:50 +03:00
' virNetworkGetUUID ' ,
' virNetworkLookupByUUID ' ,
2008-01-21 18:55:53 +03:00
' virDomainGetAutostart ' ,
' virNetworkGetAutostart ' ,
2007-10-01 00:52:13 +04:00
' virDomainBlockStats ' ,
' virDomainInterfaceStats ' ,
2007-12-07 11:41:01 +03:00
' virNodeGetCellsFreeMemory ' ,
2008-01-21 18:41:15 +03:00
' virDomainGetSchedulerType ' ,
' virDomainGetSchedulerParameters ' ,
' virDomainSetSchedulerParameters ' ,
' virDomainGetVcpus ' ,
' virDomainPinVcpu ' ,
2005-12-19 19:34:11 +03:00
)
2008-01-21 18:55:53 +03:00
# These are functions which the generator skips completly - no python
# or C code is generated. Generally should not be used for any more
# functions than those already listed
skip_function = (
' virConnectListDomains ' , # Python API is called virConectListDomainsID for unknown reasons
' virConnSetErrorFunc ' , # Not used in Python API XXX is this a bug ?
' virResetError ' , # Not used in Python API XXX is this a bug ?
' virConnectGetVersion ' , # Not used in Python API XXX is this a bug ?
' virGetVersion ' , # Python C code is manually written
' virSetErrorFunc ' , # Python API is called virRegisterErrorHandler for unknown reasons
' virConnCopyLastError ' , # Python API is called virConnGetLastError instead
' virCopyLastError ' , # Python API is called virGetLastError instead
' virConnectOpenAuth ' , # Python C code is manually written
' virDefaultErrorFunc ' , # Python virErrorFuncHandler impl calls this from C
)
2005-12-19 19:34:11 +03:00
def print_function_wrapper ( name , output , export , include ) :
global py_types
global unknown_types
global functions
global skipped_modules
try :
( desc , ret , args , file , cond ) = functions [ name ]
except :
print " failed to get function %s infos "
return
if skipped_modules . has_key ( file ) :
return 0
2008-01-21 18:55:53 +03:00
if name in skip_function :
2005-12-19 19:34:11 +03:00
return 0
if name in skip_impl :
# Don't delete the function entry in the caller.
return 1
c_call = " " ;
format = " "
format_args = " "
c_args = " "
c_return = " "
c_convert = " "
num_bufs = 0
for arg in args :
# This should be correct
if arg [ 1 ] [ 0 : 6 ] == " const " :
arg [ 1 ] = arg [ 1 ] [ 6 : ]
c_args = c_args + " %s %s ; \n " % ( arg [ 1 ] , arg [ 0 ] )
if py_types . has_key ( arg [ 1 ] ) :
( f , t , n , c ) = py_types [ arg [ 1 ] ]
if ( f == ' z ' ) and ( name in foreign_encoding_args ) and ( num_bufs == 0 ) :
f = ' t# '
if f != None :
format = format + f
if t != None :
format_args = format_args + " , &pyobj_ %s " % ( arg [ 0 ] )
c_args = c_args + " PyObject *pyobj_ %s ; \n " % ( arg [ 0 ] )
c_convert = c_convert + \
" %s = ( %s ) Py %s _Get(pyobj_ %s ); \n " % ( arg [ 0 ] ,
arg [ 1 ] , t , arg [ 0 ] ) ;
else :
format_args = format_args + " , & %s " % ( arg [ 0 ] )
if f == ' t# ' :
format_args = format_args + " , &py_buffsize %d " % num_bufs
c_args = c_args + " int py_buffsize %d ; \n " % num_bufs
num_bufs = num_bufs + 1
if c_call != " " :
c_call = c_call + " , " ;
c_call = c_call + " %s " % ( arg [ 0 ] )
else :
if skipped_types . has_key ( arg [ 1 ] ) :
return 0
if unknown_types . has_key ( arg [ 1 ] ) :
lst = unknown_types [ arg [ 1 ] ]
lst . append ( name )
else :
unknown_types [ arg [ 1 ] ] = [ name ]
return - 1
if format != " " :
format = format + " : %s " % ( name )
if ret [ 0 ] == ' void ' :
if file == " python_accessor " :
if args [ 1 ] [ 1 ] == " char * " :
2008-01-29 20:41:07 +03:00
c_call = " \n free( %s -> %s ); \n " % (
2005-12-19 19:34:11 +03:00
args [ 0 ] [ 0 ] , args [ 1 ] [ 0 ] , args [ 0 ] [ 0 ] , args [ 1 ] [ 0 ] )
c_call = c_call + " %s -> %s = ( %s )strdup((const xmlChar *) %s ); \n " % ( args [ 0 ] [ 0 ] ,
args [ 1 ] [ 0 ] , args [ 1 ] [ 1 ] , args [ 1 ] [ 0 ] )
else :
c_call = " \n %s -> %s = %s ; \n " % ( args [ 0 ] [ 0 ] , args [ 1 ] [ 0 ] ,
args [ 1 ] [ 0 ] )
else :
c_call = " \n %s ( %s ); \n " % ( name , c_call ) ;
ret_convert = " Py_INCREF(Py_None); \n return(Py_None); \n "
elif py_types . has_key ( ret [ 0 ] ) :
( f , t , n , c ) = py_types [ ret [ 0 ] ]
c_return = " %s c_retval; \n " % ( ret [ 0 ] )
if file == " python_accessor " and ret [ 2 ] != None :
c_call = " \n c_retval = %s -> %s ; \n " % ( args [ 0 ] [ 0 ] , ret [ 2 ] )
else :
c_call = " \n c_retval = %s ( %s ); \n " % ( name , c_call ) ;
2006-02-09 20:45:11 +03:00
ret_convert = " py_retval = libvirt_ %s Wrap(( %s ) c_retval); \n " % ( n , c )
2005-12-19 19:34:11 +03:00
ret_convert = ret_convert + " return(py_retval); \n "
elif py_return_types . has_key ( ret [ 0 ] ) :
( f , t , n , c ) = py_return_types [ ret [ 0 ] ]
c_return = " %s c_retval; \n " % ( ret [ 0 ] )
c_call = " \n c_retval = %s ( %s ); \n " % ( name , c_call ) ;
2006-02-09 20:45:11 +03:00
ret_convert = " py_retval = libvirt_ %s Wrap(( %s ) c_retval); \n " % ( n , c )
2005-12-19 19:34:11 +03:00
ret_convert = ret_convert + " return(py_retval); \n "
else :
if skipped_types . has_key ( ret [ 0 ] ) :
return 0
if unknown_types . has_key ( ret [ 0 ] ) :
lst = unknown_types [ ret [ 0 ] ]
lst . append ( name )
else :
unknown_types [ ret [ 0 ] ] = [ name ]
return - 1
if cond != None and cond != " " :
include . write ( " #if %s \n " % cond )
export . write ( " #if %s \n " % cond )
output . write ( " #if %s \n " % cond )
include . write ( " PyObject * " )
2006-02-09 20:45:11 +03:00
include . write ( " libvirt_ %s (PyObject *self, PyObject *args); \n " % ( name ) ) ;
2005-12-19 19:34:11 +03:00
2006-02-09 20:45:11 +03:00
export . write ( " { (char *) \" %s \" , libvirt_ %s , METH_VARARGS, NULL }, \n " %
2005-12-19 19:34:11 +03:00
( name , name ) )
if file == " python " :
# Those have been manually generated
if cond != None and cond != " " :
include . write ( " #endif \n " ) ;
export . write ( " #endif \n " ) ;
output . write ( " #endif \n " ) ;
return 1
if file == " python_accessor " and ret [ 0 ] != " void " and ret [ 2 ] is None :
# Those have been manually generated
if cond != None and cond != " " :
include . write ( " #endif \n " ) ;
export . write ( " #endif \n " ) ;
output . write ( " #endif \n " ) ;
return 1
output . write ( " PyObject * \n " )
2006-02-09 20:45:11 +03:00
output . write ( " libvirt_ %s (PyObject *self ATTRIBUTE_UNUSED, " % ( name ) )
2005-12-19 19:34:11 +03:00
output . write ( " PyObject *args " )
if format == " " :
output . write ( " ATTRIBUTE_UNUSED " )
output . write ( " ) { \n " )
if ret [ 0 ] != ' void ' :
output . write ( " PyObject *py_retval; \n " )
if c_return != " " :
output . write ( c_return )
if c_args != " " :
output . write ( c_args )
if format != " " :
output . write ( " \n if (!PyArg_ParseTuple(args, (char *) \" %s \" %s )) \n " %
( format , format_args ) )
output . write ( " return(NULL); \n " )
if c_convert != " " :
output . write ( c_convert )
2006-10-25 00:28:16 +04:00
output . write ( " LIBVIRT_BEGIN_ALLOW_THREADS; \n " ) ;
output . write ( c_call ) ;
output . write ( " LIBVIRT_END_ALLOW_THREADS; \n " ) ;
2005-12-19 19:34:11 +03:00
output . write ( ret_convert )
output . write ( " } \n \n " )
if cond != None and cond != " " :
include . write ( " #endif /* %s */ \n " % cond )
export . write ( " #endif /* %s */ \n " % cond )
output . write ( " #endif /* %s */ \n " % cond )
return 1
def buildStubs ( ) :
global py_types
global py_return_types
global unknown_types
try :
2006-02-09 20:45:11 +03:00
f = open ( os . path . join ( srcPref , " libvirt-api.xml " ) )
2005-12-19 19:34:11 +03:00
data = f . read ( )
( parser , target ) = getparser ( )
parser . feed ( data )
parser . close ( )
except IOError , msg :
try :
2006-02-09 20:45:11 +03:00
f = open ( os . path . join ( srcPref , " .. " , " docs " , " libvirt-api.xml " ) )
2005-12-19 19:34:11 +03:00
data = f . read ( )
( parser , target ) = getparser ( )
parser . feed ( data )
parser . close ( )
except IOError , msg :
print file , " : " , msg
sys . exit ( 1 )
n = len ( functions . keys ( ) )
2006-02-09 20:45:11 +03:00
print " Found %d functions in libvirt-api.xml " % ( n )
2005-12-19 19:34:11 +03:00
py_types [ ' pythonObject ' ] = ( ' O ' , " pythonObject " , " pythonObject " , " pythonObject " )
try :
2006-02-09 20:45:11 +03:00
f = open ( os . path . join ( srcPref , " libvirt-python-api.xml " ) )
2005-12-19 19:34:11 +03:00
data = f . read ( )
( parser , target ) = getparser ( )
parser . feed ( data )
parser . close ( )
except IOError , msg :
print file , " : " , msg
2006-02-09 20:45:11 +03:00
print " Found %d functions in libvirt-python-api.xml " % (
2005-12-19 19:34:11 +03:00
len ( functions . keys ( ) ) - n )
nb_wrap = 0
failed = 0
skipped = 0
2006-02-09 20:45:11 +03:00
include = open ( " libvirt-py.h " , " w " )
2005-12-19 19:34:11 +03:00
include . write ( " /* Generated */ \n \n " )
2006-02-09 20:45:11 +03:00
export = open ( " libvirt-export.c " , " w " )
2005-12-19 19:34:11 +03:00
export . write ( " /* Generated */ \n \n " )
2006-02-09 20:45:11 +03:00
wrapper = open ( " libvirt-py.c " , " w " )
2005-12-19 19:34:11 +03:00
wrapper . write ( " /* Generated */ \n \n " )
wrapper . write ( " #include <Python.h> \n " )
2006-06-26 19:02:18 +04:00
wrapper . write ( " #include <libvirt/libvirt.h> \n " )
2006-02-09 20:45:11 +03:00
wrapper . write ( " #include \" libvirt_wrap.h \" \n " )
wrapper . write ( " #include \" libvirt-py.h \" \n \n " )
2005-12-19 19:34:11 +03:00
for function in functions . keys ( ) :
ret = print_function_wrapper ( function , wrapper , export , include )
if ret < 0 :
failed = failed + 1
2006-01-31 13:24:12 +03:00
functions_failed . append ( function )
2005-12-19 19:34:11 +03:00
del functions [ function ]
if ret == 0 :
skipped = skipped + 1
2006-01-31 13:24:12 +03:00
functions_skipped . append ( function )
2005-12-19 19:34:11 +03:00
del functions [ function ]
if ret == 1 :
nb_wrap = nb_wrap + 1
include . close ( )
export . close ( )
wrapper . close ( )
2008-01-21 18:55:53 +03:00
print " Generated %d wrapper functions " % nb_wrap
2005-12-19 19:34:11 +03:00
print " Missing type converters: "
for type in unknown_types . keys ( ) :
print " %s : %d " % ( type , len ( unknown_types [ type ] ) ) ,
print
2008-01-21 18:55:53 +03:00
for f in functions_failed :
print " ERROR: failed %s " % f
if failed > 0 :
return - 1
return 0
2005-12-19 19:34:11 +03:00
#######################################################################
#
# This part writes part of the Python front-end classes based on
# mapping rules between types and classes and also based on function
# renaming to get consistent function names at the Python level
#
#######################################################################
#
# The type automatically remapped to generated classes
#
classes_type = {
2007-04-16 16:37:59 +04:00
" virDomainPtr " : ( " ._o " , " virDomain(self,_obj= %s ) " , " virDomain " ) ,
" virDomain * " : ( " ._o " , " virDomain(self, _obj= %s ) " , " virDomain " ) ,
" virNetworkPtr " : ( " ._o " , " virNetwork(self, _obj= %s ) " , " virNetwork " ) ,
" virNetwork * " : ( " ._o " , " virNetwork(self, _obj= %s ) " , " virNetwork " ) ,
2005-12-19 19:34:11 +03:00
" virConnectPtr " : ( " ._o " , " virConnect(_obj= %s ) " , " virConnect " ) ,
" virConnect * " : ( " ._o " , " virConnect(_obj= %s ) " , " virConnect " ) ,
}
converter_type = {
}
2007-03-09 18:42:50 +03:00
primary_classes = [ " virDomain " , " virNetwork " , " virConnect " ]
2005-12-19 19:34:11 +03:00
classes_ancestor = {
}
classes_destructors = {
" virDomain " : " virDomainFree " ,
2007-03-09 18:42:50 +03:00
" virNetwork " : " virNetworkFree " ,
2005-12-19 19:34:11 +03:00
" virConnect " : " virConnectClose " ,
}
functions_noexcept = {
2007-03-28 15:24:14 +04:00
' virDomainGetID ' : True ,
' virDomainGetName ' : True ,
2005-12-19 19:34:11 +03:00
}
reference_keepers = {
}
function_classes = { }
function_classes [ " None " ] = [ ]
2006-01-31 13:24:12 +03:00
function_post = {
' virDomainDestroy ' : " self._o = None " ,
2007-03-09 18:42:50 +03:00
' virNetworkDestroy ' : " self._o = None " ,
2006-01-31 13:24:12 +03:00
}
2007-03-28 15:24:14 +04:00
# Functions returning an integral type which need special rules to
# check for errors and raise exceptions.
functions_int_exception_test = {
' virDomainGetMaxMemory ' : " %s == 0 " ,
}
functions_int_default_test = " %s == -1 "
def is_integral_type ( name ) :
return not re . search ( " ^(unsigned)? ?(int|long)$ " , name ) is None
# Functions returning lists which need special rules to check for errors
# and raise exceptions.
functions_list_exception_test = {
}
functions_list_default_test = " %s is None "
def is_list_type ( name ) :
return name [ - 1 : ] == " * "
2005-12-19 19:34:11 +03:00
def nameFixup ( name , classe , type , file ) :
2007-03-15 18:23:21 +03:00
# avoid a desastrous clash
2005-12-19 19:34:11 +03:00
listname = classe + " List "
ll = len ( listname )
l = len ( classe )
if name [ 0 : l ] == listname :
func = name [ l : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
2007-03-16 13:44:44 +03:00
elif name [ 0 : 16 ] == " virNetworkDefine " :
func = name [ 3 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
2007-03-15 18:23:21 +03:00
elif name [ 0 : 16 ] == " virNetworkLookup " :
2007-03-16 13:44:44 +03:00
func = name [ 3 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
2005-12-19 19:34:11 +03:00
elif name [ 0 : 12 ] == " virDomainGet " :
func = name [ 12 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
elif name [ 0 : 9 ] == " virDomain " :
func = name [ 9 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
2007-03-09 18:42:50 +03:00
elif name [ 0 : 13 ] == " virNetworkGet " :
func = name [ 13 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
elif name [ 0 : 10 ] == " virNetwork " :
func = name [ 10 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
2006-03-29 16:46:03 +04:00
elif name [ 0 : 7 ] == " virNode " :
func = name [ 7 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
2005-12-19 19:34:11 +03:00
elif name [ 0 : 10 ] == " virConnect " :
func = name [ 10 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
elif name [ 0 : 3 ] == " xml " :
func = name [ 3 : ]
func = string . lower ( func [ 0 : 1 ] ) + func [ 1 : ]
else :
func = name
2006-01-31 13:24:12 +03:00
if func == " iD " :
func = " ID "
2006-02-23 14:26:17 +03:00
if func == " uUID " :
func = " UUID "
2007-03-09 18:42:50 +03:00
if func == " uUIDString " :
func = " UUIDString "
2006-01-31 13:24:12 +03:00
if func == " oSType " :
func = " OSType "
if func == " xMLDesc " :
func = " XMLDesc "
2005-12-19 19:34:11 +03:00
return func
def functionCompare ( info1 , info2 ) :
( index1 , func1 , name1 , ret1 , args1 , file1 ) = info1
( index2 , func2 , name2 , ret2 , args2 , file2 ) = info2
if file1 == file2 :
if func1 < func2 :
return - 1
if func1 > func2 :
return 1
if file1 == " python_accessor " :
return - 1
if file2 == " python_accessor " :
return 1
if file1 < file2 :
return - 1
if file1 > file2 :
return 1
return 0
def writeDoc ( name , args , indent , output ) :
if functions [ name ] [ 0 ] is None or functions [ name ] [ 0 ] == " " :
return
val = functions [ name ] [ 0 ]
val = string . replace ( val , " NULL " , " None " ) ;
output . write ( indent )
output . write ( ' " " " ' )
while len ( val ) > 60 :
str = val [ 0 : 60 ]
i = string . rfind ( str , " " ) ;
if i < 0 :
i = 60
str = val [ 0 : i ]
val = val [ i : ]
output . write ( str )
output . write ( ' \n ' ) ;
output . write ( indent )
output . write ( val ) ;
output . write ( ' " " " \n ' )
def buildWrappers ( ) :
global ctypes
global py_types
global py_return_types
global unknown_types
global functions
global function_classes
global classes_type
global classes_list
global converter_type
global primary_classes
global converter_type
global classes_ancestor
global converter_type
global primary_classes
global classes_ancestor
global classes_destructors
global functions_noexcept
for type in classes_type . keys ( ) :
function_classes [ classes_type [ type ] [ 2 ] ] = [ ]
#
# Build the list of C types to look for ordered to start
# with primary classes
#
ctypes = [ ]
classes_list = [ ]
ctypes_processed = { }
classes_processed = { }
for classe in primary_classes :
classes_list . append ( classe )
classes_processed [ classe ] = ( )
for type in classes_type . keys ( ) :
tinfo = classes_type [ type ]
if tinfo [ 2 ] == classe :
ctypes . append ( type )
ctypes_processed [ type ] = ( )
for type in classes_type . keys ( ) :
if ctypes_processed . has_key ( type ) :
continue
tinfo = classes_type [ type ]
if not classes_processed . has_key ( tinfo [ 2 ] ) :
classes_list . append ( tinfo [ 2 ] )
classes_processed [ tinfo [ 2 ] ] = ( )
ctypes . append ( type )
ctypes_processed [ type ] = ( )
for name in functions . keys ( ) :
found = 0 ;
( desc , ret , args , file , cond ) = functions [ name ]
for type in ctypes :
classe = classes_type [ type ] [ 2 ]
if name [ 0 : 3 ] == " vir " and len ( args ) > = 1 and args [ 0 ] [ 1 ] == type :
found = 1
func = nameFixup ( name , classe , type , file )
info = ( 0 , func , name , ret , args , file )
function_classes [ classe ] . append ( info )
elif name [ 0 : 3 ] == " vir " and len ( args ) > = 2 and args [ 1 ] [ 1 ] == type \
and file != " python_accessor " :
found = 1
func = nameFixup ( name , classe , type , file )
info = ( 1 , func , name , ret , args , file )
function_classes [ classe ] . append ( info )
if found == 1 :
continue
func = nameFixup ( name , " None " , file , file )
info = ( 0 , func , name , ret , args , file )
function_classes [ ' None ' ] . append ( info )
2006-02-28 15:17:00 +03:00
classes = open ( " libvirtclass.py " , " w " )
2005-12-19 19:34:11 +03:00
2006-02-09 20:45:11 +03:00
txt = open ( " libvirtclass.txt " , " w " )
2005-12-19 19:34:11 +03:00
txt . write ( " Generated Classes for libvir-python \n \n " )
txt . write ( " # \n # Global functions of the module \n # \n \n " )
if function_classes . has_key ( " None " ) :
flist = function_classes [ " None " ]
flist . sort ( functionCompare )
oldfile = " "
for info in flist :
( index , func , name , ret , args , file ) = info
if file != oldfile :
classes . write ( " # \n # Functions from module %s \n # \n \n " % file )
txt . write ( " \n # functions from module %s \n " % file )
oldfile = file
classes . write ( " def %s ( " % func )
txt . write ( " %s () \n " % func ) ;
n = 0
for arg in args :
if n != 0 :
classes . write ( " , " )
classes . write ( " %s " % arg [ 0 ] )
n = n + 1
classes . write ( " ): \n " )
writeDoc ( name , args , ' ' , classes ) ;
for arg in args :
if classes_type . has_key ( arg [ 1 ] ) :
classes . write ( " if %s is None: %s __o = None \n " %
( arg [ 0 ] , arg [ 0 ] ) )
classes . write ( " else: %s __o = %s %s \n " %
( arg [ 0 ] , arg [ 0 ] , classes_type [ arg [ 1 ] ] [ 0 ] ) )
if ret [ 0 ] != " void " :
classes . write ( " ret = " ) ;
else :
classes . write ( " " ) ;
2006-02-09 20:45:11 +03:00
classes . write ( " libvirtmod. %s ( " % name )
2005-12-19 19:34:11 +03:00
n = 0
for arg in args :
if n != 0 :
classes . write ( " , " ) ;
classes . write ( " %s " % arg [ 0 ] )
if classes_type . has_key ( arg [ 1 ] ) :
classes . write ( " __o " ) ;
n = n + 1
classes . write ( " ) \n " ) ;
2007-03-28 15:24:14 +04:00
if ret [ 0 ] != " void " :
2005-12-19 19:34:11 +03:00
if classes_type . has_key ( ret [ 0 ] ) :
#
# Raise an exception
#
if functions_noexcept . has_key ( name ) :
2006-02-28 15:17:00 +03:00
classes . write ( " if ret is None:return None \n " ) ;
else :
classes . write (
" if ret is None:raise libvirtError( ' %s () failed ' ) \n " %
( name ) )
2005-12-19 19:34:11 +03:00
classes . write ( " return " ) ;
classes . write ( classes_type [ ret [ 0 ] ] [ 1 ] % ( " ret " ) ) ;
classes . write ( " \n " ) ;
2007-03-28 15:24:14 +04:00
# For functions returning an integral type there are
# several things that we can do, depending on the
# contents of functions_int_*:
elif is_integral_type ( ret [ 0 ] ) :
if not functions_noexcept . has_key ( name ) :
if functions_int_exception_test . has_key ( name ) :
test = functions_int_exception_test [ name ]
else :
test = functions_int_default_test
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' ) \n " ) %
( " ret " , name ) )
classes . write ( " return ret \n " )
elif is_list_type ( ret [ 0 ] ) :
if not functions_noexcept . has_key ( name ) :
if functions_list_exception_test . has_key ( name ) :
test = functions_list_exception_test [ name ]
else :
test = functions_list_default_test
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' ) \n " ) %
( " ret " , name ) )
classes . write ( " return ret \n " )
2005-12-19 19:34:11 +03:00
else :
2007-03-28 15:24:14 +04:00
classes . write ( " return ret \n " )
2005-12-19 19:34:11 +03:00
classes . write ( " \n " ) ;
txt . write ( " \n \n # \n # Set of classes of the module \n # \n \n " )
for classname in classes_list :
if classname == " None " :
pass
else :
if classes_ancestor . has_key ( classname ) :
txt . write ( " \n \n Class %s ( %s ) \n " % ( classname ,
classes_ancestor [ classname ] ) )
classes . write ( " class %s ( %s ): \n " % ( classname ,
classes_ancestor [ classname ] ) )
classes . write ( " def __init__(self, _obj=None): \n " )
if reference_keepers . has_key ( classname ) :
rlist = reference_keepers [ classname ]
for ref in rlist :
classes . write ( " self. %s = None \n " % ref [ 1 ] )
classes . write ( " self._o = _obj \n " )
classes . write ( " %s .__init__(self, _obj=_obj) \n \n " % (
classes_ancestor [ classname ] ) )
else :
txt . write ( " Class %s () \n " % ( classname ) )
classes . write ( " class %s : \n " % ( classname ) )
2007-04-16 16:37:59 +04:00
if classname == " virDomain " or classname == " virNetwork " :
classes . write ( " def __init__(self, conn, _obj=None): \n " )
else :
classes . write ( " def __init__(self, _obj=None): \n " )
2005-12-19 19:34:11 +03:00
if reference_keepers . has_key ( classname ) :
list = reference_keepers [ classname ]
for ref in list :
classes . write ( " self. %s = None \n " % ref [ 1 ] )
2007-04-16 16:37:59 +04:00
if classname == " virDomain " or classname == " virNetwork " :
classes . write ( " self._conn = conn \n " )
2005-12-19 19:34:11 +03:00
classes . write ( " if _obj != None:self._o = _obj;return \n " )
classes . write ( " self._o = None \n \n " ) ;
destruct = None
if classes_destructors . has_key ( classname ) :
classes . write ( " def __del__(self): \n " )
classes . write ( " if self._o != None: \n " )
2006-02-09 20:45:11 +03:00
classes . write ( " libvirtmod. %s (self._o) \n " %
2005-12-19 19:34:11 +03:00
classes_destructors [ classname ] ) ;
classes . write ( " self._o = None \n \n " ) ;
destruct = classes_destructors [ classname ]
flist = function_classes [ classname ]
flist . sort ( functionCompare )
oldfile = " "
for info in flist :
( index , func , name , ret , args , file ) = info
#
# Do not provide as method the destructors for the class
# to avoid double free
#
if name == destruct :
continue ;
if file != oldfile :
if file == " python_accessor " :
classes . write ( " # accessors for %s \n " % ( classname ) )
txt . write ( " # accessors \n " )
else :
classes . write ( " # \n " )
classes . write ( " # %s functions from module %s \n " % (
classname , file ) )
txt . write ( " \n # functions from module %s \n " % file )
classes . write ( " # \n \n " )
oldfile = file
classes . write ( " def %s (self " % func )
txt . write ( " %s () \n " % func ) ;
n = 0
for arg in args :
if n != index :
classes . write ( " , %s " % arg [ 0 ] )
n = n + 1
classes . write ( " ): \n " )
writeDoc ( name , args , ' ' , classes ) ;
n = 0
for arg in args :
if classes_type . has_key ( arg [ 1 ] ) :
if n != index :
classes . write ( " if %s is None: %s __o = None \n " %
( arg [ 0 ] , arg [ 0 ] ) )
classes . write ( " else: %s __o = %s %s \n " %
( arg [ 0 ] , arg [ 0 ] , classes_type [ arg [ 1 ] ] [ 0 ] ) )
n = n + 1
if ret [ 0 ] != " void " :
classes . write ( " ret = " ) ;
else :
classes . write ( " " ) ;
2006-02-09 20:45:11 +03:00
classes . write ( " libvirtmod. %s ( " % name )
2005-12-19 19:34:11 +03:00
n = 0
for arg in args :
if n != 0 :
classes . write ( " , " ) ;
if n != index :
classes . write ( " %s " % arg [ 0 ] )
if classes_type . has_key ( arg [ 1 ] ) :
classes . write ( " __o " ) ;
else :
classes . write ( " self " ) ;
if classes_type . has_key ( arg [ 1 ] ) :
classes . write ( classes_type [ arg [ 1 ] ] [ 0 ] )
n = n + 1
classes . write ( " ) \n " ) ;
2007-03-28 15:24:14 +04:00
# For functions returning object types:
if ret [ 0 ] != " void " :
2005-12-19 19:34:11 +03:00
if classes_type . has_key ( ret [ 0 ] ) :
#
# Raise an exception
#
if functions_noexcept . has_key ( name ) :
classes . write (
" if ret is None:return None \n " ) ;
2006-02-28 15:17:00 +03:00
else :
2006-11-08 02:18:56 +03:00
if classname == " virConnect " :
classes . write (
" if ret is None:raise libvirtError( ' %s () failed ' , conn=self) \n " %
( name ) )
2007-04-16 16:37:59 +04:00
elif classname == " virDomain " :
classes . write (
" if ret is None:raise libvirtError( ' %s () failed ' , dom=self) \n " %
( name ) )
elif classname == " virNetwork " :
classes . write (
" if ret is None:raise libvirtError( ' %s () failed ' , net=self) \n " %
( name ) )
2006-11-08 02:18:56 +03:00
else :
classes . write (
2006-02-28 15:17:00 +03:00
" if ret is None:raise libvirtError( ' %s () failed ' ) \n " %
2006-11-08 02:18:56 +03:00
( name ) )
2005-12-19 19:34:11 +03:00
#
# generate the returned class wrapper for the object
#
classes . write ( " __tmp = " ) ;
classes . write ( classes_type [ ret [ 0 ] ] [ 1 ] % ( " ret " ) ) ;
classes . write ( " \n " ) ;
#
# Sometime one need to keep references of the source
# class in the returned class object.
# See reference_keepers for the list
#
tclass = classes_type [ ret [ 0 ] ] [ 2 ]
if reference_keepers . has_key ( tclass ) :
list = reference_keepers [ tclass ]
for pref in list :
if pref [ 0 ] == classname :
classes . write ( " __tmp. %s = self \n " %
pref [ 1 ] )
2007-03-28 15:24:14 +04:00
# Post-processing - just before we return.
if function_post . has_key ( name ) :
classes . write ( " %s \n " %
( function_post [ name ] ) ) ;
2005-12-19 19:34:11 +03:00
#
# return the class
#
classes . write ( " return __tmp \n " ) ;
elif converter_type . has_key ( ret [ 0 ] ) :
#
# Raise an exception
#
if functions_noexcept . has_key ( name ) :
classes . write (
" if ret is None:return None " ) ;
2007-03-28 15:24:14 +04:00
# Post-processing - just before we return.
if function_post . has_key ( name ) :
classes . write ( " %s \n " %
( function_post [ name ] ) ) ;
2005-12-19 19:34:11 +03:00
classes . write ( " return " ) ;
classes . write ( converter_type [ ret [ 0 ] ] % ( " ret " ) ) ;
classes . write ( " \n " ) ;
2007-03-28 15:24:14 +04:00
# For functions returning an integral type there
# are several things that we can do, depending on
# the contents of functions_int_*:
elif is_integral_type ( ret [ 0 ] ) :
if not functions_noexcept . has_key ( name ) :
if functions_int_exception_test . has_key ( name ) :
test = functions_int_exception_test [ name ]
else :
test = functions_int_default_test
if classname == " virConnect " :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' , conn=self) \n " ) %
( " ret " , name ) )
2007-04-16 16:37:59 +04:00
elif classname == " virDomain " :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' , dom=self) \n " ) %
( " ret " , name ) )
elif classname == " virNetwork " :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' , net=self) \n " ) %
( " ret " , name ) )
2007-03-28 15:24:14 +04:00
else :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' ) \n " ) %
( " ret " , name ) )
# Post-processing - just before we return.
if function_post . has_key ( name ) :
classes . write ( " %s \n " %
( function_post [ name ] ) ) ;
classes . write ( " return ret \n " )
elif is_list_type ( ret [ 0 ] ) :
if not functions_noexcept . has_key ( name ) :
if functions_list_exception_test . has_key ( name ) :
test = functions_list_exception_test [ name ]
else :
test = functions_list_default_test
if classname == " virConnect " :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' , conn=self) \n " ) %
( " ret " , name ) )
2007-04-16 16:37:59 +04:00
elif classname == " virDomain " :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' , dom=self) \n " ) %
( " ret " , name ) )
elif classname == " virNetwork " :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' , net=self) \n " ) %
( " ret " , name ) )
2007-03-28 15:24:14 +04:00
else :
classes . write ( ( " if " + test +
" : raise libvirtError ( ' %s () failed ' ) \n " ) %
( " ret " , name ) )
# Post-processing - just before we return.
if function_post . has_key ( name ) :
classes . write ( " %s \n " %
( function_post [ name ] ) ) ;
classes . write ( " return ret \n " )
2005-12-19 19:34:11 +03:00
else :
2007-03-28 15:24:14 +04:00
# Post-processing - just before we return.
if function_post . has_key ( name ) :
classes . write ( " %s \n " %
( function_post [ name ] ) ) ;
2005-12-19 19:34:11 +03:00
classes . write ( " return ret \n " ) ;
2007-03-28 15:24:14 +04:00
2005-12-19 19:34:11 +03:00
classes . write ( " \n " ) ;
#
# Generate enum constants
#
for type , enum in enums . items ( ) :
classes . write ( " # %s \n " % type )
items = enum . items ( )
items . sort ( lambda i1 , i2 : cmp ( long ( i1 [ 1 ] ) , long ( i2 [ 1 ] ) ) )
for name , value in items :
classes . write ( " %s = %s \n " % ( name , value ) )
classes . write ( " \n " ) ;
2006-01-31 13:24:12 +03:00
if len ( functions_skipped ) != 0 :
txt . write ( " \n Functions skipped: \n " )
for function in functions_skipped :
txt . write ( " %s \n " % function )
if len ( functions_failed ) != 0 :
txt . write ( " \n Functions failed: \n " )
for function in functions_failed :
txt . write ( " %s \n " % function )
2005-12-19 19:34:11 +03:00
txt . close ( )
classes . close ( )
2008-01-21 18:55:53 +03:00
if buildStubs ( ) < 0 :
sys . exit ( 1 )
2005-12-19 19:34:11 +03:00
buildWrappers ( )
2008-01-21 18:55:53 +03:00
sys . exit ( 0 )