gstreamer/codegen/codegen.py

1565 lines
62 KiB
Python
Raw Normal View History

import getopt
import keyword
import os
import string
import sys
import argtypes
import definitions
import defsparser
import override
import reversewrapper
class Coverage(object):
def __init__(self, name):
self.name = name
self.wrapped = 0
self.not_wrapped = 0
def declare_wrapped(self):
self.wrapped += 1
def declare_not_wrapped(self):
self.not_wrapped += 1
def printstats(self):
total = self.wrapped + self.not_wrapped
fd = sys.stderr
if total:
fd.write("***INFO*** The coverage of %s is %.2f%% (%i/%i)\n" %
(self.name,
float(self.wrapped*100)/total,
self.wrapped,
total))
else:
fd.write("***INFO*** There are no declared %s." % self.name)
functions_coverage = Coverage("global functions")
methods_coverage = Coverage("methods")
vproxies_coverage = Coverage("virtual proxies")
vaccessors_coverage = Coverage("virtual accessors")
iproxies_coverage = Coverage("interface proxies")
def exc_info():
#traceback.print_exc()
etype, value, tb = sys.exc_info()
ret = ""
try:
sval = str(value)
if etype == KeyError:
ret = "No ArgType for %s" % (sval,)
else:
ret = sval
finally:
del etype, value, tb
return ret
def fixname(name):
if keyword.iskeyword(name):
return name + '_'
return name
class FileOutput:
'''Simple wrapper for file object, that makes writing #line
statements easier.''' # "
def __init__(self, fp, filename=None):
self.fp = fp
self.lineno = 1
if filename:
self.filename = filename
else:
self.filename = self.fp.name
# handle writing to the file, and keep track of the line number ...
def write(self, str):
self.fp.write(str)
self.lineno = self.lineno + string.count(str, '\n')
def writelines(self, sequence):
for line in sequence:
self.write(line)
def close(self):
self.fp.close()
def flush(self):
self.fp.flush()
def setline(self, linenum, filename):
'''writes out a #line statement, for use by the C
preprocessor.''' # "
self.write('#line %d "%s"\n' % (linenum, filename))
def resetline(self):
'''resets line numbering to the original file'''
self.setline(self.lineno + 1, self.filename)
class Wrapper:
type_tmpl = (
'PyTypeObject Py%(typename)s_Type = {\n'
' PyObject_HEAD_INIT(NULL)\n'
' 0, /* ob_size */\n'
' "%(classname)s", /* tp_name */\n'
' sizeof(%(tp_basicsize)s), /* tp_basicsize */\n'
' 0, /* tp_itemsize */\n'
' /* methods */\n'
' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n'
' (printfunc)0, /* tp_print */\n'
' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n'
' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n'
' (cmpfunc)%(tp_compare)s, /* tp_compare */\n'
' (reprfunc)%(tp_repr)s, /* tp_repr */\n'
' (PyNumberMethods*)%(tp_as_number)s, /* tp_as_number */\n'
' (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n'
' (PyMappingMethods*)%(tp_as_mapping)s, /* tp_as_mapping */\n'
' (hashfunc)%(tp_hash)s, /* tp_hash */\n'
' (ternaryfunc)%(tp_call)s, /* tp_call */\n'
' (reprfunc)%(tp_str)s, /* tp_str */\n'
' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n'
' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n'
' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n'
' %(tp_flags)s, /* tp_flags */\n'
' %(tp_doc)s, /* Documentation string */\n'
' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n'
' (inquiry)%(tp_clear)s, /* tp_clear */\n'
' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n'
' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n'
' (getiterfunc)%(tp_iter)s, /* tp_iter */\n'
' (iternextfunc)%(tp_iternext)s, /* tp_iternext */\n'
' (struct PyMethodDef*)%(tp_methods)s, /* tp_methods */\n'
' (struct PyMemberDef*)0, /* tp_members */\n'
' (struct PyGetSetDef*)%(tp_getset)s, /* tp_getset */\n'
' NULL, /* tp_base */\n'
' NULL, /* tp_dict */\n'
' (descrgetfunc)%(tp_descr_get)s, /* tp_descr_get */\n'
' (descrsetfunc)%(tp_descr_set)s, /* tp_descr_set */\n'
' %(tp_dictoffset)s, /* tp_dictoffset */\n'
' (initproc)%(tp_init)s, /* tp_init */\n'
' (allocfunc)%(tp_alloc)s, /* tp_alloc */\n'
' (newfunc)%(tp_new)s, /* tp_new */\n'
' (freefunc)%(tp_free)s, /* tp_free */\n'
' (inquiry)%(tp_is_gc)s /* tp_is_gc */\n'
'};\n\n'
)
slots_list = [
'tp_getattr', 'tp_setattr', 'tp_getattro', 'tp_setattro',
'tp_compare', 'tp_repr',
'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash',
'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter',
'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init',
'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc',
'tp_traverse', 'tp_clear', 'tp_dealloc', 'tp_flags', 'tp_doc'
]
getter_tmpl = (
'static PyObject *\n'
'%(funcname)s(PyObject *self, void *closure)\n'
'{\n'
'%(varlist)s'
' ret = %(field)s;\n'
'%(codeafter)s\n'
'}\n\n'
)
parse_tmpl = (
' if (!PyArg_ParseTupleAndKeywords(args, kwargs,'
'"%(typecodes)s:%(name)s"%(parselist)s))\n'
' return %(errorreturn)s;\n'
)
deprecated_tmpl = (
' if (PyErr_Warn(PyExc_DeprecationWarning, '
'"%(deprecationmsg)s") < 0)\n'
' return %(errorreturn)s;\n'
)
methdef_tmpl = (
' { "%(name)s", (PyCFunction)%(cname)s, %(flags)s,\n'
' %(docstring)s },\n'
)
noconstructor = (
'static int\n'
'pygobject_no_constructor(PyObject *self, PyObject *args, '
'PyObject *kwargs)\n'
'{\n'
' gchar buf[512];\n'
'\n'
' g_snprintf(buf, sizeof(buf), "%s is an abstract widget", '
'self->ob_type->tp_name);\n'
' PyErr_SetString(PyExc_NotImplementedError, buf);\n'
' return -1;\n'
'}\n\n'
)
function_tmpl = (
'static PyObject *\n'
'_wrap_%(cname)s(PyObject *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' %(begin_allow_threads)s\n'
' %(setreturn)s%(cname)s(%(arglist)s);\n'
' %(end_allow_threads)s\n'
'%(codeafter)s\n'
'}\n\n'
)
virtual_accessor_tmpl = (
'static PyObject *\n'
'_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n'
'{\n'
' gpointer klass;\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' klass = g_type_class_ref(pyg_type_from_object(cls));\n'
' if (%(class_cast_macro)s(klass)->%(virtual)s)\n'
' %(setreturn)s%(class_cast_macro)s(klass)->'
'%(virtual)s(%(arglist)s);\n'
' else {\n'
' PyErr_SetString(PyExc_NotImplementedError, '
'"virtual method %(name)s not implemented");\n'
' g_type_class_unref(klass);\n'
' return NULL;\n'
' }\n'
' g_type_class_unref(klass);\n'
'%(codeafter)s\n'
'}\n\n'
)
# template for method calls
constructor_tmpl = None
method_tmpl = None
def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
self.parser = parser
self.objinfo = objinfo
self.overrides = overrides
self.fp = fp
def get_lower_name(self):
return string.lower(string.replace(self.objinfo.typecode,
'_TYPE_', '_', 1))
def get_field_accessor(self, fieldname):
raise NotImplementedError
def get_initial_class_substdict(self): return {}
def get_initial_constructor_substdict(self, constructor):
return { 'name': '%s.__init__' % self.objinfo.c_name,
'errorreturn': '-1' }
def get_initial_method_substdict(self, method):
substdict = { 'name': '%s.%s' % (self.objinfo.c_name, method.name) }
substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;'
substdict['end_allow_threads'] = 'pyg_end_allow_threads;'
return substdict
def write_class(self):
if self.overrides.is_type_ignored(self.objinfo.c_name):
return
self.fp.write('\n/* ----------- %s ----------- */\n\n' %
self.objinfo.c_name)
substdict = self.get_initial_class_substdict()
if not substdict.has_key('tp_flags'):
substdict['tp_flags'] = 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE'
substdict['typename'] = self.objinfo.c_name
if self.overrides.modulename:
substdict['classname'] = '%s.%s' % (self.overrides.modulename,
self.objinfo.name)
else:
substdict['classname'] = self.objinfo.name
substdict['tp_doc'] = self.objinfo.docstring
# Maybe this could be done in a nicer way, but I'll leave it as it is
# for now: -- Johan
if not self.overrides.slot_is_overriden('%s.tp_init' %
self.objinfo.c_name):
substdict['tp_init'] = self.write_constructor()
substdict['tp_methods'] = self.write_methods()
substdict['tp_getset'] = self.write_getsets()
# handle slots ...
for slot in self.slots_list:
slotname = '%s.%s' % (self.objinfo.c_name, slot)
slotfunc = '_wrap_%s_%s' % (self.get_lower_name(), slot)
if slot[:6] == 'tp_as_':
slotfunc = '&' + slotfunc
if self.overrides.slot_is_overriden(slotname):
data = self.overrides.slot_override(slotname)
self.write_function(slotname, data)
substdict[slot] = slotfunc
else:
if not substdict.has_key(slot):
substdict[slot] = '0'
self.fp.write(self.type_tmpl % substdict)
self.write_virtuals()
def write_function_wrapper(self, function_obj, template,
handle_return=0, is_method=0, kwargs_needed=0,
substdict=None):
'''This function is the guts of all functions that generate
wrappers for functions, methods and constructors.'''
if not substdict: substdict = {}
info = argtypes.WrapperInfo()
substdict.setdefault('errorreturn', 'NULL')
# for methods, we want the leading comma
if is_method:
info.arglist.append('')
if function_obj.varargs:
raise ValueError, "varargs functions not supported"
for param in function_obj.params:
if param.pdflt and '|' not in info.parsestr:
info.add_parselist('|', [], [])
handler = argtypes.matcher.get(param.ptype)
handler.write_param(param.ptype, param.pname, param.pdflt,
param.pnull, param.keeprefcount, info)
substdict['setreturn'] = ''
if handle_return:
if function_obj.ret not in ('none', None):
substdict['setreturn'] = 'ret = '
handler = argtypes.matcher.get(function_obj.ret)
handler.write_return(function_obj.ret,
function_obj.caller_owns_return, info)
if function_obj.deprecated != None:
deprecated = self.deprecated_tmpl % {
'deprecationmsg': function_obj.deprecated,
'errorreturn': substdict['errorreturn'] }
else:
deprecated = ''
# if name isn't set, set it to function_obj.name
substdict.setdefault('name', function_obj.name)
substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;'
substdict['end_allow_threads'] = 'pyg_end_allow_threads;'
if self.objinfo:
substdict['typename'] = self.objinfo.c_name
substdict.setdefault('cname', function_obj.c_name)
substdict['varlist'] = info.get_varlist()
substdict['typecodes'] = info.parsestr
substdict['parselist'] = info.get_parselist()
substdict['arglist'] = info.get_arglist()
substdict['codebefore'] = deprecated + (
string.replace(info.get_codebefore(),
'return NULL', 'return ' + substdict['errorreturn'])
)
substdict['codeafter'] = (
string.replace(info.get_codeafter(),
'return NULL',
'return ' + substdict['errorreturn']))
if info.parsestr or kwargs_needed:
substdict['parseargs'] = self.parse_tmpl % substdict
substdict['extraparams'] = ', PyObject *args, PyObject *kwargs'
flags = 'METH_VARARGS|METH_KEYWORDS'
# prepend the keyword list to the variable list
substdict['varlist'] = info.get_kwlist() + substdict['varlist']
else:
substdict['parseargs'] = ''
substdict['extraparams'] = ''
flags = 'METH_NOARGS'
return template % substdict, flags
def write_constructor(self):
initfunc = '0'
constructor = self.parser.find_constructor(self.objinfo,self.overrides)
if not constructor:
return self.write_default_constructor()
funcname = constructor.c_name
try:
if self.overrides.is_overriden(funcname):
data = self.overrides.override(funcname)
self.write_function(funcname, data)
self.objinfo.has_new_constructor_api = (
self.objinfo.typecode in
self.overrides.newstyle_constructors)
else:
# ok, a hack to determine if we should use
# new-style constructores :P
property_based = getattr(self,
'write_property_based_constructor',
None)
if property_based:
if (len(constructor.params) == 0 or
isinstance(constructor.params[0],
definitions.Property)):
# write_property_based_constructor is only
# implemented in GObjectWrapper
return self.write_property_based_constructor(
constructor)
else:
sys.stderr.write(
"Warning: generating old-style constructor for:" +
constructor.c_name + '\n')
# write constructor from template ...
code = self.write_function_wrapper(constructor,
self.constructor_tmpl,
handle_return=0, is_method=0, kwargs_needed=1,
substdict=self.get_initial_constructor_substdict(
constructor))[0]
self.fp.write(code)
initfunc = '_wrap_' + funcname
except:
sys.stderr.write('Could not write constructor for %s: %s\n'
% (self.objinfo.c_name, exc_info()))
initfunc = self.write_noconstructor()
return initfunc
def write_noconstructor(self):
# this is a hack ...
if not hasattr(self.overrides, 'no_constructor_written'):
self.fp.write(self.noconstructor)
self.overrides.no_constructor_written = 1
initfunc = 'pygobject_no_constructor'
return initfunc
def write_default_constructor(self):
return self.write_noconstructor()
def get_methflags(self, funcname):
if self.overrides.wants_kwargs(funcname):
flags = 'METH_VARARGS|METH_KEYWORDS'
elif self.overrides.wants_noargs(funcname):
flags = 'METH_NOARGS'
elif self.overrides.wants_onearg(funcname):
flags = 'METH_O'
else:
flags = 'METH_VARARGS'
if self.overrides.is_staticmethod(funcname):
flags += '|METH_STATIC'
elif self.overrides.is_classmethod(funcname):
flags += '|METH_CLASS'
return flags
def write_function(self, funcname, data):
lineno, filename = self.overrides.getstartline(funcname)
self.fp.setline(lineno, filename)
self.fp.write(data)
self.fp.resetline()
self.fp.write('\n\n')
def _get_class_virtual_substdict(self, meth, cname, parent):
substdict = self.get_initial_method_substdict(meth)
substdict['virtual'] = substdict['name'].split('.')[1]
substdict['cname'] = cname
substdict['class_cast_macro'] = parent.typecode.replace(
'_TYPE_', '_', 1) + "_CLASS"
substdict['typecode'] = self.objinfo.typecode
substdict['cast'] = string.replace(parent.typecode, '_TYPE_', '_', 1)
return substdict
def write_methods(self):
methods = []
klass = self.objinfo.c_name
# First, get methods from the defs files
for meth in self.parser.find_methods(self.objinfo):
method_name = meth.c_name
if self.overrides.is_ignored(method_name):
continue
try:
if self.overrides.is_overriden(method_name):
if not self.overrides.is_already_included(method_name):
data = self.overrides.override(method_name)
self.write_function(method_name, data)
methflags = self.get_methflags(method_name)
else:
# write constructor from template ...
code, methflags = self.write_function_wrapper(meth,
self.method_tmpl, handle_return=1, is_method=1,
substdict=self.get_initial_method_substdict(meth))
self.fp.write(code)
methods.append(self.methdef_tmpl %
{ 'name': fixname(meth.name),
'cname': '_wrap_' + method_name,
'flags': methflags,
'docstring': meth.docstring })
methods_coverage.declare_wrapped()
except:
methods_coverage.declare_not_wrapped()
sys.stderr.write('Could not write method %s.%s: %s\n'
% (klass, meth.name, exc_info()))
# Now try to see if there are any defined in the override
for method_name in self.overrides.get_defines_for(klass):
c_name = override.class2cname(klass, method_name)
if self.overrides.is_already_included(method_name):
continue
try:
data = self.overrides.define(klass, method_name)
self.write_function(method_name, data)
methflags = self.get_methflags(method_name)
methods.append(self.methdef_tmpl %
{ 'name': method_name,
'cname': '_wrap_' + c_name,
'flags': methflags,
'docstring': meth.docstring })
methods_coverage.declare_wrapped()
except:
methods_coverage.declare_not_wrapped()
sys.stderr.write('Could not write method %s.%s: %s\n'
% (klass, meth.name, exc_info()))
# Add GObject virtual method accessors, for chaining to parent
# virtuals from subclasses
methods += self.write_virtual_accessors()
if methods:
methoddefs = '_Py%s_methods' % self.objinfo.c_name
# write the PyMethodDef structure
methods.append(' { NULL, NULL, 0, NULL }\n')
self.fp.write('static const PyMethodDef %s[] = {\n' % methoddefs)
self.fp.write(string.join(methods, ''))
self.fp.write('};\n\n')
else:
methoddefs = 'NULL'
return methoddefs
def write_virtual_accessors(self):
klass = self.objinfo.c_name
methods = []
for meth in self.parser.find_virtuals(self.objinfo):
method_name = self.objinfo.c_name + "__do_" + meth.name
if self.overrides.is_ignored(method_name):
continue
try:
if self.overrides.is_overriden(method_name):
if not self.overrides.is_already_included(method_name):
data = self.overrides.override(method_name)
self.write_function(method_name, data)
methflags = self.get_methflags(method_name)
else:
# temporarily add a 'self' parameter as first argument
meth.params.insert(0, definitions.Parameter(
ptype=(self.objinfo.c_name + '*'),
pname='self', pdflt=None, pnull=None))
try:
# write method from template ...
code, methflags = self.write_function_wrapper(
meth, self.virtual_accessor_tmpl,
handle_return=True, is_method=False,
substdict=self._get_class_virtual_substdict(
meth, method_name, self.objinfo))
self.fp.write(code)
finally:
del meth.params[0]
methods.append(self.methdef_tmpl %
{ 'name': "do_" + fixname(meth.name),
'cname': '_wrap_' + method_name,
'flags': methflags + '|METH_CLASS',
'docstring': 'NULL'})
vaccessors_coverage.declare_wrapped()
except:
vaccessors_coverage.declare_not_wrapped()
sys.stderr.write(
'Could not write virtual accessor method %s.%s: %s\n'
% (klass, meth.name, exc_info()))
return methods
def write_virtuals(self):
'''
Write _wrap_FooBar__proxy_do_zbr() reverse wrapers for
GObject virtuals
'''
klass = self.objinfo.c_name
virtuals = []
for meth in self.parser.find_virtuals(self.objinfo):
method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
if self.overrides.is_ignored(method_name):
continue
try:
if self.overrides.is_overriden(method_name):
if not self.overrides.is_already_included(method_name):
data = self.overrides.override(method_name)
self.write_function(method_name, data)
else:
# write virtual proxy ...
ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
wrapper = reversewrapper.ReverseWrapper(
'_wrap_' + method_name, is_static=True)
wrapper.set_return_type(ret(wrapper, **props))
wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
wrapper, "self", method_name="do_" + meth.name,
c_type=(klass + ' *')))
for param in meth.params:
handler, props = argtypes.matcher.get_reverse(
param.ptype)
props["direction"] = param.pdir
wrapper.add_parameter(handler(wrapper,
param.pname, **props))
buf = reversewrapper.MemoryCodeSink()
wrapper.generate(buf)
self.fp.write(buf.flush())
virtuals.append((fixname(meth.name), '_wrap_' + method_name))
vproxies_coverage.declare_wrapped()
except (KeyError, ValueError):
vproxies_coverage.declare_not_wrapped()
virtuals.append((fixname(meth.name), None))
sys.stderr.write('Could not write virtual proxy %s.%s: %s\n'
% (klass, meth.name, exc_info()))
if virtuals:
# Write a 'pygtk class init' function for this object,
# except when the object type is explicitly ignored (like
# GtkPlug and GtkSocket on win32).
if self.overrides.is_ignored(self.objinfo.typecode):
return
class_cast_macro = self.objinfo.typecode.replace(
'_TYPE_', '_', 1) + "_CLASS"
cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1)
funcname = "__%s_class_init" % klass
self.objinfo.class_init_func = funcname
have_implemented_virtuals = not not [True
for name, cname in virtuals
if cname is not None]
self.fp.write(
('\nstatic int\n'
'%(funcname)s(gpointer gclass, PyTypeObject *pyclass)\n'
'{\n') % vars())
if have_implemented_virtuals:
self.fp.write(' PyObject *o;\n')
self.fp.write(
' %(klass)sClass *klass = '
'%(class_cast_macro)s(gclass);\n'
' PyObject *gsignals = '
'PyDict_GetItemString(pyclass->tp_dict, "__gsignals__");\n'
% vars())
for name, cname in virtuals:
do_name = 'do_' + name
if cname is None:
self.fp.write('\n /* overriding %(do_name)s '
'is currently not supported */\n' % vars())
else:
self.fp.write('''
o = PyObject_GetAttrString((PyObject *) pyclass, "%(do_name)s");
if (o == NULL)
PyErr_Clear();
else {
if (!PyObject_TypeCheck(o, &PyCFunction_Type)
&& !(gsignals && PyDict_GetItemString(gsignals, "%(name)s")))
klass->%(name)s = %(cname)s;
Py_DECREF(o);
}
''' % vars())
self.fp.write(' return 0;\n}\n')
def write_getsets(self):
lower_name = self.get_lower_name()
getsets_name = lower_name + '_getsets'
getterprefix = '_wrap_' + lower_name + '__get_'
setterprefix = '_wrap_' + lower_name + '__set_'
# no overrides for the whole function. If no fields,
# don't write a func
if not self.objinfo.fields:
return '0'
getsets = []
for ftype, cfname in self.objinfo.fields:
fname = cfname.replace('.', '_')
gettername = '0'
settername = '0'
attrname = self.objinfo.c_name + '.' + fname
if self.overrides.attr_is_overriden(attrname):
code = self.overrides.attr_override(attrname)
self.write_function(attrname, code)
if string.find(code, getterprefix + fname) >= 0:
gettername = getterprefix + fname
if string.find(code, setterprefix + fname) >= 0:
settername = setterprefix + fname
if gettername == '0':
try:
funcname = getterprefix + fname
info = argtypes.WrapperInfo()
handler = argtypes.matcher.get(ftype)
# for attributes, we don't own the "return value"
handler.write_return(ftype, 0, info)
self.fp.write(self.getter_tmpl %
{ 'funcname': funcname,
'varlist': info.varlist,
'field': self.get_field_accessor(cfname),
'codeafter': info.get_codeafter() })
gettername = funcname
except:
sys.stderr.write(
"Could not write getter for %s.%s: %s\n"
% (self.objinfo.c_name, fname, exc_info()))
if gettername != '0' or settername != '0':
getsets.append(' { "%s", (getter)%s, (setter)%s },\n' %
(fixname(fname), gettername, settername))
if not getsets:
return '0'
self.fp.write('static const PyGetSetDef %s[] = {\n' % getsets_name)
for getset in getsets:
self.fp.write(getset)
self.fp.write(' { NULL, (getter)0, (setter)0 },\n')
self.fp.write('};\n\n')
return getsets_name
def write_functions(self, prefix):
self.fp.write('\n/* ----------- functions ----------- */\n\n')
functions = []
# First, get methods from the defs files
for func in self.parser.find_functions():
funcname = func.c_name
if self.overrides.is_ignored(funcname):
continue
try:
if self.overrides.is_overriden(funcname):
data = self.overrides.override(funcname)
self.write_function(funcname, data)
methflags = self.get_methflags(funcname)
else:
# write constructor from template ...
code, methflags = self.write_function_wrapper(func,
self.function_tmpl, handle_return=1, is_method=0)
self.fp.write(code)
functions.append(self.methdef_tmpl %
{ 'name': func.name,
'cname': '_wrap_' + funcname,
'flags': methflags,
'docstring': func.docstring })
functions_coverage.declare_wrapped()
except:
functions_coverage.declare_not_wrapped()
sys.stderr.write('Could not write function %s: %s\n'
% (func.name, exc_info()))
# Now try to see if there are any defined in the override
for funcname in self.overrides.get_functions():
try:
data = self.overrides.function(funcname)
self.write_function(funcname, data)
methflags = self.get_methflags(funcname)
functions.append(self.methdef_tmpl %
{ 'name': funcname,
'cname': '_wrap_' + funcname,
'flags': methflags,
'docstring': 'NULL'})
functions_coverage.declare_wrapped()
except:
functions_coverage.declare_not_wrapped()
sys.stderr.write('Could not write function %s: %s\n'
% (funcname, exc_info()))
# write the PyMethodDef structure
functions.append(' { NULL, NULL, 0, NULL }\n')
self.fp.write('const PyMethodDef ' + prefix + '_functions[] = {\n')
self.fp.write(string.join(functions, ''))
self.fp.write('};\n\n')
class GObjectWrapper(Wrapper):
constructor_tmpl = (
'static int\n'
'_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' self->obj = (GObject *)%(cname)s(%(arglist)s);\n'
'%(codeafter)s\n'
' if (!self->obj) {\n'
' PyErr_SetString(PyExc_RuntimeError, '
'"could not create %(typename)s object");\n'
' return -1;\n'
' }\n'
'%(aftercreate)s'
' pygobject_register_wrapper((PyObject *)self);\n'
' return 0;\n'
'}\n\n'
)
method_tmpl = (
'static PyObject *\n'
'_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' %(begin_allow_threads)s\n'
' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n'
' %(end_allow_threads)s\n'
'%(codeafter)s\n'
'}\n\n'
)
def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
Wrapper.__init__(self, parser, objinfo, overrides, fp)
if self.objinfo:
self.castmacro = string.replace(self.objinfo.typecode,
'_TYPE_', '_', 1)
def get_initial_class_substdict(self):
return { 'tp_basicsize' : 'PyGObject',
'tp_weaklistoffset' : 'offsetof(PyGObject, weakreflist)',
'tp_dictoffset' : 'offsetof(PyGObject, inst_dict)' }
def get_field_accessor(self, fieldname):
castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1)
return '%s(pygobject_get(self))->%s' % (castmacro, fieldname)
def get_initial_constructor_substdict(self, constructor):
substdict = Wrapper.get_initial_constructor_substdict(self,
constructor)
if not constructor.caller_owns_return:
substdict['aftercreate'] = " g_object_ref(self->obj);\n"
else:
substdict['aftercreate'] = ''
return substdict
def get_initial_method_substdict(self, method):
substdict = Wrapper.get_initial_method_substdict(self, method)
substdict['cast'] = string.replace(self.objinfo.typecode,
'_TYPE_', '_', 1)
return substdict
def write_default_constructor(self):
try:
parent = self.parser.find_object(self.objinfo.parent)
except ValueError:
parent = None
if parent is not None:
## just like the constructor is inheritted, we should
# inherit the new API compatibility flag
self.objinfo.has_new_constructor_api = (
parent.has_new_constructor_api)
elif self.objinfo.parent == 'GObject':
self.objinfo.has_new_constructor_api = True
return '0'
def write_property_based_constructor(self, constructor):
self.objinfo.has_new_constructor_api = True
out = self.fp
print >> out, "static int"
print >> out, '_wrap_%s(PyGObject *self, PyObject *args,' \
' PyObject *kwargs)\n{' % constructor.c_name
if constructor.params:
s = " GType obj_type = pyg_type_from_object((PyObject *) self);"
print >> out, s
def py_str_list_to_c(arg):
if arg:
return "{" + ", ".join(
map(lambda s: '"' + s + '"', arg)) + ", NULL }"
else:
return "{ NULL }"
classname = '%s.%s' % (self.overrides.modulename,
self.objinfo.name)
if constructor.params:
mandatory_arguments = [param for param in constructor.params
if not param.optional]
optional_arguments = [param for param in constructor.params
if param.optional]
arg_names = py_str_list_to_c(
[param.argname
for param in mandatory_arguments + optional_arguments])
prop_names = py_str_list_to_c(
[param.pname
for param in mandatory_arguments + optional_arguments])
print >> out, " GParameter params[%i];" % \
len(constructor.params)
print >> out, " PyObject *parsed_args[%i] = {NULL, };" % \
len(constructor.params)
print >> out, " char *arg_names[] = %s;" % arg_names
print >> out, " char *prop_names[] = %s;" % prop_names
print >> out, " guint nparams, i;"
print >> out
if constructor.deprecated is not None:
out.write(
' if (PyErr_Warn(PyExc_DeprecationWarning, '
'"%s") < 0)\n' %
constructor.deprecated)
print >> out, ' return -1;'
print >> out
out.write(" if (!PyArg_ParseTupleAndKeywords(args, kwargs, ")
template = '"'
if mandatory_arguments:
template += "O"*len(mandatory_arguments)
if optional_arguments:
template += "|" + "O"*len(optional_arguments)
template += ':%s.__init__"' % classname
print >> out, template, ", arg_names",
for i in range(len(constructor.params)):
print >> out, ", &parsed_args[%i]" % i,
out.write(
"))\n"
" return -1;\n"
"\n"
" memset(params, 0, sizeof(GParameter)*%i);\n"
" if (!pyg_parse_constructor_args(obj_type, arg_names,\n"
" prop_names, params, \n"
" &nparams, parsed_args))\n"
" return -1;\n"
" pygobject_constructv(self, nparams, params);\n"
" for (i = 0; i < nparams; ++i)\n"
" g_value_unset(&params[i].value);\n"
% len(constructor.params))
else:
out.write(
" static char* kwlist[] = { NULL };\n"
"\n")
if constructor.deprecated is not None:
out.write(
' if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)\n'
' return -1;\n'
'\n' % constructor.deprecated)
out.write(
' if (!PyArg_ParseTupleAndKeywords(args, kwargs,\n'
' ":%s.__init__",\n'
' kwlist))\n'
' return -1;\n'
'\n'
' pygobject_constructv(self, 0, NULL);\n' % classname)
out.write(
' if (!self->obj) {\n'
' PyErr_SetString(\n'
' PyExc_RuntimeError, \n'
' "could not create %s object");\n'
' return -1;\n'
' }\n' % classname)
if not constructor.caller_owns_return:
print >> out, " g_object_ref(self->obj);\n"
out.write(
' return 0;\n'
'}\n\n')
return "_wrap_%s" % constructor.c_name
## TODO : Add GstMiniObjectWrapper(Wrapper)
class GstMiniObjectWrapper(Wrapper):
constructor_tmpl = (
'static int\n'
'_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' self->obj = (GstMiniObject *)%(cname)s(%(arglist)s);\n'
'%(codeafter)s\n'
' if (!self->obj) {\n'
' PyErr_SetString(PyExc_RuntimeError, '
'"could not create %(typename)s miniobject");\n'
' return -1;\n'
' }\n'
'%(aftercreate)s'
' pygstminiobject_register_wrapper((PyObject *)self);\n'
' return 0;\n'
'}\n\n'
)
method_tmpl = (
'static PyObject *\n'
'_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' %(begin_allow_threads)s\n'
' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n'
' %(end_allow_threads)s\n'
'%(codeafter)s\n'
'}\n\n'
)
def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
Wrapper.__init__(self, parser, objinfo, overrides, fp)
if self.objinfo:
self.castmacro = string.replace(self.objinfo.typecode,
'_TYPE_', '_', 1)
def get_initial_class_substdict(self):
return { 'tp_basicsize' : 'PyGstMiniObject',
'tp_weaklistoffset' : 'offsetof(PyGstMiniObject, weakreflist)',
'tp_dictoffset' : 'offsetof(PyGstMiniObject, inst_dict)' }
def get_field_accessor(self, fieldname):
castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1)
return '%s(pygstminiobject_get(self))->%s' % (castmacro, fieldname)
def get_initial_constructor_substdict(self, constructor):
substdict = Wrapper.get_initial_constructor_substdict(self,
constructor)
if not constructor.caller_owns_return:
substdict['aftercreate'] = " gst_mini_object_ref(self->obj);\n"
else:
substdict['aftercreate'] = ''
return substdict
def get_initial_method_substdict(self, method):
substdict = Wrapper.get_initial_method_substdict(self, method)
substdict['cast'] = string.replace(self.objinfo.typecode,
'_TYPE_', '_', 1)
return substdict
class GInterfaceWrapper(GObjectWrapper):
virtual_accessor_tmpl = (
'static PyObject *\n'
'_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n'
'{\n'
' %(vtable)s *iface;\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' iface = g_type_interface_peek('
'g_type_class_peek(pyg_type_from_object(cls)), %(typecode)s);\n'
' if (iface->%(virtual)s)\n'
' %(setreturn)siface->%(virtual)s(%(arglist)s);\n'
' else {\n'
' PyErr_SetString(PyExc_NotImplementedError, '
'"interface method %(name)s not implemented");\n'
' return NULL;\n'
' }\n'
'%(codeafter)s\n'
'}\n\n'
)
def get_initial_class_substdict(self):
return { 'tp_basicsize' : 'PyObject',
'tp_weaklistoffset' : '0',
'tp_dictoffset' : '0'}
def write_constructor(self):
# interfaces have no constructors ...
return '0'
def write_getsets(self):
# interfaces have no fields ...
return '0'
def _get_class_virtual_substdict(self, meth, cname, parent):
substdict = self.get_initial_method_substdict(meth)
substdict['virtual'] = substdict['name'].split('.')[1]
substdict['cname'] = cname
substdict['typecode'] = self.objinfo.typecode
substdict['vtable'] = self.objinfo.vtable
return substdict
def write_virtuals(self):
## Now write reverse method wrappers, which let python code
## implement interface methods.
# First, get methods from the defs files
klass = self.objinfo.c_name
proxies = []
for meth in self.parser.find_virtuals(self.objinfo):
method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
if self.overrides.is_ignored(method_name):
continue
try:
if self.overrides.is_overriden(method_name):
if not self.overrides.is_already_included(method_name):
data = self.overrides.override(method_name)
self.write_function(method_name, data)
else:
# write proxy ...
ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
wrapper = reversewrapper.ReverseWrapper(
'_wrap_' + method_name, is_static=True)
wrapper.set_return_type(ret(wrapper, **props))
wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
wrapper, "self", method_name="do_" + meth.name,
c_type=(klass + ' *')))
for param in meth.params:
handler, props = argtypes.matcher.get_reverse(
param.ptype)
props["direction"] = param.pdir
wrapper.add_parameter(
handler(wrapper, param.pname, **props))
buf = reversewrapper.MemoryCodeSink()
wrapper.generate(buf)
self.fp.write(buf.flush())
proxies.append((fixname(meth.name), '_wrap_' + method_name))
iproxies_coverage.declare_wrapped()
except (KeyError, ValueError):
iproxies_coverage.declare_not_wrapped()
proxies.append((fixname(meth.name), None))
sys.stderr.write('Could not write interface proxy %s.%s: %s\n'
% (klass, meth.name, exc_info()))
if not proxies:
return
# Make sure we have at least one proxy function
if not [cname for name,cname in proxies if not cname is None]:
return
## Write an interface init function for this object
funcname = "__%s__interface_init" % klass
vtable = self.objinfo.vtable
self.fp.write(
'\nstatic void\n'
'%(funcname)s(%(vtable)s *iface, PyTypeObject *pytype)\n'
'{\n'
' %(vtable)s *parent_iface = '
'g_type_interface_peek_parent(iface);\n'
' PyObject *py_method;\n'
'\n'
% vars())
for name, cname in proxies:
do_name = 'do_' + name
if cname is None:
continue
self.fp.write((
' py_method = pytype? PyObject_GetAttrString('
'(PyObject *) pytype, "%(do_name)s") : NULL;\n'
' if (py_method && !PyObject_TypeCheck(py_method, '
'&PyCFunction_Type)) {\n'
' iface->%(name)s = %(cname)s;\n'
' } else {\n'
' PyErr_Clear();\n'
' if (parent_iface) {\n'
' iface->%(name)s = parent_iface->%(name)s;\n'
' }\n'
' Py_XDECREF(py_method);\n'
' }\n'
) % vars())
self.fp.write('}\n\n')
interface_info = "__%s__iinfo" % klass
self.fp.write('''
static const GInterfaceInfo %s = {
(GInterfaceInitFunc) %s,
NULL,
NULL
};
''' % (interface_info, funcname))
self.objinfo.interface_info = interface_info
class GBoxedWrapper(Wrapper):
constructor_tmpl = (
'static int\n'
'_wrap_%(cname)s(PyGBoxed *self%(extraparams)s)\n'
'{\n' \
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' self->gtype = %(typecode)s;\n'
' self->free_on_dealloc = FALSE;\n'
' self->boxed = %(cname)s(%(arglist)s);\n'
'%(codeafter)s\n'
' if (!self->boxed) {\n'
' PyErr_SetString(PyExc_RuntimeError, '
'"could not create %(typename)s object");\n'
' return -1;\n'
' }\n'
' self->free_on_dealloc = TRUE;\n'
' return 0;\n'
'}\n\n'
)
method_tmpl = (
'static PyObject *\n'
'_wrap_%(cname)s(PyObject *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' %(begin_allow_threads)s\n'
' %(setreturn)s%(cname)s(pyg_boxed_get(self, '
'%(typename)s)%(arglist)s);\n'
' %(end_allow_threads)s\n'
'%(codeafter)s\n'
'}\n\n'
)
def get_initial_class_substdict(self):
return { 'tp_basicsize' : 'PyGBoxed',
'tp_weaklistoffset' : '0',
'tp_dictoffset' : '0' }
def get_field_accessor(self, fieldname):
return 'pyg_boxed_get(self, %s)->%s' % (self.objinfo.c_name, fieldname)
def get_initial_constructor_substdict(self, constructor):
substdict = Wrapper.get_initial_constructor_substdict(
self, constructor)
substdict['typecode'] = self.objinfo.typecode
return substdict
class GPointerWrapper(GBoxedWrapper):
constructor_tmpl = (
'static int\n'
'_wrap_%(cname)s(PyGPointer *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' self->gtype = %(typecode)s;\n'
' self->pointer = %(cname)s(%(arglist)s);\n'
'%(codeafter)s\n'
' if (!self->pointer) {\n'
' PyErr_SetString(PyExc_RuntimeError, '
'"could not create %(typename)s object");\n'
' return -1;\n'
' }\n'
' return 0;\n'
'}\n\n'
)
method_tmpl = (
'static PyObject *\n'
'_wrap_%(cname)s(PyObject *self%(extraparams)s)\n'
'{\n'
'%(varlist)s'
'%(parseargs)s'
'%(codebefore)s'
' %(setreturn)s%(cname)s(pyg_pointer_get(self, '
'%(typename)s)%(arglist)s);\n'
'%(codeafter)s\n'
'}\n\n'
)
def get_initial_class_substdict(self):
return { 'tp_basicsize' : 'PyGPointer',
'tp_weaklistoffset' : '0',
'tp_dictoffset' : '0' }
def get_field_accessor(self, fieldname):
return 'pyg_pointer_get(self, %s)->%s' % (self.objinfo.c_name,
fieldname)
def get_initial_constructor_substdict(self, constructor):
substdict = Wrapper.get_initial_constructor_substdict(
self, constructor)
substdict['typecode'] = self.objinfo.typecode
return substdict
def write_headers(data, fp):
fp.write('/* -- THIS FILE IS GENERATED - DO NOT EDIT */')
fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n')
fp.write('#include <Python.h>\n\n\n')
fp.write(data)
fp.resetline()
fp.write('\n\n')
def write_body(data, fp):
fp.write(data)
fp.resetline()
fp.write('\n\n')
def write_imports(overrides, fp):
fp.write('/* ---------- types from other modules ---------- */\n')
for module, pyname, cname in overrides.get_imports():
fp.write('static PyTypeObject *_%s;\n' % cname)
fp.write('#define %s (*_%s)\n' % (cname, cname))
fp.write('\n\n')
def write_type_declarations(parser, fp):
fp.write('/* ---------- forward type declarations ---------- */\n')
for obj in parser.boxes:
fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n')
for obj in parser.objects:
fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n')
for obj in parser.miniobjects:
fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n')
for interface in parser.interfaces:
fp.write('PyTypeObject Py' + interface.c_name + '_Type;\n')
fp.write('\n')
def sort_parent_children(objects):
objects = list(objects)
modified = True
while modified:
modified = False
parent_index = None
child_index = None
for i, obj in enumerate(objects):
if obj.parent == 'GObject':
continue
if obj.parent not in [info.c_name for info in objects[:i]]:
for j, info in enumerate(objects[i+1:]):
if info.c_name == obj.parent:
parent_index = i + 1 + j
child_index = i
break
else:
continue
break
if child_index is not None and parent_index is not None:
if child_index != parent_index:
objects.insert(child_index, objects.pop(parent_index))
modified = True
return objects
def write_classes(parser, overrides, fp):
## Sort the objects, so that we generate code for the parent types
## before their children.
objects = sort_parent_children(parser.objects)
for klass, items in ((GBoxedWrapper, parser.boxes),
(GPointerWrapper, parser.pointers),
(GObjectWrapper, objects),
(GstMiniObjectWrapper, parser.miniobjects),
(GInterfaceWrapper, parser.interfaces)):
for item in items:
instance = klass(parser, item, overrides, fp)
instance.write_class()
fp.write('\n')
def write_enums(parser, overrides, prefix, fp=sys.stdout):
if not parser.enums:
return
fp.write('\n/* ----------- enums and flags ----------- */\n\n')
fp.write(
'void\n' + prefix +
'_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n')
for enum in parser.enums:
if overrides.is_type_ignored(enum.c_name):
continue
if enum.typecode is None:
for nick, value in enum.values:
fp.write(
' PyModule_AddIntConstant(module, '
'(char *) pyg_constant_strip_prefix("%s", strip_prefix), %s);\n'
% (value, value))
else:
if enum.deftype == 'enum':
fp.write(' pyg_enum_add(module, "%s", strip_prefix, %s);\n'
% (enum.name, enum.typecode))
else:
fp.write(' pyg_flags_add(module, "%s", strip_prefix, %s);\n'
% (enum.name, enum.typecode))
fp.write('\n')
fp.write(' if (PyErr_Occurred())\n')
fp.write(' PyErr_Print();\n')
fp.write('}\n\n')
def write_extension_init(overrides, prefix, fp):
fp.write('/* initialise stuff extension classes */\n')
fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n')
imports = overrides.get_imports()[:]
if imports:
bymod = {}
for module, pyname, cname in imports:
bymod.setdefault(module, []).append((pyname, cname))
fp.write(' PyObject *module;\n\n')
for module in bymod:
fp.write(
' if ((module = PyImport_ImportModule("%s")) != NULL) {\n'
% module)
fp.write(
' PyObject *moddict = PyModule_GetDict(module);\n\n')
for pyname, cname in bymod[module]:
fp.write(
' _%s = (PyTypeObject *)PyDict_GetItemString('
'moddict, "%s");\n' % (cname, pyname))
fp.write(' if (_%s == NULL) {\n' % cname)
fp.write(' PyErr_SetString(PyExc_ImportError,\n')
fp.write(' "cannot import name %s from %s");\n'
% (pyname, module))
fp.write(' return;\n')
fp.write(' }\n')
fp.write(' } else {\n')
fp.write(' PyErr_SetString(PyExc_ImportError,\n')
fp.write(' "could not import %s");\n' % module)
fp.write(' return;\n')
fp.write(' }\n')
fp.write('\n')
fp.write(overrides.get_init() + '\n')
fp.resetline()
def write_registers(parser, overrides, fp):
for boxed in parser.boxes:
fp.write(' pyg_register_boxed(d, "' + boxed.name +
'", ' + boxed.typecode +
', &Py' + boxed.c_name +
'_Type);\n')
for pointer in parser.pointers:
fp.write(' pyg_register_pointer(d, "' + pointer.name +
'", ' + pointer.typecode +
', &Py' + pointer.c_name + '_Type);\n')
for interface in parser.interfaces:
fp.write(' pyg_register_interface(d, "' + interface.name +
'", '+ interface.typecode + ', &Py' + interface.c_name +
'_Type);\n')
if interface.interface_info is not None:
fp.write(' pyg_register_interface_info(%s, &%s);\n' %
(interface.typecode, interface.interface_info))
objects = parser.objects[:]
pos = 0
while pos < len(objects):
parent = objects[pos].parent
for i in range(pos+1, len(objects)):
if objects[i].c_name == parent:
objects.insert(i+1, objects[pos])
del objects[pos]
break
else:
pos = pos + 1
for obj in objects:
if overrides.is_type_ignored(obj.c_name):
continue
bases = []
if obj.parent != None:
bases.append(obj.parent)
bases = bases + obj.implements
if bases:
fp.write(' pygobject_register_class(d, "' + obj.c_name +
'", ' + obj.typecode + ', &Py' + obj.c_name +
'_Type, Py_BuildValue("(' + 'O' * len(bases) + ')", ' +
string.join(map(lambda s: '&Py'+s+'_Type', bases), ', ') +
'));\n')
else:
fp.write(' pygobject_register_class(d, "' + obj.c_name +
'", ' + obj.typecode + ', &Py' + obj.c_name +
'_Type, NULL);\n')
if obj.has_new_constructor_api:
fp.write(' pyg_set_object_has_new_constructor(%s);\n' %
obj.typecode)
else:
print >> sys.stderr, (
"Warning: Constructor for %s needs to be updated to new API\n"
" See http://live.gnome.org/PyGTK_2fWhatsNew28"
"#update-constructors") % obj.c_name
if obj.class_init_func is not None:
fp.write(' pyg_register_class_init(%s, %s);\n' %
(obj.typecode, obj.class_init_func))
#TODO: register mini-objects
miniobjects = parser.miniobjects[:]
for obj in miniobjects:
bases = []
if obj.parent != None:
bases.append(obj.parent)
bases = bases + obj.implements
if bases:
fp.write(' pygstminiobject_register_class(d, "' + obj.c_name +
'", ' + obj.typecode + ', &Py' + obj.c_name +
'_Type, Py_BuildValue("(' + 'O' * len(bases) + ')", ' +
string.join(map(lambda s: '&Py'+s+'_Type', bases), ', ') +
'));\n')
else:
fp.write(' pygstminiobject_register_class(d, "' + obj.c_name +
'", ' + obj.typecode + ', &Py' + obj.c_name +
'_Type, NULL);\n')
fp.write('}\n')
def write_source(parser, overrides, prefix, fp=FileOutput(sys.stdout)):
write_headers(overrides.get_headers(), fp)
write_imports(overrides, fp)
write_type_declarations(parser, fp)
write_body(overrides.get_body(), fp)
write_classes(parser, overrides, fp)
wrapper = Wrapper(parser, None, overrides, fp)
wrapper.write_functions(prefix)
write_enums(parser, overrides, prefix, fp)
write_extension_init(overrides, prefix, fp)
write_registers(parser, overrides, fp)
def register_types(parser):
for boxed in parser.boxes:
argtypes.matcher.register_boxed(boxed.c_name, boxed.typecode)
for pointer in parser.pointers:
argtypes.matcher.register_pointer(pointer.c_name, pointer.typecode)
for obj in parser.objects:
argtypes.matcher.register_object(obj.c_name, obj.parent, obj.typecode)
for obj in parser.miniobjects:
argtypes.matcher.register_miniobject(obj.c_name, obj.parent, obj.typecode)
for obj in parser.interfaces:
argtypes.matcher.register_object(obj.c_name, None, obj.typecode)
for enum in parser.enums:
if enum.deftype == 'flags':
argtypes.matcher.register_flag(enum.c_name, enum.typecode)
else:
argtypes.matcher.register_enum(enum.c_name, enum.typecode)
usage = 'usage: codegen.py [-o overridesfile] [-p prefix] defsfile'
def main(argv):
o = override.Overrides()
prefix = 'pygtk'
outfilename = None
errorfilename = None
extendpath = []
opts, args = getopt.getopt(argv[1:], "o:p:r:t:D:x",
["override=", "prefix=", "register=", "outfilename=",
"load-types=", "errorfilename=", "extendpath="])
defines = {} # -Dkey[=val] options
for opt, arg in opts:
if opt in ('-x', '--extendpath'):
extendpath.append(arg)
extendpath.insert(0, os.getcwd())
o = override.Overrides(path=extendpath)
for opt, arg in opts:
if opt in ('-o', '--override'):
o = override.Overrides(arg, path=extendpath)
elif opt in ('-p', '--prefix'):
prefix = arg
elif opt in ('-r', '--register'):
# Warning: user has to make sure all -D options appear before -r
p = defsparser.DefsParser(arg, defines)
p.startParsing()
register_types(p)
del p
elif opt == '--outfilename':
outfilename = arg
elif opt == '--errorfilename':
errorfilename = arg
elif opt in ('-t', '--load-types'):
globals = {}
execfile(arg, globals)
elif opt == '-D':
nameval = arg.split('=')
try:
defines[nameval[0]] = nameval[1]
except IndexError:
defines[nameval[0]] = None
if len(args) < 1:
print >> sys.stderr, usage
return 1
if errorfilename:
sys.stderr = open(errorfilename, "w")
p = defsparser.DefsParser(args[0], defines)
if not outfilename:
outfilename = os.path.splitext(args[0])[0] + '.c'
p.startParsing()
register_types(p)
write_source(p, o, prefix, FileOutput(sys.stdout, outfilename))
functions_coverage.printstats()
methods_coverage.printstats()
vproxies_coverage.printstats()
vaccessors_coverage.printstats()
iproxies_coverage.printstats()
if __name__ == '__main__':
sys.exit(main(sys.argv))