diff options
Diffstat (limited to 'codegen/codegen.py')
-rw-r--r--[-rwxr-xr-x] | codegen/codegen.py | 1722 |
1 files changed, 7 insertions, 1715 deletions
diff --git a/codegen/codegen.py b/codegen/codegen.py index aef93ae..6486fb7 100755..100644 --- a/codegen/codegen.py +++ b/codegen/codegen.py @@ -1,1719 +1,11 @@ #! /usr/bin/env python -import getopt -import keyword -import os -import string -import sys - -import argtypes -import definitions -import defsparser -import override -import reversewrapper -import warnings - -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.\n" % 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(): - warnings.warn("deprecated", DeprecationWarning, stacklevel=2) - #traceback.print_exc() - etype, value, tb = sys.exc_info() - ret = "" - try: - sval = str(value) - if etype == argtypes.ArgTypeError: - 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 + str.count('\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 G_GNUC_INTERNAL Py%(typename)s_Type = {\n' - ' PyVarObject_HEAD_INIT(NULL, 0)\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' - ' NULL, //%(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.py_name, - 'errorreturn': '-1' } - - def get_initial_method_substdict(self, method): - substdict = { 'name': '%s.%s' % (self.objinfo.py_name, method.name) } - if method.unblock_threads: - substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;' - substdict['end_allow_threads'] = 'pyg_end_allow_threads;' - else: - substdict['begin_allow_threads'] = '' - substdict['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 argtypes.ArgTypeNotFoundError("varargs functions not supported") - - for param in function_obj.params: - if param.pdflt != None 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, 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) - - if function_obj.unblock_threads: - substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;' - substdict['end_allow_threads'] = 'pyg_end_allow_threads;' - else: - substdict['begin_allow_threads'] = '' - substdict['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 argtypes.ArgTypeError, ex: - sys.stderr.write('Could not write constructor for %s: %s\n' - % (self.objinfo.c_name, str(ex))) - - 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'] = meth.name - 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 argtypes.ArgTypeError, ex: - methods_coverage.declare_not_wrapped() - sys.stderr.write('Could not write method %s.%s: %s\n' - % (klass, meth.name, str(ex))) - - # 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': 'NULL' }) - methods_coverage.declare_wrapped() - except argtypes.ArgTypeError, ex: - methods_coverage.declare_not_wrapped() - sys.stderr.write('Could not write method %s.%s: %s\n' - % (klass, method_name, str(ex))) - - # 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 argtypes.ArgTypeError, ex: - vaccessors_coverage.declare_not_wrapped() - sys.stderr.write( - 'Could not write virtual accessor method %s.%s: %s\n' - % (klass, meth.name, str(ex))) - 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 argtypes.ArgTypeError, ex: - 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, str(ex))) - 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 argtypes.ArgTypeError, ex: - sys.stderr.write( - "Could not write getter for %s.%s: %s\n" - % (self.objinfo.c_name, fname, str(ex))) - 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_get_symbol_names(self, writer, functions): - self.fp.write("""static PyObject * -_wrap__get_symbol_names(PyObject *self) -{ - PyObject *pylist = PyList_New(0); - -""") - for obj, bases in writer.get_classes(): - self.fp.write(' PyList_Append(pylist, ' - 'PyString_FromString("%s"));\n' % (obj.name)) - - for name, cname, flags, docstring in functions: - self.fp.write(' PyList_Append(pylist, ' - 'PyString_FromString("%s"));\n' % (name)) - - for enum in writer.get_enums(): - self.fp.write(' PyList_Append(pylist, ' - 'PyString_FromString("%s"));\n' % (enum.name)) - for nick, value in enum.values: - name = value[len(self.overrides.modulename)+1:] - self.fp.write(' PyList_Append(pylist, ' - 'PyString_FromString("%s"));\n' % (name)) - - self.fp.write(" return pylist;\n}\n\n"); - - def _write_get_symbol(self, writer, functions): - self.fp.write("""static PyObject * -_wrap__get_symbol(PyObject *self, PyObject *args) -{ - PyObject *d; - char *name; - static PyObject *modulename = NULL; - static PyObject *module = NULL; - static char *strip_prefix = "%s"; - - if (!PyArg_ParseTuple(args, "Os", &d, &name)) - return NULL; - - if (!modulename) - modulename = PyString_FromString("%s"); - - if (!module) - module = PyDict_GetItemString(d, "__module__"); - -""" % (self.overrides.modulename.upper() + '_', - self.overrides.modulename)) - - first = True - # Classes / GObjects - for obj, bases in writer.get_classes(): - if first: - self.fp.write(' if (!strcmp(name, "%s")) {\n' % obj.name) - first = False - else: - self.fp.write(' } else if (!strcmp(name, "%s")) {\n' % obj.name) - self.fp.write( - ' return (PyObject*)pygobject_lookup_class(%s);\n' % - obj.typecode) - self.fp.write(' }\n') - - # Functions - for name, cname, flags, docstring in functions: - self.fp.write(' else if (!strcmp(name, "%s")) {\n' % name) - self.fp.write(' static PyMethodDef ml = { ' - '"%s", (PyCFunction)%s, %s, "%s"};\n' % ( - name, cname, flags, docstring)) - self.fp.write(' return PyCFunction_NewEx(&ml, NULL, modulename);\n') - self.fp.write(' }\n') - - # Enums - def write_enum(enum, returnobj=False): - if returnobj: - ret = 'return ' - else: - ret = '' - if enum.deftype == 'enum': - self.fp.write( - ' %spyg_enum_add(module, "%s", strip_prefix, %s);\n' - % (ret, enum.name, enum.typecode)) - else: - self.fp.write( - ' %spyg_flags_add(module, "%s", strip_prefix, %s);\n' - % (ret, enum.name, enum.typecode)) - - strip_len = len(self.overrides.modulename)+1 # GTK_ - for enum in writer.get_enums(): - # XXX: Implement without typecodes - self.fp.write(' else if (!strcmp(name, "%s")) {\n' % enum.name) - write_enum(enum, returnobj=True) - self.fp.write(' }\n') - - for nick, value in enum.values: - value = value[strip_len:] - self.fp.write(' else if (!strcmp(name, "%s")) {\n' % value) - write_enum(enum) - self.fp.write(' return PyObject_GetAttrString(module, "%s");\n' % - value) - self.fp.write(' }\n') - - self.fp.write(' return Py_None;\n}\n\n'); - - def _write_function_bodies(self): - 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((func.name, '_wrap_' + funcname, - methflags, func.docstring)) - functions_coverage.declare_wrapped() - except argtypes.ArgTypeError, ex: - functions_coverage.declare_not_wrapped() - sys.stderr.write('Could not write function %s: %s\n' - % (func.name, str(ex))) - - # 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((funcname, '_wrap_' + funcname, - methflags, 'NULL')) - functions_coverage.declare_wrapped() - except argtypes.ArgTypeError, ex: - functions_coverage.declare_not_wrapped() - sys.stderr.write('Could not write function %s: %s\n' - % (funcname, str(ex))) - return functions - - def write_functions(self, writer, prefix): - self.fp.write('\n/* ----------- functions ----------- */\n\n') - functions = [] - func_infos = self._write_function_bodies() - - # If we have a dynamic namespace, write symbol and attribute getter - if self.overrides.dynamicnamespace: - self._write_get_symbol_names(writer, func_infos) - self._write_get_symbol(writer, func_infos) - for obj, bases in writer.get_classes(): - self.fp.write("""static PyTypeObject * -%s_register_type(const gchar *name, PyObject *unused) -{ - PyObject *m = PyImport_ImportModule("gtk"); - PyObject *d = PyModule_GetDict(m); -""" % obj.c_name) - writer.write_class(obj, bases, indent=1) - self.fp.write( - ' return (%s)PyDict_GetItemString(d, "%s");\n' % ( - 'PyTypeObject*', obj.name)) - self.fp.write("}\n") - - functions.append(' { "_get_symbol_names", ' - '(PyCFunction)_wrap__get_symbol_names, ' - 'METH_NOARGS, NULL },\n') - functions.append(' { "_get_symbol", ' - '(PyCFunction)_wrap__get_symbol, ' - 'METH_VARARGS, NULL },\n') - else: - for name, cname, flags, docstring in func_infos: - functions.append(self.methdef_tmpl % dict(name=name, - cname=cname, - flags=flags, - docstring=docstring)) - - # 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(¶ms[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 - - -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'] = meth.name - 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 argtypes.ArgTypeError, ex: - 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, str(ex))) - - if not proxies or not [cname for name, cname in proxies if cname]: - 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 - -class SourceWriter: - def __init__(self, parser, overrides, prefix, fp=FileOutput(sys.stdout)): - self.parser = parser - self.overrides = overrides - self.prefix = prefix - self.fp = fp - - def write(self, py_ssize_t_clean=False): - argtypes.py_ssize_t_clean = py_ssize_t_clean - - self.write_headers(py_ssize_t_clean) - self.write_imports() - self.write_type_declarations() - self.write_body() - self.write_classes() - - wrapper = Wrapper(self.parser, None, self.overrides, self.fp) - wrapper.write_functions(self, self.prefix) - - if not self.overrides.dynamicnamespace: - self.write_enums() - self.write_extension_init() - self.write_registers() - - argtypes.py_ssize_t_clean = False - - def write_headers(self, py_ssize_t_clean): - self.fp.write('/* -- THIS FILE IS GENERATED - DO NOT EDIT */') - self.fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n') - if py_ssize_t_clean: - self.fp.write('#define PY_SSIZE_T_CLEAN\n') - self.fp.write('#include <Python.h>\n\n\n') - if py_ssize_t_clean: - self.fp.write(''' - -#if PY_VERSION_HEX < 0x02050000 -typedef int Py_ssize_t; -#define PY_SSIZE_T_MAX INT_MAX -#define PY_SSIZE_T_MIN INT_MIN -typedef inquiry lenfunc; -typedef intargfunc ssizeargfunc; -typedef intobjargproc ssizeobjargproc; -#endif - -''') - self.fp.write(self.overrides.get_headers()) - self.fp.resetline() - self.fp.write('\n\n') - - def write_imports(self): - self.fp.write('/* ---------- types from other modules ---------- */\n') - for module, pyname, cname, importing_for in self.overrides.get_imports(): - if importing_for is None or is_registered_object(importing_for): - self.fp.write('static PyTypeObject *_%s;\n' % cname) - self.fp.write('#define %s (*_%s)\n' % (cname, cname)) - self.fp.write('\n\n') - - def write_type_declarations(self): - #todo use 'static' if used only in one file - self.fp.write('/* ---------- forward type declarations ---------- */\n') - for obj in self.parser.boxes: - if not self.overrides.is_type_ignored(obj.c_name): - self.fp.write('PyTypeObject G_GNUC_INTERNAL Py' + obj.c_name + '_Type;\n') - for obj in self.parser.objects: - if not self.overrides.is_type_ignored(obj.c_name): - self.fp.write('PyTypeObject G_GNUC_INTERNAL Py' + obj.c_name + '_Type;\n') - for interface in self.parser.interfaces: - if not self.overrides.is_type_ignored(interface.c_name): - self.fp.write('PyTypeObject G_GNUC_INTERNAL Py' + interface.c_name + '_Type;\n') - self.fp.write('\n') - - def write_body(self): - self.fp.write(self.overrides.get_body()) - self.fp.resetline() - self.fp.write('\n\n') - - def _sort_parent_children(self, 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(self): - ## Sort the objects, so that we generate code for the parent types - ## before their children. - objects = self._sort_parent_children(self.parser.objects) - - for klass, items in ((GBoxedWrapper, self.parser.boxes), - (GPointerWrapper, self.parser.pointers), - (GObjectWrapper, objects), - (GInterfaceWrapper, self.parser.interfaces)): - for item in items: - instance = klass(self.parser, item, self.overrides, self.fp) - instance.write_class() - self.fp.write('\n') - - def get_enums(self): - enums = [] - for enum in self.parser.enums: - if self.overrides.is_type_ignored(enum.c_name): - continue - enums.append(enum) - return enums - - def write_enums(self): - if not self.parser.enums: - return - - self.fp.write('\n/* ----------- enums and flags ----------- */\n\n') - self.fp.write( - 'void\n' + self.prefix + - '_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n') - - self.fp.write( - '#ifdef VERSION\n' - ' PyModule_AddStringConstant(module, "__version__", VERSION);\n' - '#endif\n') - - for enum in self.get_enums(): - if enum.typecode is None: - for nick, value in enum.values: - self.fp.write( - ' PyModule_AddIntConstant(module, ' - '(char *) pyg_constant_strip_prefix("%s", strip_prefix), %s);\n' - % (value, value)) - else: - if enum.deftype == 'enum': - self.fp.write(' pyg_enum_add(module, "%s", strip_prefix, %s);\n' - % (enum.name, enum.typecode)) - else: - self.fp.write(' pyg_flags_add(module, "%s", strip_prefix, %s);\n' - % (enum.name, enum.typecode)) - - self.fp.write('\n') - self.fp.write(' if (PyErr_Occurred())\n') - self.fp.write(' PyErr_Print();\n') - self.fp.write('}\n\n') - - def write_object_imports(self, retval=''): - imports = self.overrides.get_imports()[:] - if not imports: - return - - bymod = {} - for module, pyname, cname, importing_for in imports: - if importing_for is None or is_registered_object(importing_for): - bymod.setdefault(module, []).append((pyname, cname)) - self.fp.write(' PyObject *module;\n\n') - for module in bymod: - self.fp.write( - ' if ((module = PyImport_ImportModule("%s")) != NULL) {\n' - % module) - #self.fp.write( - # ' PyObject *moddict = PyModule_GetDict(module);\n\n') - for pyname, cname in bymod[module]: - #self.fp.write( - # ' _%s = (PyTypeObject *)PyDict_GetItemString(' - # 'moddict, "%s");\n' % (cname, pyname)) - self.fp.write( - ' _%s = (PyTypeObject *)PyObject_GetAttrString(' - 'module, "%s");\n' % (cname, pyname)) - self.fp.write(' if (_%s == NULL) {\n' % cname) - self.fp.write(' PyErr_SetString(PyExc_ImportError,\n') - self.fp.write(' "cannot import name %s from %s");\n' - % (pyname, module)) - self.fp.write(' return %s;\n' % retval) - self.fp.write(' }\n') - self.fp.write(' } else {\n') - self.fp.write(' PyErr_SetString(PyExc_ImportError,\n') - self.fp.write(' "could not import %s");\n' % module) - self.fp.write(' return %s;\n' % retval) - self.fp.write(' }\n') - self.fp.write('\n') - - def write_extension_init(self): - self.fp.write('/* initialise stuff extension classes */\n') - self.fp.write('void\n' + self.prefix + '_register_classes(PyObject *d)\n{\n') - self.write_object_imports() - self.fp.write(self.overrides.get_init() + '\n') - self.fp.resetline() - - def get_classes(self): - objects = self.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 - - retval = [] - for obj in objects: - if self.overrides.is_type_ignored(obj.c_name): - continue - bases = [] - if obj.parent != None: - bases.append(obj.parent) - bases = bases + obj.implements - retval.append((obj, bases)) - - return retval - - def write_registers(self): - for boxed in self.parser.boxes: - if not self.overrides.is_type_ignored(boxed.c_name): - self.fp.write(' pyg_register_boxed(d, "' + boxed.name + - '", ' + boxed.typecode + - ', &Py' + boxed.c_name + - '_Type);\n') - for pointer in self.parser.pointers: - if not self.overrides.is_type_ignored(pointer.c_name): - self.fp.write(' pyg_register_pointer(d, "' + pointer.name + - '", ' + pointer.typecode + - ', &Py' + pointer.c_name + '_Type);\n') - for interface in self.parser.interfaces: - if not self.overrides.is_type_ignored(interface.c_name): - self.fp.write(' pyg_register_interface(d, "' - + interface.name + '", '+ interface.typecode - + ', &Py' + interface.c_name + '_Type);\n') - if interface.interface_info is not None: - self.fp.write(' pyg_register_interface_info(%s, &%s);\n' % - (interface.typecode, interface.interface_info)) - - if not self.overrides.dynamicnamespace: - for obj, bases in self.get_classes(): - self.write_class(obj, bases) - else: - for obj, bases in self.get_classes(): - self.fp.write( - ' pyg_type_register_custom_callback("%s", ' - '(PyGTypeRegistrationFunction)%s_register_type, d);\n' % - (obj.c_name, obj.c_name)) - - self.fp.write('}\n') - - def _can_direct_ref(self, base): - if not self.overrides.dynamicnamespace: - return True - if base == 'GObject': - return True - obj = get_object_by_name(base) - if obj.module.lower() != self.overrides.modulename: - return True - return False - - def write_class(self, obj, bases, indent=1): - indent_str = ' ' * (indent * 4) - if bases: - bases_str = 'Py_BuildValue("(%s)"' % (len(bases) * 'O') - - for base in bases: - if self._can_direct_ref(base): - bases_str += ', &Py%s_Type' % base - else: - baseobj = get_object_by_name(base) - bases_str += ', PyObject_GetAttrString(m, "%s")' % baseobj.name - bases_str += ')' - else: - bases_str = 'NULL' - - self.fp.write( - '%(indent)spygobject_register_class(d, "%(c_name)s", %(typecode)s, &Py%(c_name)s_Type, %(bases)s);\n' - % dict(indent=indent_str, c_name=obj.c_name, typecode=obj.typecode, bases=bases_str)) - - if obj.has_new_constructor_api: - self.fp.write( - indent_str + '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: - self.fp.write( - indent_str + 'pyg_register_class_init(%s, %s);\n' % - (obj.typecode, obj.class_init_func)) - -_objects = {} - -def is_registered_object(c_name): - return c_name in _objects - -def get_object_by_name(c_name): - global _objects - return _objects[c_name] - -def register_types(parser): - global _objects - for boxed in parser.boxes: - argtypes.matcher.register_boxed(boxed.c_name, boxed.typecode) - _objects[boxed.c_name] = boxed - 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) - _objects[obj.c_name] = obj - for iface in parser.interfaces: - argtypes.matcher.register_object(iface.c_name, None, iface.typecode) - _objects[iface.c_name] = iface - 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 - opts, args = getopt.getopt(argv[1:], "o:p:r:t:D:I:", - ["override=", "prefix=", "register=", "outfilename=", - "load-types=", "errorfilename=", "py_ssize_t-clean"]) - defines = {} # -Dkey[=val] options - py_ssize_t_clean = False - for opt, arg in opts: - if opt in ('-o', '--override'): - o = override.Overrides(arg) - 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 - elif opt == '-I': - defsparser.include_path.insert(0, arg) - elif opt == '--py_ssize_t-clean': - py_ssize_t_clean = True - 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) - sw = SourceWriter(p, o, prefix, FileOutput(sys.stdout, outfilename)) - sw.write(py_ssize_t_clean) +# codegen.py is runnable as a script and available as module in codegen package +if __name__ == '__main__': + from libcodegen import codegen + import sys + sys.exit(codegen.main(sys.argv)) +else: + from codegen.libcodegen.codegen import * - functions_coverage.printstats() - methods_coverage.printstats() - vproxies_coverage.printstats() - vaccessors_coverage.printstats() - iproxies_coverage.printstats() -if __name__ == '__main__': - sys.exit(main(sys.argv)) |