summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Ehresman <jpe@wingware.com>2010-04-15 12:57:22 -0400
committerJohn Ehresman <jpe@wingware.com>2010-04-15 12:57:22 -0400
commit27e7665c4805eab2f4d97b99436e471cf7ba945c (patch)
tree3dfe3a248fee559d8d297b80a2b3fddd38f50d14
parentdc91f48833e5f3b94f02a0be16d0d47c10d364f5 (diff)
downloadpygobject-27e7665c4805eab2f4d97b99436e471cf7ba945c.tar.gz
pygobject-27e7665c4805eab2f4d97b99436e471cf7ba945c.tar.xz
pygobject-27e7665c4805eab2f4d97b99436e471cf7ba945c.zip
Python 3 support for setup.py
-rw-r--r--codegen/__init__.py16
-rwxr-xr-xcodegen/code-coverage.py2
-rw-r--r--[-rwxr-xr-x]codegen/codegen.py1722
-rwxr-xr-xcodegen/defsconvert.py4
-rwxr-xr-xcodegen/defsgen.py4
-rw-r--r--codegen/defsparser.py154
-rw-r--r--codegen/docextract.py448
-rwxr-xr-xcodegen/docextract_to_xml.py101
-rw-r--r--codegen/libcodegen/__init__.py16
-rw-r--r--codegen/libcodegen/argtypes.py (renamed from codegen/argtypes.py)53
-rw-r--r--codegen/libcodegen/codegen.py1722
-rw-r--r--codegen/libcodegen/definitions.py (renamed from codegen/definitions.py)16
-rw-r--r--codegen/libcodegen/defsparser.py153
-rw-r--r--codegen/libcodegen/docextract.py185
-rw-r--r--codegen/libcodegen/override.py285
-rw-r--r--codegen/libcodegen/reversewrapper.py (renamed from codegen/reversewrapper.py)10
-rw-r--r--codegen/libcodegen/scmexpr.py147
-rw-r--r--codegen/override.py286
-rw-r--r--[-rwxr-xr-x]codegen/scmexpr.py146
-rw-r--r--dsextras.py24
-rwxr-xr-xsetup.py41
21 files changed, 2626 insertions, 2909 deletions
diff --git a/codegen/__init__.py b/codegen/__init__.py
index 86188f9..e69de29 100644
--- a/codegen/__init__.py
+++ b/codegen/__init__.py
@@ -1,16 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-
-__all__ = [
- 'argtypes',
- 'codegen',
- 'definitions',
- 'defsparser',
- 'docextract',
- 'docgen',
- 'h2def',
- 'defsgen'
- 'mergedefs',
- 'mkskel',
- 'override',
- 'scmexpr'
-]
diff --git a/codegen/code-coverage.py b/codegen/code-coverage.py
index 1dc54c3..5d192b3 100755
--- a/codegen/code-coverage.py
+++ b/codegen/code-coverage.py
@@ -38,7 +38,7 @@ def main():
for symbol in read_symbols(library, type='T', dynamic=1):
if symbol[0] == '_': continue
if symbol not in wrapper_symbols:
- print symbol
+ print(symbol)
if __name__ == '__main__':
main()
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(&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
-
-
-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))
diff --git a/codegen/defsconvert.py b/codegen/defsconvert.py
index c3c2324..c58db53 100755
--- a/codegen/defsconvert.py
+++ b/codegen/defsconvert.py
@@ -16,11 +16,11 @@ def to_upper_str(name):
name = _upperstr_pat1.sub(r'\1_\2', name)
name = _upperstr_pat2.sub(r'\1_\2', name)
name = _upperstr_pat3.sub(r'\1_\2', name, count=1)
- return string.upper(name)
+ return name.upper()
def typecode(typename):
"""create a typecode (eg. GTK_TYPE_WIDGET) from a typename"""
- return string.replace(to_upper_str(typename), '_', '_TYPE_', 1)
+ return to_upper_str(typename).replace('_', '_TYPE_', 1)
STATE_START = 0
diff --git a/codegen/defsgen.py b/codegen/defsgen.py
index 6c2e63d..de7c0de 100755
--- a/codegen/defsgen.py
+++ b/codegen/defsgen.py
@@ -220,7 +220,7 @@ def find_defs(buf, gobj, modlib, defs):
func_name = m[1]
for lib in modlib:
if hasattr(lib, func_name):
- objtype = apply(getattr(lib, func_name))
+ objtype = getattr(lib, func_name)()
obj_name = gobj.g_type_name(objtype)
parent = gobj.g_type_parent(objtype)
parent_name = gobj.g_type_name(parent)
@@ -504,7 +504,7 @@ class DefsWriter:
func = m.group(1) + '_get_type'
lib = [l for l in self.modlib if hasattr(l, func)]
if lib:
- cname = self.gobj.g_type_name(apply(getattr(lib[0], func)))
+ cname = self.gobj.g_type_name(getattr(lib[0], func)())
if cname and self.gobj.g_type_from_name(r.group(1)):
self.fp.write(' (is-constructor-of "' + cname + '")\n')
self._write_return(ret)
diff --git a/codegen/defsparser.py b/codegen/defsparser.py
index 37ba0a2..27b6b4d 100644
--- a/codegen/defsparser.py
+++ b/codegen/defsparser.py
@@ -1,153 +1 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-import os, sys
-import scmexpr
-from definitions import BoxedDef, EnumDef, FlagsDef, FunctionDef, \
- InterfaceDef, MethodDef, ObjectDef, PointerDef, VirtualDef
-
-include_path = ['.']
-
-class IncludeParser(scmexpr.Parser):
- """A simple parser that follows include statements automatically"""
- def include(self, input_filename):
- global include_path
- if os.path.isabs(input_filename):
- filename = input_filename
- # set self.filename to the include name, to handle recursive includes
- oldfile = self.filename
- self.filename = filename
- self.startParsing()
- self.filename = oldfile
- else:
- inc_path = [os.path.dirname(self.filename)] + include_path
- for filename in [os.path.join(path_entry, input_filename)
- for path_entry in inc_path]:
- if not os.path.exists(filename):
- continue
- # set self.filename to the include name, to handle recursive includes
- oldfile = self.filename
- self.filename = filename
- self.startParsing()
- self.filename = oldfile
- break
- else:
- raise IOError("%s not found in include path %s" % (input_filename, inc_path))
-
-class DefsParser(IncludeParser):
- def __init__(self, arg, defines={}):
- IncludeParser.__init__(self, arg)
- self.objects = []
- self.interfaces = []
- self.enums = [] # enums and flags
- self.boxes = [] # boxed types
- self.pointers = [] # pointer types
- self.functions = [] # functions and methods
- self.virtuals = [] # virtual methods
- self.c_name = {} # hash of c names of functions
- self.methods = {} # hash of methods of particular objects
- self.defines = defines # -Dfoo=bar options, as dictionary
-
- def define_object(self, *args):
- odef = apply(ObjectDef, args)
- self.objects.append(odef)
- self.c_name[odef.c_name] = odef
- def define_interface(self, *args):
- idef = apply(InterfaceDef, args)
- self.interfaces.append(idef)
- self.c_name[idef.c_name] = idef
- def define_enum(self, *args):
- edef = apply(EnumDef, args)
- self.enums.append(edef)
- self.c_name[edef.c_name] = edef
- def define_flags(self, *args):
- fdef = apply(FlagsDef, args)
- self.enums.append(fdef)
- self.c_name[fdef.c_name] = fdef
- def define_boxed(self, *args):
- bdef = apply(BoxedDef, args)
- self.boxes.append(bdef)
- self.c_name[bdef.c_name] = bdef
- def define_pointer(self, *args):
- pdef = apply(PointerDef, args)
- self.pointers.append(pdef)
- self.c_name[pdef.c_name] = pdef
- def define_function(self, *args):
- fdef = apply(FunctionDef, args)
- self.functions.append(fdef)
- self.c_name[fdef.c_name] = fdef
- def define_method(self, *args):
- mdef = apply(MethodDef, args)
- self.functions.append(mdef)
- self.c_name[mdef.c_name] = mdef
- def define_virtual(self, *args):
- vdef = apply(VirtualDef, args)
- self.virtuals.append(vdef)
- def merge(self, old, parmerge):
- for obj in self.objects:
- if old.c_name.has_key(obj.c_name):
- obj.merge(old.c_name[obj.c_name])
- for f in self.functions:
- if old.c_name.has_key(f.c_name):
- f.merge(old.c_name[f.c_name], parmerge)
-
- def printMissing(self, old):
- for obj in self.objects:
- if not old.c_name.has_key(obj.c_name):
- obj.write_defs()
- for f in self.functions:
- if not old.c_name.has_key(f.c_name):
- f.write_defs()
-
- def write_defs(self, fp=sys.stdout):
- for obj in self.objects:
- obj.write_defs(fp)
- for enum in self.enums:
- enum.write_defs(fp)
- for boxed in self.boxes:
- boxed.write_defs(fp)
- for pointer in self.pointers:
- pointer.write_defs(fp)
- for func in self.functions:
- func.write_defs(fp)
-
- def find_object(self, c_name):
- for obj in self.objects:
- if obj.c_name == c_name:
- return obj
- else:
- raise ValueError('object %r not found' % c_name)
-
- def find_constructor(self, obj, overrides):
- for func in self.functions:
- if isinstance(func, FunctionDef) and \
- func.is_constructor_of == obj.c_name and \
- not overrides.is_ignored(func.c_name):
- return func
-
- def find_methods(self, obj):
- objname = obj.c_name
- return filter(lambda func, on=objname: isinstance(func, MethodDef) and
- func.of_object == on, self.functions)
-
- def find_virtuals(self, obj):
- objname = obj.c_name
- retval = filter(lambda func, on=objname: isinstance(func, VirtualDef) and
- func.of_object == on, self.virtuals)
- return retval
-
- def find_functions(self):
- return filter(lambda func: isinstance(func, FunctionDef) and
- not func.is_constructor_of, self.functions)
-
- def ifdef(self, *args):
- if args[0] in self.defines:
- for arg in args[1:]:
- #print >> sys.stderr, "-----> Handling conditional definition (%s): %s" % (args[0], arg)
- self.handle(arg)
- else:
- pass
- #print >> sys.stderr, "-----> Conditional %s is not true" % (args[0],)
-
- def ifndef(self, *args):
- if args[0] not in self.defines:
- for arg in args[1:]:
- self.handle(arg)
+from .libcodegen.defsparser import *
diff --git a/codegen/docextract.py b/codegen/docextract.py
deleted file mode 100644
index 06a08a3..0000000
--- a/codegen/docextract.py
+++ /dev/null
@@ -1,448 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-'''Simple module for extracting GNOME style doc comments from C
-sources, so I can use them for other purposes.'''
-
-import sys, os, string, re
-
-__all__ = ['extract']
-
-class GtkDoc:
- def __init__(self):
- self.name = None
- self.block_type = '' # The block type ('function', 'signal', 'property')
- self.params = []
- self.annotations = []
- self.description = ''
- self.ret = ('', []) # (return, annotations)
- def set_name(self, name):
- self.name = name
- def set_type(self, block_type):
- self.block_type = block_type
- def get_type(self):
- return self.block_type
- def add_param(self, name, description, annotations=[]):
- if name == '...':
- name = 'Varargs'
- self.params.append((name, description, annotations))
- def append_to_last_param(self, extra):
- self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra,
- self.params[-1][2])
- def append_to_named_param(self, name, extra):
- for i in range(len(self.params)):
- if self.params[i][0] == name:
- self.params[i] = (name, self.params[i][1] + extra,
- self.params[i][2])
- return
- # fall through to adding extra parameter ...
- self.add_param(name, extra)
- def add_annotation(self, annotation):
- self.annotations.append(annotation)
- def get_annotations(self):
- return self.annotations
- def append_to_description(self, extra):
- self.description = self.description + extra
- def get_description(self):
- return self.description
- def add_return(self, first_line, annotations=[]):
- self.ret = (first_line, annotations)
- def append_to_return(self, extra):
- self.ret = (self.ret[0] + extra, self.ret[1])
-
-comment_start_pattern = re.compile(r'^\s*/\*\*\s')
-comment_end_pattern = re.compile(r'^\s*\*+/')
-comment_line_lead_pattern = re.compile(r'^\s*\*\s*')
-comment_empty_line_pattern = re.compile(r'^\s*\**\s*$')
-function_name_pattern = re.compile(r'^([a-z]\w*)\s*:?(\s*\(.*\)\s*){0,2}\s*$')
-signal_name_pattern = re.compile(r'^([A-Z]\w+::[a-z0-9-]+)\s*:?(\s*\(.*\)\s*){0,2}\s*$')
-property_name_pattern = re.compile(r'^([A-Z]\w+:[a-z0-9-]+)\s*:?(\s*\(.*\)\s*){0,2}\s*$')
-return_pattern = re.compile(r'^@?(returns:|return\s+value:)(.*\n?)$', re.IGNORECASE)
-deprecated_pattern = re.compile(r'^(deprecated\s*:\s*.*\n?)$', re.IGNORECASE)
-rename_to_pattern = re.compile(r'^(rename\s+to)\s*:\s*(.*\n?)$', re.IGNORECASE)
-param_pattern = re.compile(r'^@(\S+)\s*:(.*\n?)$')
-# Used to extract the annotations in the parameter and return descriptions
-# extracted using above [param|return]_pattern patterns.
-annotations_pattern = re.compile(r'^(?:(\s*\(.*\)\s*)*:)')
-# Used to construct the annotation lists.
-annotation_lead_pattern = re.compile(r'^\s*\(\s*(.*?)\s*\)\s*')
-
-# These patterns determine the identifier of the current comment block. They
-# are grouped in a list for easy determination of block identifiers (in
-# skip_to_identifier). The function_name_pattern should be tested for last
-# because it always matches signal and property identifiers.
-identifier_patterns = [ signal_name_pattern, property_name_pattern, function_name_pattern ]
-
-# This pattern is to match return sections that forget to have a colon (':')
-# after the initial 'Return' phrase. It is not included by default in the list
-# of final sections below because a lot of function descriptions begin with
-# 'Returns ...' and the process_description() function would stop right at that
-# first line, thinking it is a return section.
-no_colon_return_pattern = re.compile(r'^@?(returns|return\s+value)\s*(.*\n?)$', re.IGNORECASE)
-since_pattern = re.compile(r'^(since\s*:\s*.*\n?)$', re.IGNORECASE)
-
-# These patterns normally will be encountered after the description. Knowing
-# the order of their appearance is difficult so this list is used to test when
-# one begins and the other ends when processing the rest of the sections after
-# the description.
-final_section_patterns = [ return_pattern, since_pattern, deprecated_pattern, rename_to_pattern ]
-
-def parse_file(fp, doc_dict):
- line = fp.readline()
- while line:
- cur_doc = GtkDoc()
- line = skip_to_comment_block(fp, line)
- line = skip_to_identifier(fp, line, cur_doc)
- # See if the identifier is found (stored in the current GtkDoc by
- # skip_to_identifier). If so, continue reading the rest of the comment
- # block.
- if cur_doc.name:
- line = process_params(fp, line, cur_doc)
- line = process_description(fp, line, cur_doc)
- line = process_final_sections(fp, line, cur_doc)
- # Add the current doc block to the dictionary of doc blocks.
- doc_dict[cur_doc.name] = cur_doc
-
-# Given a list of annotations as string of the form
-# '(annotation1) (annotation2) ...' return a list of annotations of the form
-# [ (name1, value1), (name2, value2) ... ]. Not all annotations have values so
-# the values in the list of tuples could be empty ('').
-def get_annotation_list(annotations):
- annotation_list = []
- while annotations:
- match = annotation_lead_pattern.match(annotations)
- if match:
- annotation_contents = match.group(1)
- name, split, value = annotation_contents.strip().partition(' ')
- annotation_list.append((name, value))
- # Remove first occurrence to continue processing.
- annotations = annotation_lead_pattern.sub('', annotations)
- else:
- break
- return annotation_list
-
-# Given a currently read line, test that line and continue reading until the
-# beginning of a comment block is found or eof is reached. Return the last
-# read line.
-def skip_to_comment_block(fp, line):
- while line:
- if comment_start_pattern.match(line):
- break
- line = fp.readline()
- return line
-
-# Given the current line in a comment block, continue skipping lines until a
-# non-blank line in the comment block is found or until the end of the block
-# (or eof) is reached. Returns the line where reading stopped.
-def skip_to_nonblank(fp, line):
- while line:
- if not comment_empty_line_pattern.match(line):
- break
- line = fp.readline()
- # Stop processing if eof or end of comment block is reached.
- if not line or comment_end_pattern.match(line):
- break
- return line
-
-# Given the first line of a comment block (the '/**'), see if the next
-# non-blank line is the identifier of the comment block. Stop processing if
-# the end of the block or eof is reached. Store the identifier (if there is
-# one) and its type ('function', 'signal' or 'property') in the given GtkDoc.
-# Return the line where the identifier is found or the line that stops the
-# processing (if eof or the end of the comment block is found first).
-def skip_to_identifier(fp, line, cur_doc):
- # Skip the initial comment block line ('/**') if not eof.
- if line: line = fp.readline()
-
- # Now skip empty lines.
- line = skip_to_nonblank(fp, line)
-
- # See if the first non-blank line is the identifier.
- if line and not comment_end_pattern.match(line):
- # Remove the initial ' * ' in comment block line and see if there is an
- # identifier.
- line = comment_line_lead_pattern.sub('', line)
- for pattern in identifier_patterns:
- match = pattern.match(line)
- if match:
- # Set the GtkDoc name.
- cur_doc.set_name(match.group(1))
- # Get annotations and add them to the GtkDoc.
- annotations = get_annotation_list(match.group(2))
- for annotation in annotations:
- cur_doc.add_annotation(annotation)
- # Set the GtkDoc type.
- if pattern == signal_name_pattern:
- cur_doc.set_type('signal')
- elif pattern == property_name_pattern:
- cur_doc.set_type('property')
- elif pattern == function_name_pattern:
- cur_doc.set_type('function')
- return line
- return line
-
-# Given a currently read line (presumably the identifier line), read the next
-# lines, testing to see if the lines are part of parameter descriptions. If
-# so, store the parameter descriptions in the given doc block. Stop on eof and
-# return the last line that stops the processing.
-def process_params(fp, line, cur_doc):
- # Skip the identifier line if not eof. Also skip any blank lines in the
- # comment block. Return if eof or the end of the comment block are
- # encountered.
- if line: line = fp.readline()
- line = skip_to_nonblank(fp, line)
- if not line or comment_end_pattern.match(line):
- return line
-
- # Remove initial ' * ' in first non-empty comment block line.
- line = comment_line_lead_pattern.sub('', line)
-
- # Now process possible parameters as long as no eof or the end of the
- # param section is not reached (which could be triggered by anything that
- # doesn't match a '@param:..." line, even the end of the comment block).
- match = param_pattern.match(line)
- while line and match:
- description = match.group(2)
-
- # First extract the annotations from the description and save them.
- annotations = []
- annotation_match = annotations_pattern.match(description)
- if annotation_match:
- annotations = get_annotation_list(annotation_match.group(1))
- # Remove the annotations from the description
- description = annotations_pattern.sub('', description)
-
- # Default to appending lines to current parameter.
- append_func = cur_doc.append_to_last_param
-
- # See if the return has been included as part of the parameter
- # section and make sure that lines are added to the GtkDoc return if
- # so.
- if match.group(1).lower() == "returns":
- cur_doc.add_return(description, annotations)
- append_func = cur_doc.append_to_return
- # If not, just add it as a regular parameter.
- else:
- cur_doc.add_param(match.group(1), description, annotations)
-
- # Now read lines and append them until next parameter, beginning of
- # description (an empty line), the end of the comment block or eof.
- line = fp.readline()
- while line:
- # Stop processing if end of comment block or a blank comment line
- # is encountered.
- if comment_empty_line_pattern.match(line) or \
- comment_end_pattern.match(line):
- break
-
- # Remove initial ' * ' in comment block line.
- line = comment_line_lead_pattern.sub('', line)
-
- # Break from current param processing if a new one is
- # encountered.
- if param_pattern.match(line): break;
-
- # Otherwise, just append the current line and get the next line.
- append_func(line)
- line = fp.readline()
-
- # Re-evaluate match for while condition
- match = param_pattern.match(line)
-
- # End by returning the current line.
- return line
-
-# Having processed parameters, read the following lines into the description of
-# the current doc block until the end of the comment block, the end of file or
-# a return section is encountered.
-def process_description(fp, line, cur_doc):
- # First skip empty lines returning on eof or end of comment block.
- line = skip_to_nonblank(fp, line)
- if not line or comment_end_pattern.match(line):
- return line
-
- # Remove initial ' * ' in non-empty comment block line.
- line = comment_line_lead_pattern.sub('', line)
-
- # Also remove possible 'Description:' prefix.
- if line[:12] == 'Description:': line = line[12:]
-
- # Used to tell if the previous line was blank and a return section
- # uncommonly marked with 'Returns ...' instead of 'Returns: ...' has
- # started (assume it is non-empty to begin with).
- prev_line = 'non-empty'
-
- # Now read lines until a new section (like a return or a since section) is
- # encountered.
- while line:
- # See if the description section has ended (if the line begins with
- # 'Returns ...' and the previous line was empty -- this loop replaces
- # empty lines with a newline).
- if no_colon_return_pattern.match(line) and prev_line == '\n':
- return line
- # Or if one of the patterns of the final sections match
- for pattern in final_section_patterns:
- if pattern.match(line):
- return line
-
- # If not, append lines to description in the doc comment block.
- cur_doc.append_to_description(line)
-
- prev_line = line
- line = fp.readline()
-
- # Stop processing on eof or at the end of comment block.
- if not line or comment_end_pattern.match(line):
- return line
-
- # Remove initial ' * ' in line so that the text can be appended to the
- # description of the comment block and make sure that if the line is
- # empty it be interpreted as a newline.
- line = comment_line_lead_pattern.sub('', line)
- if not line: line = '\n'
-
-# Given the line that ended the description (the first line of one of the final
-# sections) process the final sections ('Returns:', 'Since:', etc.) until the
-# end of the comment block or eof. Return the line that ends the processing.
-def process_final_sections(fp, line, cur_doc):
- while line and not comment_end_pattern.match(line):
- # Remove leading ' * ' from current non-empty comment line.
- line = comment_line_lead_pattern.sub('', line)
- # Temporarily append the no colon return pattern to the final section
- # patterns now that the description has been processed. It will be
- # removed after the for loop below executes so that future descriptions
- # that begin with 'Returns ...' are not interpreted as a return
- # section.
- final_section_patterns.append(no_colon_return_pattern)
- for pattern in final_section_patterns:
- match = pattern.match(line)
- if match:
- if pattern == return_pattern or \
- pattern == no_colon_return_pattern:
- # Dealing with a 'Returns:' so first extract the
- # annotations from the description and save them.
- description = match.group(2)
- annotations = []
- annotation_match = \
- annotations_pattern.match(description)
- if annotation_match:
- annotations = \
- get_annotation_list(annotation_match.group(1))
- # Remove the annotations from the description
- description = annotations_pattern.sub('', description)
-
- # Now add the return.
- cur_doc.add_return(description, annotations)
- # In case more lines need to be appended.
- append_func = cur_doc.append_to_return
- elif pattern == rename_to_pattern:
- # Dealing with a 'Rename to:' section (GObjectIntrospection
- # annotation) so no further lines will be appended but this
- # single one (and only to the annotations).
- append_func = None
- cur_doc.add_annotation((match.group(1),
- match.group(2)))
- else:
- # For all others ('Since:' and 'Deprecated:') just append
- # the line to the description for now.
- cur_doc.append_to_description(line)
- # In case more lines need to be appended.
- append_func = cur_doc.append_to_description
-
- # Stop final section pattern matching for loop since a match
- # has already been found.
- break
-
- # Remove the no colon return pattern (which was temporarily added in
- # the just executed loop) from the list of final section patterns.
- final_section_patterns.pop()
-
- line = fp.readline()
-
- # Now continue appending lines to current section until a new one is
- # found or an eof or the end of the comment block is encountered.
- finished = False
- while not finished and line and \
- not comment_end_pattern.match(line):
- # Remove leading ' * ' from line and make sure that if it is empty,
- # it be interpreted as a newline.
- line = comment_line_lead_pattern.sub('', line)
- if not line: line = '\n'
-
- for pattern in final_section_patterns:
- if pattern.match(line):
- finished = True
- break
-
- # Break out of loop if a new section is found (determined in above
- # inner loop).
- if finished: break
-
- # Now it's safe to append line.
- if append_func: append_func(line)
-
- # Get the next line to continue processing.
- line = fp.readline()
-
- return line
-
-def parse_dir(dir, doc_dict):
- for file in os.listdir(dir):
- if file in ('.', '..'): continue
- path = os.path.join(dir, file)
- if os.path.isdir(path):
- parse_dir(path, doc_dict)
- if len(file) > 2 and file[-2:] == '.c':
- sys.stderr.write("Processing " + path + '\n')
- parse_file(open(path, 'r'), doc_dict)
-
-def extract(dirs, doc_dict=None):
- if not doc_dict: doc_dict = {}
- for dir in dirs:
- parse_dir(dir, doc_dict)
- return doc_dict
-
-tmpl_section_pattern = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$')
-def parse_tmpl(fp, doc_dict):
- cur_doc = None
-
- line = fp.readline()
- while line:
- match = tmpl_section_pattern.match(line)
- if match:
- cur_doc = None # new input shouldn't affect the old doc dict
- sect_type = match.group(1)
- sect_name = match.group(2)
-
- if sect_type == 'FUNCTION':
- cur_doc = doc_dict.get(sect_name)
- if not cur_doc:
- cur_doc = GtkDoc()
- cur_doc.set_name(sect_name)
- doc_dict[sect_name] = cur_doc
- elif line == '<!-- # Unused Parameters # -->\n':
- cur_doc = None # don't worry about unused params.
- elif cur_doc:
- if line[:10] == '@Returns: ':
- if line[10:].strip():
- cur_doc.append_to_return(line[10:])
- elif line[0] == '@':
- pos = line.find(':')
- if pos >= 0:
- cur_doc.append_to_named_param(line[1:pos], line[pos+1:])
- else:
- cur_doc.append_to_description(line)
- else:
- cur_doc.append_to_description(line)
-
- line = fp.readline()
-
-def extract_tmpl(dirs, doc_dict=None):
- if not doc_dict: doc_dict = {}
- for dir in dirs:
- for file in os.listdir(dir):
- if file in ('.', '..'): continue
- path = os.path.join(dir, file)
- if os.path.isdir(path):
- continue
- if len(file) > 2 and file[-2:] == '.sgml':
- parse_tmpl(open(path, 'r'), doc_dict)
- return doc_dict
diff --git a/codegen/docextract_to_xml.py b/codegen/docextract_to_xml.py
index 775b57d..f8d3bae 100755
--- a/codegen/docextract_to_xml.py
+++ b/codegen/docextract_to_xml.py
@@ -13,18 +13,6 @@ import sys
import docextract
-def usage():
- sys.stderr.write('usage: docextract_to_xml.py ' +
- '[-s /src/dir | --source-dir=/src/dir] ' +
- '[-a | --with-annotations] [-p | --with-properties] ' +
- '[-i | --with-signals ]\n')
- sys.exit(1)
-
-# Translates special texts to &... HTML acceptable format. Also replace
-# occurrences of '/*' and '*/' with '/ *' and '* /' respectively to avoid
-# comment errors (note the spaces). Some function descriptions include C++
-# multi-line comments which cause errors when the description is included in a
-# C++ Doxygen comment block.
def escape_text(unescaped_text):
# Escape every "&" not part of an entity reference
escaped_text = re.sub(r'&(?![A-Za-z]+;)', '&amp;', unescaped_text)
@@ -34,51 +22,31 @@ def escape_text(unescaped_text):
escaped_text = string.replace(escaped_text, '&ast;', '*')
escaped_text = string.replace(escaped_text, '&percnt;', '%')
escaped_text = string.replace(escaped_text, '&commat;', '@')
- escaped_text = string.replace(escaped_text, '&num;', '')
- escaped_text = string.replace(escaped_text, '&nbsp;', ' ')
- # This represents a '/' before or after an '*' so replace with slash but
- # with spaces.
- escaped_text = string.replace(escaped_text, '&sol;', ' / ')
# Escape for both tag contents and attribute values
escaped_text = string.replace(escaped_text, '<', '&lt;')
escaped_text = string.replace(escaped_text, '>', '&gt;')
escaped_text = string.replace(escaped_text, '"', '&quot;')
- # Replace C++ comment begin and ends to ones that don't affect Doxygen.
- escaped_text = string.replace(escaped_text, '/*', '/ *')
- escaped_text = string.replace(escaped_text, '*/', '* /')
-
return escaped_text
-def print_annotations(annotations):
- for annotation in annotations:
- print "<annotation name=" + annotation[0] + ">" + \
- escape_text(annotation[1]) + "</annotation>"
-
if __name__ == '__main__':
try:
- opts, args = getopt.getopt(sys.argv[1:], "d:s:o:api",
- ["source-dir=", "with-annotations",
- "with-properties", "with-signals"])
+ opts, args = getopt.getopt(sys.argv[1:], "d:s:o:",
+ ["source-dir="])
except getopt.error, e:
- sys.stderr.write('docextract_to_xml.py: %s\n' % e)
- usage()
+ sys.stderr.write('docgen.py: %s\n' % e)
+ sys.stderr.write(
+ 'usage: docgen.py [-s /src/dir]\n')
+ sys.exit(1)
source_dirs = []
- with_annotations = False
- with_signals = False
- with_properties = False
for opt, arg in opts:
if opt in ('-s', '--source-dir'):
source_dirs.append(arg)
- if opt in ('-a', '--with-annotations'):
- with_annotations = True
- if opt in ('-p', '--with-properties'):
- with_properties = True
- if opt in ('-i', '--with-signals'):
- with_signals = True
if len(args) != 0:
- usage()
+ sys.stderr.write(
+ 'usage: docgen.py [-s /src/dir]\n')
+ sys.exit(1)
docs = docextract.extract(source_dirs);
docextract.extract_tmpl(source_dirs, docs); #Try the tmpl sgml files too.
@@ -90,50 +58,25 @@ if __name__ == '__main__':
print "<root>"
for name, value in docs.items():
- # Get the type of comment block ('function', 'signal' or
- # 'property') (the value is a GtkDoc).
- block_type = value.get_type()
-
- # Skip signals if the option was not specified.
- if block_type == 'signal' and not with_signals:
- continue
- # Likewise for properties.
- elif block_type == 'property' and not with_properties:
- continue
-
- print "<" + block_type + " name=\"" + escape_text(name) + "\">"
+ print "<function name=\"" + escape_text(name) + "\">"
print "<description>"
- print escape_text(value.get_description())
+ #The value is a docextract.FunctionDoc
+ print escape_text(value.description)
print "</description>"
- # Loop through the parameters if not dealing with a property:
- if block_type != 'property':
- print "<parameters>"
- for name, description, annotations in value.params:
- print "<parameter name=\"" + escape_text(name) + "\">"
- print "<parameter_description>" + escape_text(description) + "</parameter_description>"
-
- if with_annotations:
- print_annotations(annotations)
-
- print "</parameter>"
-
- print "</parameters>"
+ # Loop through the parameters:
+ print "<parameters>"
+ for name, description in value.params:
+ print "<parameter name=\"" + escape_text(name) + "\">"
+ print "<parameter_description>" + escape_text(description) + "</parameter_description>"
+ print "</parameter>"
- # Show the return-type (also if not dealing with a property):
- if with_annotations:
- print "<return>"
- print "<return_description>" + escape_text(value.ret[0]) + \
- "</return_description>"
- print_annotations(value.ret[1])
- print "</return>"
- else:
- print "<return>" + escape_text(value.ret[0]) + "</return>"
+ print "</parameters>"
- if with_annotations:
- print_annotations(value.get_annotations())
+ # Show the return-type:
+ print "<return>" + escape_text(value.ret) + "</return>"
- print "</" + block_type + ">\n"
+ print "</function>\n"
print "</root>"
diff --git a/codegen/libcodegen/__init__.py b/codegen/libcodegen/__init__.py
new file mode 100644
index 0000000..86188f9
--- /dev/null
+++ b/codegen/libcodegen/__init__.py
@@ -0,0 +1,16 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+
+__all__ = [
+ 'argtypes',
+ 'codegen',
+ 'definitions',
+ 'defsparser',
+ 'docextract',
+ 'docgen',
+ 'h2def',
+ 'defsgen'
+ 'mergedefs',
+ 'mkskel',
+ 'override',
+ 'scmexpr'
+]
diff --git a/codegen/argtypes.py b/codegen/libcodegen/argtypes.py
index b35f6ef..c8252bb 100644
--- a/codegen/argtypes.py
+++ b/codegen/libcodegen/argtypes.py
@@ -1,5 +1,4 @@
# -*- Mode: Python; py-indent-offset: 4 -*-
-import string
import keyword
import struct
@@ -20,7 +19,7 @@ class VarList:
def __init__(self):
self.vars = {}
def add(self, ctype, name):
- if self.vars.has_key(ctype):
+ if ctype in self.vars:
self.vars[ctype] = self.vars[ctype] + (name,)
else:
self.vars[ctype] = (name,)
@@ -30,11 +29,11 @@ class VarList:
ret.append(' ')
ret.append(type)
ret.append(' ')
- ret.append(string.join(self.vars[type], ', '))
+ ret.append(', '.join(self.vars[type]))
ret.append(';\n')
if ret:
ret.append('\n')
- return string.join(ret, '')
+ return ''.join(ret)
return ''
class WrapperInfo:
@@ -50,18 +49,18 @@ class WrapperInfo:
self.arglist = []
self.kwlist = []
def get_parselist(self):
- return string.join(self.parselist, ', ')
+ return ', '.join(self.parselist)
def get_codebefore(self):
- return string.join(self.codebefore, '')
+ return ''.join(self.codebefore)
def get_codeafter(self):
- return string.join(self.codeafter, '')
+ return ''.join(self.codeafter)
def get_arglist(self):
- return string.join(self.arglist, ', ')
+ return ', '.join(self.arglist)
def get_varlist(self):
return str(self.varlist)
def get_kwlist(self):
ret = ' static char *kwlist[] = { %s };\n' % \
- string.join(self.kwlist + [ 'NULL' ], ', ')
+ ', '.join(self.kwlist + [ 'NULL' ])
if not self.get_varlist():
ret = ret + '\n'
return ret
@@ -79,14 +78,14 @@ class ArgType:
def write_param(self, ptype, pname, pdflt, pnull, info):
"""Add code to the WrapperInfo instance to handle
parameter."""
- raise RuntimeError, "write_param not implemented for %s" % \
- self.__class__.__name__
+ raise RuntimeError("write_param not implemented for %s" % \
+ self.__class__.__name__)
def write_return(self, ptype, ownsreturn, info):
"""Adds a variable named ret of the return type to
info.varlist, and add any required code to info.codeafter to
convert the return value to a python object."""
- raise RuntimeError, "write_return not implemented for %s" % \
- self.__class__.__name__
+ raise RuntimeError("write_return not implemented for %s" % \
+ self.__class__.__name__)
class NoneArg(ArgType):
def write_return(self, ptype, ownsreturn, info):
@@ -110,7 +109,7 @@ class StringArg(ArgType):
# have to free result ...
info.varlist.add('gchar', '*ret')
info.codeafter.append(' if (ret) {\n' +
- ' PyObject *py_ret = PyString_FromString(ret);\n' +
+ ' PyObject *py_ret = _PyUnicode_FromString(ret);\n' +
' g_free(ret);\n' +
' return py_ret;\n' +
' }\n' +
@@ -119,7 +118,7 @@ class StringArg(ArgType):
else:
info.varlist.add('const gchar', '*ret')
info.codeafter.append(' if (ret)\n' +
- ' return PyString_FromString(ret);\n'+
+ ' return _PyUnicode_FromString(ret);\n'+
' Py_INCREF(Py_None);\n' +
' return Py_None;')
@@ -152,7 +151,7 @@ class CharArg(ArgType):
info.add_parselist('c', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add('gchar', 'ret')
- info.codeafter.append(' return PyString_FromStringAndSize(&ret, 1);')
+ info.codeafter.append(' return _PyUnicode_FromStringAndSize(&ret, 1);')
class GUniCharArg(ArgType):
ret_tmpl = ('#if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2\n'
' if (ret > 0xffff) {\n'
@@ -185,14 +184,14 @@ class IntArg(ArgType):
info.add_parselist('i', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add('int', 'ret')
- info.codeafter.append(' return PyInt_FromLong(ret);')
+ info.codeafter.append(' return _PyLong_FromLong(ret);')
class UIntArg(ArgType):
dflt = (' if (py_%(name)s) {\n'
' if (PyLong_Check(py_%(name)s))\n'
' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
- ' else if (PyInt_Check(py_%(name)s))\n'
- ' %(name)s = PyInt_AsLong(py_%(name)s);\n'
+ ' else if (_PyLong_Check(py_%(name)s))\n'
+ ' %(name)s = _PyLong_AsLong(py_%(name)s);\n'
' else\n'
' PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
' if (PyErr_Occurred())\n'
@@ -200,8 +199,8 @@ class UIntArg(ArgType):
' }\n')
before = (' if (PyLong_Check(py_%(name)s))\n'
' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
- ' else if (PyInt_Check(py_%(name)s))\n'
- ' %(name)s = PyInt_AsLong(py_%(name)s);\n'
+ ' else if (_PyLong_Check(py_%(name)s))\n'
+ ' %(name)s = _PyLong_AsLong(py_%(name)s);\n'
' else\n'
' PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
' if (PyErr_Occurred())\n'
@@ -277,7 +276,7 @@ class LongArg(ArgType):
info.add_parselist('l', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add(ptype, 'ret')
- info.codeafter.append(' return PyInt_FromLong(ret);\n')
+ info.codeafter.append(' return _PyLong_FromLong(ret);\n')
class BoolArg(IntArg):
def write_return(self, ptype, ownsreturn, info):
@@ -294,7 +293,7 @@ class TimeTArg(ArgType):
info.add_parselist('i', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add('time_t', 'ret')
- info.codeafter.append(' return PyInt_FromLong(ret);')
+ info.codeafter.append(' return _PyLong_FromLong(ret);')
class ULongArg(ArgType):
def write_param(self, ptype, pname, pdflt, pnull, info):
@@ -475,7 +474,7 @@ class ObjectArg(ArgType):
' %(name)s = %(cast)s(py_%(name)s->obj);\n'
def __init__(self, objname, parent, typecode):
self.objname = objname
- self.cast = string.replace(typecode, '_TYPE_', '_', 1)
+ self.cast = typecode.replace('_TYPE_', '_', 1)
self.parent = parent
def write_param(self, ptype, pname, pdflt, pnull, info):
if pnull:
@@ -695,7 +694,7 @@ class AtomArg(IntArg):
info.varlist.add('PyObject *', 'py_ret')
info.varlist.add('gchar *', 'name')
info.codeafter.append(' name = gdk_atom_name(ret);\n'
- ' py_ret = PyString_FromString(name);\n'
+ ' py_ret = _PyUnicode_FromString(name);\n'
' g_free(name);\n'
' return py_ret;')
@@ -867,7 +866,7 @@ class ArgMatcher:
self.register('GdkBitmap', oa)
self.register('GdkBitmap*', oa)
def register_boxed(self, ptype, typecode):
- if self.argtypes.has_key(ptype): return
+ if ptype in self.argtypes: return
arg = BoxedArg(ptype, typecode)
self.register(ptype, arg)
self.register(ptype+'*', arg)
@@ -934,7 +933,7 @@ class ArgMatcher:
def object_is_a(self, otype, parent):
if otype == None: return 0
if otype == parent: return 1
- if not self.argtypes.has_key(otype): return 0
+ if otype not in self.argtypes: return 0
return self.object_is_a(self.get(otype).parent, parent)
matcher = ArgMatcher()
diff --git a/codegen/libcodegen/codegen.py b/codegen/libcodegen/codegen.py
new file mode 100644
index 0000000..538a68c
--- /dev/null
+++ b/codegen/libcodegen/codegen.py
@@ -0,0 +1,1722 @@
+
+import getopt
+import keyword
+import os
+import string
+import sys
+
+from . import argtypes
+from . import definitions
+from . import defsparser
+from . import override
+from . 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)'
+ ' "%(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", '
+ 'Py_TYPE(self)->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 self.objinfo.typecode.replace('_TYPE_', '_', 1).lower()
+
+ 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 'tp_flags' not in substdict:
+ 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 slot not in substdict:
+ 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 + (
+ info.get_codebefore().replace(
+ 'return NULL', 'return ' + substdict['errorreturn'])
+ )
+ substdict['codeafter'] = (
+ info.get_codeafter().replace(
+ '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.exc_info()[1]
+ 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'] = parent.typecode.replace('_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 = sys.exc_info()[1]
+ 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 = sys.exc_info()[1]
+ 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(''.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 = sys.exc_info()[1]
+ 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 = sys.exc_info()[1]
+ 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 code.find(getterprefix + fname) >= 0:
+ gettername = getterprefix + fname
+ if code.find(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.exc_info()[1]
+ 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, '
+ '_PyUnicode_FromString("%s"));\n' % (obj.name))
+
+ for name, cname, flags, docstring in functions:
+ self.fp.write(' PyList_Append(pylist, '
+ '_PyUnicode_FromString("%s"));\n' % (name))
+
+ for enum in writer.get_enums():
+ self.fp.write(' PyList_Append(pylist, '
+ '_PyUnicode_FromString("%s"));\n' % (enum.name))
+ for nick, value in enum.values:
+ name = value[len(self.overrides.modulename)+1:]
+ self.fp.write(' PyList_Append(pylist, '
+ '_PyUnicode_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 = _PyUnicode_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 = sys.exc_info()[1]
+ 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 = sys.exc_info()[1]
+ 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(''.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 = self.objinfo.typecode.replace(
+ '_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 = self.objinfo.typecode.replace('_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'] = self.objinfo.typecode.replace(
+ '_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
+ out.write("static int\n")
+ out.write('_wrap_%s(PyGObject *self, PyObject *args,' \
+ ' PyObject *kwargs)\n{\n\n' % constructor.c_name)
+ if constructor.params:
+ s = " GType obj_type = pyg_type_from_object((PyObject *) self);\n"
+ out.write(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])
+
+ out.write(" GParameter params[%i];\n" % \
+ len(constructor.params))
+ out.write(" PyObject *parsed_args[%i] = {NULL, };\n" % \
+ len(constructor.params))
+ out.write(" char *arg_names[] = %s;\n" % arg_names)
+ out.write(" char *prop_names[] = %s;\n" % prop_names)
+ out.write(" guint nparams, i;\n\n")
+ if constructor.deprecated is not None:
+ out.write(
+ ' if (PyErr_Warn(PyExc_DeprecationWarning, '
+ '"%s") < 0)\n' %
+ constructor.deprecated)
+ out.write(' return -1;\n\n')
+ out.write(" if (!PyArg_ParseTupleAndKeywords(args, kwargs, \n")
+ template = '"'
+ if mandatory_arguments:
+ template += "O"*len(mandatory_arguments)
+ if optional_arguments:
+ template += "|" + "O"*len(optional_arguments)
+ template += ':%s.__init__"' % classname
+ out.write(template + " , arg_names")
+ for i in range(len(constructor.params)):
+ out.write(", &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\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:
+ out.write(" g_object_ref(self->obj);\n\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 = sys.exc_info()[1]
+ 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:
+ sys.stderr.write(
+ "Warning: Constructor for %s needs to be updated to new API\n"
+ " See http://live.gnome.org/PyGTK_2fWhatsNew28"
+ "#update-constructors\n" % 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)
+
+ functions_coverage.printstats()
+ methods_coverage.printstats()
+ vproxies_coverage.printstats()
+ vaccessors_coverage.printstats()
+ iproxies_coverage.printstats()
+
diff --git a/codegen/definitions.py b/codegen/libcodegen/definitions.py
index aca5adb..bab0ecb 100644
--- a/codegen/definitions.py
+++ b/codegen/libcodegen/definitions.py
@@ -71,15 +71,15 @@ class Definition(object):
def __init__(self, *args):
"""Create a new defs object of this type. The arguments are the
components of the definition"""
- raise RuntimeError, "this is an abstract class"
+ raise RuntimeError("this is an abstract class")
def merge(self, old):
"""Merge in customisations from older version of definition"""
- raise RuntimeError, "this is an abstract class"
+ raise RuntimeError("this is an abstract class")
def write_defs(self, fp=sys.stdout):
"""write out this definition in defs file format"""
- raise RuntimeError, "this is an abstract class"
+ raise RuntimeError("this is an abstract class")
def guess_return_value_ownership(self):
"return 1 if caller owns return value"
@@ -210,7 +210,7 @@ class EnumDef(Definition):
class FlagsDef(EnumDef):
def __init__(self, *args):
- apply(EnumDef.__init__, (self,) + args)
+ EnumDef.__init__(self, *args)
self.deftype = 'flags'
class BoxedDef(Definition):
@@ -407,7 +407,7 @@ class MethodDef(MethodDefBase):
for item in ('c_name', 'of_object'):
if self.__dict__[item] == None:
self.write_defs(sys.stderr)
- raise RuntimeError, "definition missing required %s" % (item,)
+ raise RuntimeError("definition missing required %s" % (item,))
def write_defs(self, fp=sys.stdout):
fp.write('(define-method ' + self.name + '\n')
@@ -491,7 +491,7 @@ class FunctionDef(Definition):
for item in ('c_name',):
if self.__dict__[item] == None:
self.write_defs(sys.stderr)
- raise RuntimeError, "definition missing required %s" % (item,)
+ raise RuntimeError("definition missing required %s" % (item,))
_method_write_defs = MethodDef.__dict__['write_defs']
@@ -513,8 +513,8 @@ class FunctionDef(Definition):
else:
param.merge(old_param)
return param
- raise RuntimeError, "could not find %s in old_parameters %r" % (
- param.pname, [p.pname for p in old.params])
+ raise RuntimeError("could not find %s in old_parameters %r" % (
+ param.pname, [p.pname for p in old.params]))
try:
self.params = map(merge_param, self.params)
except RuntimeError:
diff --git a/codegen/libcodegen/defsparser.py b/codegen/libcodegen/defsparser.py
new file mode 100644
index 0000000..b901f31
--- /dev/null
+++ b/codegen/libcodegen/defsparser.py
@@ -0,0 +1,153 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+import os, sys
+from . import scmexpr
+from .definitions import BoxedDef, EnumDef, FlagsDef, FunctionDef, \
+ InterfaceDef, MethodDef, ObjectDef, PointerDef, VirtualDef
+
+include_path = ['.']
+
+class IncludeParser(scmexpr.Parser):
+ """A simple parser that follows include statements automatically"""
+ def include(self, input_filename):
+ global include_path
+ if os.path.isabs(input_filename):
+ filename = input_filename
+ # set self.filename to the include name, to handle recursive includes
+ oldfile = self.filename
+ self.filename = filename
+ self.startParsing()
+ self.filename = oldfile
+ else:
+ inc_path = [os.path.dirname(self.filename)] + include_path
+ for filename in [os.path.join(path_entry, input_filename)
+ for path_entry in inc_path]:
+ if not os.path.exists(filename):
+ continue
+ # set self.filename to the include name, to handle recursive includes
+ oldfile = self.filename
+ self.filename = filename
+ self.startParsing()
+ self.filename = oldfile
+ break
+ else:
+ raise IOError("%s not found in include path %s" % (input_filename, inc_path))
+
+class DefsParser(IncludeParser):
+ def __init__(self, arg, defines={}):
+ IncludeParser.__init__(self, arg)
+ self.objects = []
+ self.interfaces = []
+ self.enums = [] # enums and flags
+ self.boxes = [] # boxed types
+ self.pointers = [] # pointer types
+ self.functions = [] # functions and methods
+ self.virtuals = [] # virtual methods
+ self.c_name = {} # hash of c names of functions
+ self.methods = {} # hash of methods of particular objects
+ self.defines = defines # -Dfoo=bar options, as dictionary
+
+ def define_object(self, *args):
+ odef = ObjectDef(*args)
+ self.objects.append(odef)
+ self.c_name[odef.c_name] = odef
+ def define_interface(self, *args):
+ idef = InterfaceDef(*args)
+ self.interfaces.append(idef)
+ self.c_name[idef.c_name] = idef
+ def define_enum(self, *args):
+ edef = EnumDef(*args)
+ self.enums.append(edef)
+ self.c_name[edef.c_name] = edef
+ def define_flags(self, *args):
+ fdef = FlagsDef(*args)
+ self.enums.append(fdef)
+ self.c_name[fdef.c_name] = fdef
+ def define_boxed(self, *args):
+ bdef = BoxedDef(*args)
+ self.boxes.append(bdef)
+ self.c_name[bdef.c_name] = bdef
+ def define_pointer(self, *args):
+ pdef = PointerDef(*args)
+ self.pointers.append(pdef)
+ self.c_name[pdef.c_name] = pdef
+ def define_function(self, *args):
+ fdef = FunctionDef(*args)
+ self.functions.append(fdef)
+ self.c_name[fdef.c_name] = fdef
+ def define_method(self, *args):
+ mdef = MethodDef(*args)
+ self.functions.append(mdef)
+ self.c_name[mdef.c_name] = mdef
+ def define_virtual(self, *args):
+ vdef = VirtualDef(*args)
+ self.virtuals.append(vdef)
+ def merge(self, old, parmerge):
+ for obj in self.objects:
+ if obj.c_name in old.c_name:
+ obj.merge(old.c_name[obj.c_name])
+ for f in self.functions:
+ if f.c_name in old.c_name:
+ f.merge(old.c_name[f.c_name], parmerge)
+
+ def printMissing(self, old):
+ for obj in self.objects:
+ if obj.c_name not in old.c_name:
+ obj.write_defs()
+ for f in self.functions:
+ if f.c_name not in old.c_name:
+ f.write_defs()
+
+ def write_defs(self, fp=sys.stdout):
+ for obj in self.objects:
+ obj.write_defs(fp)
+ for enum in self.enums:
+ enum.write_defs(fp)
+ for boxed in self.boxes:
+ boxed.write_defs(fp)
+ for pointer in self.pointers:
+ pointer.write_defs(fp)
+ for func in self.functions:
+ func.write_defs(fp)
+
+ def find_object(self, c_name):
+ for obj in self.objects:
+ if obj.c_name == c_name:
+ return obj
+ else:
+ raise ValueError('object %r not found' % c_name)
+
+ def find_constructor(self, obj, overrides):
+ for func in self.functions:
+ if isinstance(func, FunctionDef) and \
+ func.is_constructor_of == obj.c_name and \
+ not overrides.is_ignored(func.c_name):
+ return func
+
+ def find_methods(self, obj):
+ objname = obj.c_name
+ return filter(lambda func, on=objname: isinstance(func, MethodDef) and
+ func.of_object == on, self.functions)
+
+ def find_virtuals(self, obj):
+ objname = obj.c_name
+ retval = filter(lambda func, on=objname: isinstance(func, VirtualDef) and
+ func.of_object == on, self.virtuals)
+ return retval
+
+ def find_functions(self):
+ return filter(lambda func: isinstance(func, FunctionDef) and
+ not func.is_constructor_of, self.functions)
+
+ def ifdef(self, *args):
+ if args[0] in self.defines:
+ for arg in args[1:]:
+ #print >> sys.stderr, "-----> Handling conditional definition (%s): %s" % (args[0], arg)
+ self.handle(arg)
+ else:
+ pass
+ #print >> sys.stderr, "-----> Conditional %s is not true" % (args[0],)
+
+ def ifndef(self, *args):
+ if args[0] not in self.defines:
+ for arg in args[1:]:
+ self.handle(arg)
diff --git a/codegen/libcodegen/docextract.py b/codegen/libcodegen/docextract.py
new file mode 100644
index 0000000..027afbc
--- /dev/null
+++ b/codegen/libcodegen/docextract.py
@@ -0,0 +1,185 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+'''Simple module for extracting GNOME style doc comments from C
+sources, so I can use them for other purposes.'''
+
+import sys, os, string, re
+
+__all__ = ['extract']
+
+class FunctionDoc:
+ def __init__(self):
+ self.name = None
+ self.params = []
+ self.description = ''
+ self.ret = ''
+ def set_name(self, name):
+ self.name = name
+ def add_param(self, name, description):
+ if name == '...':
+ name = 'Varargs'
+ self.params.append((name, description))
+ def append_to_last_param(self, extra):
+ self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra)
+ def append_to_named_param(self, name, extra):
+ for i in range(len(self.params)):
+ if self.params[i][0] == name:
+ self.params[i] = (name, self.params[i][1] + extra)
+ return
+ # fall through to adding extra parameter ...
+ self.add_param(name, extra)
+ def append_description(self, extra):
+ self.description = self.description + extra
+ def append_return(self, extra):
+ self.ret = self.ret + extra
+
+ def get_param_description(self, name):
+ for param, description in self.params:
+ if param == name:
+ return description
+ else:
+ return ''
+
+comment_start_pat = re.compile(r'^\s*/\*\*\s')
+comment_end_pat = re.compile(r'^\s*\*+/')
+comment_line_lead = re.compile(r'^\s*\*\s*')
+funcname_pat = re.compile(r'^(\w+)\s*:?')
+return_pat = re.compile(r'^(returns:|return\s+value:|returns\s*)(.*\n?)$',
+ re.IGNORECASE)
+param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$')
+
+def parse_file(fp, doc_dict):
+ line = fp.readline()
+ in_comment_block = 0
+ while line:
+ if not in_comment_block:
+ if comment_start_pat.match(line):
+ in_comment_block = 1
+ cur_doc = FunctionDoc()
+ in_description = 0
+ in_return = 0
+ line = fp.readline()
+ continue
+
+ # we are inside a comment block ...
+ if comment_end_pat.match(line):
+ if not cur_doc.name:
+ sys.stderr.write("no function name found in doc comment\n")
+ else:
+ doc_dict[cur_doc.name] = cur_doc
+ in_comment_block = 0
+ line = fp.readline()
+ continue
+
+ # inside a comment block, and not the end of the block ...
+ line = comment_line_lead.sub('', line)
+ if not line: line = '\n'
+
+ if not cur_doc.name:
+ match = funcname_pat.match(line)
+ if match:
+ cur_doc.set_name(match.group(1))
+ elif in_return:
+ match = return_pat.match(line)
+ if match:
+ # assume the last return statement was really part of the
+ # description
+ return_start = match.group(1)
+ cur_doc.ret = match.group(2)
+ cur_doc.description = cur_doc.description + return_start + \
+ cur_doc.ret
+ else:
+ cur_doc.append_return(line)
+ elif in_description:
+ if line[:12] == 'Description:':
+ line = line[12:]
+ match = return_pat.match(line)
+ if match:
+ in_return = 1
+ return_start = match.group(1)
+ cur_doc.append_return(match.group(2))
+ else:
+ cur_doc.append_description(line)
+ elif line == '\n':
+ # end of parameters
+ in_description = 1
+ else:
+ match = param_pat.match(line)
+ if match:
+ param = match.group(1)
+ desc = match.group(2)
+ if param == 'returns':
+ cur_doc.ret = desc
+ else:
+ cur_doc.add_param(param, desc)
+ else:
+ # must be continuation
+ try:
+ if param == 'returns':
+ cur_doc.append_return(line)
+ else:
+ cur_doc.append_to_last_param(line)
+ except:
+ sys.stderr.write('something weird while reading param\n')
+ line = fp.readline()
+
+def parse_dir(dir, doc_dict):
+ for file in os.listdir(dir):
+ if file in ('.', '..'): continue
+ path = os.path.join(dir, file)
+ if os.path.isdir(path):
+ parse_dir(path, doc_dict)
+ if len(file) > 2 and file[-2:] == '.c':
+ parse_file(open(path, 'r'), doc_dict)
+
+def extract(dirs, doc_dict=None):
+ if not doc_dict: doc_dict = {}
+ for dir in dirs:
+ parse_dir(dir, doc_dict)
+ return doc_dict
+
+tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$')
+def parse_tmpl(fp, doc_dict):
+ cur_doc = None
+
+ line = fp.readline()
+ while line:
+ match = tmpl_section_pat.match(line)
+ if match:
+ cur_doc = None # new input shouldn't affect the old doc dict
+ sect_type = match.group(1)
+ sect_name = match.group(2)
+
+ if sect_type == 'FUNCTION':
+ cur_doc = doc_dict.get(sect_name)
+ if not cur_doc:
+ cur_doc = FunctionDoc()
+ cur_doc.set_name(sect_name)
+ doc_dict[sect_name] = cur_doc
+ elif line == '<!-- # Unused Parameters # -->\n':
+ cur_doc = None # don't worry about unused params.
+ elif cur_doc:
+ if line[:10] == '@Returns: ':
+ if line[10:].strip():
+ cur_doc.append_return(line[10:])
+ elif line[0] == '@':
+ pos = line.find(':')
+ if pos >= 0:
+ cur_doc.append_to_named_param(line[1:pos], line[pos+1:])
+ else:
+ cur_doc.append_description(line)
+ else:
+ cur_doc.append_description(line)
+
+ line = fp.readline()
+
+def extract_tmpl(dirs, doc_dict=None):
+ if not doc_dict: doc_dict = {}
+ for dir in dirs:
+ for file in os.listdir(dir):
+ if file in ('.', '..'): continue
+ path = os.path.join(dir, file)
+ if os.path.isdir(path):
+ continue
+ if len(file) > 2 and file[-2:] == '.sgml':
+ parse_tmpl(open(path, 'r'), doc_dict)
+ return doc_dict
diff --git a/codegen/libcodegen/override.py b/codegen/libcodegen/override.py
new file mode 100644
index 0000000..5caa893
--- /dev/null
+++ b/codegen/libcodegen/override.py
@@ -0,0 +1,285 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+
+# this file contains code for loading up an override file. The override file
+# provides implementations of functions where the code generator could not
+# do its job correctly.
+
+import fnmatch
+import os
+import re
+import string
+import sys
+
+def class2cname(klass, method):
+ c_name = ''
+ for c in klass:
+ if c.isupper():
+ c_name += '_' + c.lower()
+ else:
+ c_name += c
+ return c_name[1:] + '_' + method
+
+# import python_type as c_name [for arg_type]
+# Last ('for') clause is optional. If present, the type will be
+# imported only if given 'arg_type' is registered.
+import_pat = re.compile(r'\s*import\s+(\S+)\.([^\s.]+)\s+as\s+(\S+)(\s+for\s+(\S+))?')
+
+class Overrides:
+ def __init__(self, filename=None):
+ self.modulename = None
+ self.ignores = {}
+ self.glob_ignores = []
+ self.type_ignores = {}
+ self.overrides = {}
+ self.overridden = {}
+ self.kwargs = {}
+ self.noargs = {}
+ self.onearg = {}
+ self.staticmethod = {}
+ self.classmethod = {}
+ self.startlines = {}
+ self.override_attrs = {}
+ self.override_slots = {}
+ self.headers = ''
+ self.body = ''
+ self.init = ''
+ self.imports = []
+ self.defines = {}
+ self.functions = {}
+ self.newstyle_constructors = {}
+ self.dynamicnamespace = False
+ if filename:
+ self.handle_file(filename)
+
+ def handle_file(self, filename):
+ oldpath = os.getcwd()
+
+ fp = open(filename, 'r')
+ dirname = os.path.dirname(os.path.abspath(filename))
+
+ if dirname != oldpath:
+ os.chdir(dirname)
+
+ # read all the components of the file ...
+ bufs = []
+ startline = 1
+ lines = []
+ line = fp.readline()
+ linenum = 1
+ while line:
+ if line == '%%\n' or line == '%%':
+ if lines:
+ bufs.append((''.join(lines), startline))
+ startline = linenum + 1
+ lines = []
+ else:
+ lines.append(line)
+ line = fp.readline()
+ linenum = linenum + 1
+ if lines:
+ bufs.append((''.join(lines), startline))
+ if not bufs: return
+
+ for buf, startline in bufs:
+ self.__parse_override(buf, startline, filename)
+
+ os.chdir(oldpath)
+
+ def __parse_override(self, buffer, startline, filename):
+ pos = buffer.find('\n')
+ if pos >= 0:
+ line = buffer[:pos]
+ rest = buffer[pos+1:]
+ else:
+ line = buffer ; rest = ''
+ words = line.split()
+ command = words[0]
+ if (command == 'ignore' or
+ command == 'ignore-' + sys.platform):
+ "ignore/ignore-platform [functions..]"
+ for func in words[1:]:
+ self.ignores[func] = 1
+ for func in rest.split():
+ self.ignores[func] = 1
+ elif (command == 'ignore-glob' or
+ command == 'ignore-glob-' + sys.platform):
+ "ignore-glob/ignore-glob-platform [globs..]"
+ for func in words[1:]:
+ self.glob_ignores.append(func)
+ for func in rest.split():
+ self.glob_ignores.append(func)
+ elif (command == 'ignore-type' or
+ command == 'ignore-type-' + sys.platform):
+ "ignore-type/ignore-type-platform [typenames..]"
+ for typename in words[1:]:
+ self.type_ignores[typename] = 1
+ for typename in rest.split():
+ self.type_ignores[typename] = 1
+ elif command == 'override':
+ "override function/method [kwargs|noargs|onearg] [staticmethod|classmethod]"
+ func = words[1]
+ if 'kwargs' in words[1:]:
+ self.kwargs[func] = 1
+ elif 'noargs' in words[1:]:
+ self.noargs[func] = 1
+ elif 'onearg' in words[1:]:
+ self.onearg[func] = True
+
+ if 'staticmethod' in words[1:]:
+ self.staticmethod[func] = True
+ elif 'classmethod' in words[1:]:
+ self.classmethod[func] = True
+ if func in self.overrides:
+ raise RuntimeError("Function %s is being overridden more than once" % (func,))
+ self.overrides[func] = rest
+ self.startlines[func] = (startline + 1, filename)
+ elif command == 'override-attr':
+ "override-slot Class.attr"
+ attr = words[1]
+ self.override_attrs[attr] = rest
+ self.startlines[attr] = (startline + 1, filename)
+ elif command == 'override-slot':
+ "override-slot Class.slot"
+ slot = words[1]
+ self.override_slots[slot] = rest
+ self.startlines[slot] = (startline + 1, filename)
+ elif command == 'headers':
+ "headers"
+ self.headers = '%s\n#line %d "%s"\n%s' % \
+ (self.headers, startline + 1, filename, rest)
+ elif command == 'body':
+ "body"
+ self.body = '%s\n#line %d "%s"\n%s' % \
+ (self.body, startline + 1, filename, rest)
+ elif command == 'init':
+ "init"
+ self.init = '%s\n#line %d "%s"\n%s' % \
+ (self.init, startline + 1, filename, rest)
+ elif command == 'modulename':
+ "modulename name"
+ self.modulename = words[1]
+ elif command == 'include':
+ "include filename"
+ for filename in words[1:]:
+ self.handle_file(filename)
+ for filename in rest.split():
+ self.handle_file(filename)
+ elif command == 'import':
+ "import module1 [\n module2, \n module3 ...]"
+ for line in buffer.split('\n'):
+ match = import_pat.match(line)
+ if match:
+ module, pyname, cname, conditional, importing_for = match.groups()
+ self.imports.append((module, pyname, cname, importing_for or None))
+ elif command == 'define':
+ "define funcname [kwargs|noargs|onearg] [classmethod|staticmethod]"
+ "define Class.method [kwargs|noargs|onearg] [classmethod|staticmethod]"
+ func = words[1]
+ klass = None
+ if func.find('.') != -1:
+ klass, func = func.split('.', 1)
+
+ if klass not in self.defines:
+ self.defines[klass] = {}
+ self.defines[klass][func] = rest
+ else:
+ self.functions[func] = rest
+
+ if 'kwargs' in words[1:]:
+ self.kwargs[func] = 1
+ elif 'noargs' in words[1:]:
+ self.noargs[func] = 1
+ elif 'onearg' in words[1:]:
+ self.onearg[func] = 1
+
+ if 'staticmethod' in words[1:]:
+ self.staticmethod[func] = True
+ elif 'classmethod' in words[1:]:
+ self.classmethod[func] = True
+
+ self.startlines[func] = (startline + 1, filename)
+
+ elif command == 'new-constructor':
+ "new-constructor GType"
+ gtype, = words[1:]
+ self.newstyle_constructors[gtype] = True
+ elif command == 'options':
+ for option in words[1:]:
+ if option == 'dynamicnamespace':
+ self.dynamicnamespace = True
+
+ def is_ignored(self, name):
+ if name in self.ignores:
+ return 1
+ for glob in self.glob_ignores:
+ if fnmatch.fnmatchcase(name, glob):
+ return 1
+ return 0
+
+ def is_type_ignored(self, name):
+ return name in self.type_ignores
+
+ def is_overriden(self, name):
+ return name in self.overrides
+
+ def is_already_included(self, name):
+ return name in self.overridden
+
+ def override(self, name):
+ self.overridden[name] = 1
+ return self.overrides[name]
+
+ def define(self, klass, name):
+ self.overridden[class2cname(klass, name)] = 1
+ return self.defines[klass][name]
+
+ def function(self, name):
+ return self.functions[name]
+
+ def getstartline(self, name):
+ return self.startlines[name]
+
+ def wants_kwargs(self, name):
+ return name in self.kwargs
+
+ def wants_noargs(self, name):
+ return name in self.noargs
+
+ def wants_onearg(self, name):
+ return name in self.onearg
+
+ def is_staticmethod(self, name):
+ return name in self.staticmethod
+
+ def is_classmethod(self, name):
+ return name in self.classmethod
+
+ def attr_is_overriden(self, attr):
+ return attr in self.override_attrs
+
+ def attr_override(self, attr):
+ return self.override_attrs[attr]
+
+ def slot_is_overriden(self, slot):
+ return slot in self.override_slots
+
+ def slot_override(self, slot):
+ return self.override_slots[slot]
+
+ def get_headers(self):
+ return self.headers
+
+ def get_body(self):
+ return self.body
+
+ def get_init(self):
+ return self.init
+
+ def get_imports(self):
+ return self.imports
+
+ def get_defines_for(self, klass):
+ return self.defines.get(klass, {})
+
+ def get_functions(self):
+ return self.functions
diff --git a/codegen/reversewrapper.py b/codegen/libcodegen/reversewrapper.py
index ed48629..27ebb2e 100644
--- a/codegen/reversewrapper.py
+++ b/codegen/libcodegen/reversewrapper.py
@@ -1,7 +1,7 @@
### -*- python -*-
### Code to generate "Reverse Wrappers", i.e. C->Python wrappers
### (C) 2004 Gustavo Carneiro <gjc@gnome.org>
-import argtypes
+from . import argtypes
import os
DEBUG_MODE = ('PYGTK_CODEGEN_DEBUG' in os.environ)
@@ -404,13 +404,13 @@ class StringParam(Parameter):
if self.props.get('optional', False):
self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
self.wrapper.write_code(code=("if (%s)\n"
- " py_%s = PyString_FromString(%s);\n"
+ " py_%s = _PyUnicode_FromString(%s);\n"
% (self.name, self.name, self.name)),
cleanup=("Py_XDECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name, optional=True)
else:
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
- self.wrapper.write_code(code=("py_%s = PyString_FromString(%s);" %
+ self.wrapper.write_code(code=("py_%s = _PyUnicode_FromString(%s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name),
failure_expression=("!py_%s" % self.name))
@@ -526,7 +526,7 @@ class IntParam(Parameter):
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
- self.wrapper.write_code(code=("py_%s = PyInt_FromLong(%s);" %
+ self.wrapper.write_code(code=("py_%s = _PyLong_FromLong(%s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
@@ -563,7 +563,7 @@ class IntPtrParam(Parameter):
def convert_c2py(self):
if self.props["direction"] == "inout":
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
- self.wrapper.write_code(code=("py_%s = PyInt_FromLong(*%s);" %
+ self.wrapper.write_code(code=("py_%s = _PyLong_FromLong(*%s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
diff --git a/codegen/libcodegen/scmexpr.py b/codegen/libcodegen/scmexpr.py
new file mode 100644
index 0000000..0f38063
--- /dev/null
+++ b/codegen/libcodegen/scmexpr.py
@@ -0,0 +1,147 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+from __future__ import generators
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+try:
+ _unicode = unicode
+except NameError:
+ _unicode = str
+
+class error(Exception):
+ def __init__(self, filename, lineno, msg):
+ Exception.__init__(self, msg)
+ self.filename = filename
+ self.lineno = lineno
+ self.msg = msg
+ def __str__(self):
+ return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
+
+trans = {}
+for i in range(256):
+ c = chr(i)
+ if not c.isalnum() and c != '_':
+ trans[i] = _unicode('_')
+
+def parse(filename):
+ if isinstance(filename, str):
+ fp = open(filename, 'r')
+ else: # if not string, assume it is some kind of iterator
+ fp = filename
+ filename = getattr(fp, 'name', '<unknown>')
+ whitespace = ' \t\n\r\x0b\x0c'
+ nonsymbol = whitespace + '();\'"'
+ stack = []
+ openlines = []
+ lineno = 0
+ for line in fp:
+ pos = 0
+ lineno += 1
+ while pos < len(line):
+ if line[pos] in whitespace: # ignore whitespace
+ pass
+ elif line[pos] == ';': # comment
+ break
+ elif line[pos:pos+2] == "'(":
+ pass # the open parenthesis will be handled next iteration
+ elif line[pos] == '(':
+ stack.append(())
+ openlines.append(lineno)
+ elif line[pos] == ')':
+ if len(stack) == 0:
+ raise error(filename, lineno, 'close parenthesis found when none open')
+ closed = stack[-1]
+ del stack[-1]
+ del openlines[-1]
+ if stack:
+ stack[-1] += (closed,)
+ else:
+ yield closed
+ elif line[pos] == '"': # quoted string
+ if not stack:
+ raise error(filename, lineno,
+ 'string found outside of s-expression')
+ endpos = pos + 1
+ chars = []
+ while endpos < len(line):
+ if endpos+1 < len(line) and line[endpos] == '\\':
+ endpos += 1
+ if line[endpos] == 'n':
+ chars.append('\n')
+ elif line[endpos] == 'r':
+ chars.append('\r')
+ elif line[endpos] == 't':
+ chars.append('\t')
+ else:
+ chars.append('\\')
+ chars.append(line[endpos])
+ elif line[endpos] == '"':
+ break
+ else:
+ chars.append(line[endpos])
+ endpos += 1
+ if endpos >= len(line):
+ raise error(filename, lineno, "unclosed quoted string")
+ pos = endpos
+ stack[-1] += (''.join(chars),)
+ else: # symbol/number
+ if not stack:
+ raise error(filename, lineno,
+ 'identifier found outside of s-expression')
+ endpos = pos
+ while endpos < len(line) and line[endpos] not in nonsymbol:
+ endpos += 1
+ symbol = line[pos:endpos]
+ pos = max(pos, endpos-1)
+ try: symbol = int(symbol)
+ except ValueError:
+ try: symbol = float(symbol)
+ except ValueError: pass
+ stack[-1] += (symbol,)
+ pos += 1
+ if len(stack) != 0:
+ msg = '%d unclosed parentheses found at end of ' \
+ 'file (opened on line(s) %s)' % (len(stack),
+ ', '.join(map(str, openlines)))
+ raise error(filename, lineno, msg)
+
+class Parser:
+ def __init__(self, filename):
+ """Argument is either a string, a parse tree, or file object"""
+ self.filename = filename
+ def startParsing(self, filename=None):
+ statements = parse(filename or self.filename)
+ for statement in statements:
+ self.handle(statement)
+ def handle(self, tup):
+ cmd = _unicode(tup[0]).translate(trans)
+ if hasattr(self, cmd):
+ getattr(self, cmd)(*tup[1:])
+ else:
+ self.unknown(tup)
+ def unknown(self, tup):
+ pass
+
+_testString = """; a scheme file
+(define-func gdk_font_load ; a comment at end of line
+ GdkFont
+ ((string name)))
+
+(define-boxed GdkEvent
+ gdk_event_copy
+ gdk_event_free
+ "sizeof(GdkEvent)")
+"""
+
+if __name__ == '__main__':
+ import sys
+ if sys.argv[1:]:
+ fp = open(sys.argv[1])
+ else:
+ fp = StringIO(_testString)
+ statements = parse(fp)
+ for s in statements:
+ sys.stdout.write(repr(s) + '\n')
diff --git a/codegen/override.py b/codegen/override.py
index bba5e42..71082ed 100644
--- a/codegen/override.py
+++ b/codegen/override.py
@@ -1,285 +1 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-
-# this file contains code for loading up an override file. The override file
-# provides implementations of functions where the code generator could not
-# do its job correctly.
-
-import fnmatch
-import os
-import re
-import string
-import sys
-
-def class2cname(klass, method):
- c_name = ''
- for c in klass:
- if c.isupper():
- c_name += '_' + c.lower()
- else:
- c_name += c
- return c_name[1:] + '_' + method
-
-# import python_type as c_name [for arg_type]
-# Last ('for') clause is optional. If present, the type will be
-# imported only if given 'arg_type' is registered.
-import_pat = re.compile(r'\s*import\s+(\S+)\.([^\s.]+)\s+as\s+(\S+)(\s+for\s+(\S+))?')
-
-class Overrides:
- def __init__(self, filename=None):
- self.modulename = None
- self.ignores = {}
- self.glob_ignores = []
- self.type_ignores = {}
- self.overrides = {}
- self.overridden = {}
- self.kwargs = {}
- self.noargs = {}
- self.onearg = {}
- self.staticmethod = {}
- self.classmethod = {}
- self.startlines = {}
- self.override_attrs = {}
- self.override_slots = {}
- self.headers = ''
- self.body = ''
- self.init = ''
- self.imports = []
- self.defines = {}
- self.functions = {}
- self.newstyle_constructors = {}
- self.dynamicnamespace = False
- if filename:
- self.handle_file(filename)
-
- def handle_file(self, filename):
- oldpath = os.getcwd()
-
- fp = open(filename, 'r')
- dirname = os.path.dirname(os.path.abspath(filename))
-
- if dirname != oldpath:
- os.chdir(dirname)
-
- # read all the components of the file ...
- bufs = []
- startline = 1
- lines = []
- line = fp.readline()
- linenum = 1
- while line:
- if line == '%%\n' or line == '%%':
- if lines:
- bufs.append((string.join(lines, ''), startline))
- startline = linenum + 1
- lines = []
- else:
- lines.append(line)
- line = fp.readline()
- linenum = linenum + 1
- if lines:
- bufs.append((string.join(lines, ''), startline))
- if not bufs: return
-
- for buf, startline in bufs:
- self.__parse_override(buf, startline, filename)
-
- os.chdir(oldpath)
-
- def __parse_override(self, buffer, startline, filename):
- pos = string.find(buffer, '\n')
- if pos >= 0:
- line = buffer[:pos]
- rest = buffer[pos+1:]
- else:
- line = buffer ; rest = ''
- words = string.split(line)
- command = words[0]
- if (command == 'ignore' or
- command == 'ignore-' + sys.platform):
- "ignore/ignore-platform [functions..]"
- for func in words[1:]:
- self.ignores[func] = 1
- for func in string.split(rest):
- self.ignores[func] = 1
- elif (command == 'ignore-glob' or
- command == 'ignore-glob-' + sys.platform):
- "ignore-glob/ignore-glob-platform [globs..]"
- for func in words[1:]:
- self.glob_ignores.append(func)
- for func in string.split(rest):
- self.glob_ignores.append(func)
- elif (command == 'ignore-type' or
- command == 'ignore-type-' + sys.platform):
- "ignore-type/ignore-type-platform [typenames..]"
- for typename in words[1:]:
- self.type_ignores[typename] = 1
- for typename in string.split(rest):
- self.type_ignores[typename] = 1
- elif command == 'override':
- "override function/method [kwargs|noargs|onearg] [staticmethod|classmethod]"
- func = words[1]
- if 'kwargs' in words[1:]:
- self.kwargs[func] = 1
- elif 'noargs' in words[1:]:
- self.noargs[func] = 1
- elif 'onearg' in words[1:]:
- self.onearg[func] = True
-
- if 'staticmethod' in words[1:]:
- self.staticmethod[func] = True
- elif 'classmethod' in words[1:]:
- self.classmethod[func] = True
- if func in self.overrides:
- raise RuntimeError("Function %s is being overridden more than once" % (func,))
- self.overrides[func] = rest
- self.startlines[func] = (startline + 1, filename)
- elif command == 'override-attr':
- "override-slot Class.attr"
- attr = words[1]
- self.override_attrs[attr] = rest
- self.startlines[attr] = (startline + 1, filename)
- elif command == 'override-slot':
- "override-slot Class.slot"
- slot = words[1]
- self.override_slots[slot] = rest
- self.startlines[slot] = (startline + 1, filename)
- elif command == 'headers':
- "headers"
- self.headers = '%s\n#line %d "%s"\n%s' % \
- (self.headers, startline + 1, filename, rest)
- elif command == 'body':
- "body"
- self.body = '%s\n#line %d "%s"\n%s' % \
- (self.body, startline + 1, filename, rest)
- elif command == 'init':
- "init"
- self.init = '%s\n#line %d "%s"\n%s' % \
- (self.init, startline + 1, filename, rest)
- elif command == 'modulename':
- "modulename name"
- self.modulename = words[1]
- elif command == 'include':
- "include filename"
- for filename in words[1:]:
- self.handle_file(filename)
- for filename in string.split(rest):
- self.handle_file(filename)
- elif command == 'import':
- "import module1 [\n module2, \n module3 ...]"
- for line in string.split(buffer, '\n'):
- match = import_pat.match(line)
- if match:
- module, pyname, cname, conditional, importing_for = match.groups()
- self.imports.append((module, pyname, cname, importing_for or None))
- elif command == 'define':
- "define funcname [kwargs|noargs|onearg] [classmethod|staticmethod]"
- "define Class.method [kwargs|noargs|onearg] [classmethod|staticmethod]"
- func = words[1]
- klass = None
- if func.find('.') != -1:
- klass, func = func.split('.', 1)
-
- if not self.defines.has_key(klass):
- self.defines[klass] = {}
- self.defines[klass][func] = rest
- else:
- self.functions[func] = rest
-
- if 'kwargs' in words[1:]:
- self.kwargs[func] = 1
- elif 'noargs' in words[1:]:
- self.noargs[func] = 1
- elif 'onearg' in words[1:]:
- self.onearg[func] = 1
-
- if 'staticmethod' in words[1:]:
- self.staticmethod[func] = True
- elif 'classmethod' in words[1:]:
- self.classmethod[func] = True
-
- self.startlines[func] = (startline + 1, filename)
-
- elif command == 'new-constructor':
- "new-constructor GType"
- gtype, = words[1:]
- self.newstyle_constructors[gtype] = True
- elif command == 'options':
- for option in words[1:]:
- if option == 'dynamicnamespace':
- self.dynamicnamespace = True
-
- def is_ignored(self, name):
- if self.ignores.has_key(name):
- return 1
- for glob in self.glob_ignores:
- if fnmatch.fnmatchcase(name, glob):
- return 1
- return 0
-
- def is_type_ignored(self, name):
- return name in self.type_ignores
-
- def is_overriden(self, name):
- return self.overrides.has_key(name)
-
- def is_already_included(self, name):
- return self.overridden.has_key(name)
-
- def override(self, name):
- self.overridden[name] = 1
- return self.overrides[name]
-
- def define(self, klass, name):
- self.overridden[class2cname(klass, name)] = 1
- return self.defines[klass][name]
-
- def function(self, name):
- return self.functions[name]
-
- def getstartline(self, name):
- return self.startlines[name]
-
- def wants_kwargs(self, name):
- return self.kwargs.has_key(name)
-
- def wants_noargs(self, name):
- return self.noargs.has_key(name)
-
- def wants_onearg(self, name):
- return self.onearg.has_key(name)
-
- def is_staticmethod(self, name):
- return self.staticmethod.has_key(name)
-
- def is_classmethod(self, name):
- return self.classmethod.has_key(name)
-
- def attr_is_overriden(self, attr):
- return self.override_attrs.has_key(attr)
-
- def attr_override(self, attr):
- return self.override_attrs[attr]
-
- def slot_is_overriden(self, slot):
- return self.override_slots.has_key(slot)
-
- def slot_override(self, slot):
- return self.override_slots[slot]
-
- def get_headers(self):
- return self.headers
-
- def get_body(self):
- return self.body
-
- def get_init(self):
- return self.init
-
- def get_imports(self):
- return self.imports
-
- def get_defines_for(self, klass):
- return self.defines.get(klass, {})
-
- def get_functions(self):
- return self.functions
+from .libcodegen.override import *
diff --git a/codegen/scmexpr.py b/codegen/scmexpr.py
index 02f2e4b..2ba30e1 100755..100644
--- a/codegen/scmexpr.py
+++ b/codegen/scmexpr.py
@@ -1,143 +1,11 @@
#!/usr/bin/env python
-# -*- Mode: Python; py-indent-offset: 4 -*-
-from __future__ import generators
-
-import string
-from cStringIO import StringIO
-
-class error(Exception):
- def __init__(self, filename, lineno, msg):
- Exception.__init__(self, msg)
- self.filename = filename
- self.lineno = lineno
- self.msg = msg
- def __str__(self):
- return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
-
-trans = [' '] * 256
-for i in range(256):
- if chr(i) in string.letters + string.digits + '_':
- trans[i] = chr(i)
- else:
- trans[i] = '_'
-trans = string.join(trans, '')
-
-def parse(filename):
- if isinstance(filename, str):
- fp = open(filename, 'r')
- else: # if not string, assume it is some kind of iterator
- fp = filename
- filename = getattr(fp, 'name', '<unknown>')
- whitespace = ' \t\n\r\x0b\x0c'
- nonsymbol = whitespace + '();\'"'
- stack = []
- openlines = []
- lineno = 0
- for line in fp:
- pos = 0
- lineno += 1
- while pos < len(line):
- if line[pos] in whitespace: # ignore whitespace
- pass
- elif line[pos] == ';': # comment
- break
- elif line[pos:pos+2] == "'(":
- pass # the open parenthesis will be handled next iteration
- elif line[pos] == '(':
- stack.append(())
- openlines.append(lineno)
- elif line[pos] == ')':
- if len(stack) == 0:
- raise error(filename, lineno, 'close parenthesis found when none open')
- closed = stack[-1]
- del stack[-1]
- del openlines[-1]
- if stack:
- stack[-1] += (closed,)
- else:
- yield closed
- elif line[pos] == '"': # quoted string
- if not stack:
- raise error(filename, lineno,
- 'string found outside of s-expression')
- endpos = pos + 1
- chars = []
- while endpos < len(line):
- if endpos+1 < len(line) and line[endpos] == '\\':
- endpos += 1
- if line[endpos] == 'n':
- chars.append('\n')
- elif line[endpos] == 'r':
- chars.append('\r')
- elif line[endpos] == 't':
- chars.append('\t')
- else:
- chars.append('\\')
- chars.append(line[endpos])
- elif line[endpos] == '"':
- break
- else:
- chars.append(line[endpos])
- endpos += 1
- if endpos >= len(line):
- raise error(filename, lineno, "unclosed quoted string")
- pos = endpos
- stack[-1] += (''.join(chars),)
- else: # symbol/number
- if not stack:
- raise error(filename, lineno,
- 'identifier found outside of s-expression')
- endpos = pos
- while endpos < len(line) and line[endpos] not in nonsymbol:
- endpos += 1
- symbol = line[pos:endpos]
- pos = max(pos, endpos-1)
- try: symbol = int(symbol)
- except ValueError:
- try: symbol = float(symbol)
- except ValueError: pass
- stack[-1] += (symbol,)
- pos += 1
- if len(stack) != 0:
- msg = '%d unclosed parentheses found at end of ' \
- 'file (opened on line(s) %s)' % (len(stack),
- ', '.join(map(str, openlines)))
- raise error(filename, lineno, msg)
-
-class Parser:
- def __init__(self, filename):
- """Argument is either a string, a parse tree, or file object"""
- self.filename = filename
- def startParsing(self, filename=None):
- statements = parse(filename or self.filename)
- for statement in statements:
- self.handle(statement)
- def handle(self, tup):
- cmd = string.translate(tup[0], trans)
- if hasattr(self, cmd):
- getattr(self, cmd)(*tup[1:])
- else:
- self.unknown(tup)
- def unknown(self, tup):
- pass
-
-_testString = """; a scheme file
-(define-func gdk_font_load ; a comment at end of line
- GdkFont
- ((string name)))
-
-(define-boxed GdkEvent
- gdk_event_copy
- gdk_event_free
- "sizeof(GdkEvent)")
-"""
+# scmexpr.py is runnable as a script and available as module in codegen package
if __name__ == '__main__':
+ from libcodegen import scmrexpr
import sys
- if sys.argv[1:]:
- fp = open(sys.argv[1])
- else:
- fp = StringIO(_testString)
- statements = parse(fp)
- for s in statements:
- print `s`
+ sys.exit(scmrexpr.main(sys.argv))
+else:
+ from codegen.libcodegen.scmexpr import *
+
+
diff --git a/dsextras.py b/dsextras.py
index 10973e2..d3e0d2e 100644
--- a/dsextras.py
+++ b/dsextras.py
@@ -48,7 +48,10 @@ def getstatusoutput(cmd):
text = text[:-1]
return sts, text
else:
- from commands import getstatusoutput
+ try:
+ from subprocess import getstatusoutput
+ except:
+ from commands import getstatusoutput
return getstatusoutput(cmd)
def have_pkgconfig():
@@ -122,8 +125,8 @@ class BuildExt(build_ext):
msnative_struct = { '2' : '-fnative-struct',
'3' : '-mms-bitfields' }
gcc_version = getoutput('gcc -dumpversion')
- print 'using MinGW GCC version %s with %s option' % \
- (gcc_version, msnative_struct[gcc_version[0]])
+ print ('using MinGW GCC version %s with %s option' % \
+ (gcc_version, msnative_struct[gcc_version[0]]))
self.extra_compile_args.append(msnative_struct[gcc_version[0]])
def modify_compiler(self):
@@ -307,14 +310,14 @@ class PkgConfigExtension(Extension):
orig_version = getoutput('pkg-config --modversion %s' %
package)
- if (map(int, orig_version.split('.')) >=
- map(int, version.split('.'))):
+ if (tuple(map(int, orig_version.split('.'))) >=
+ tuple(map(int, version.split('.')))):
self.can_build_ok = 1
return 1
else:
- print "Warning: Too old version of %s" % self.pkc_name
- print " Need %s, but %s is installed" % \
- (version, orig_version)
+ print ("Warning: Too old version of %s" % self.pkc_name)
+ print (" Need %s, but %s is installed" % \
+ (version, orig_version))
self.can_build_ok = 0
return 0
@@ -343,7 +346,8 @@ try:
from codegen.codegen import register_types, SourceWriter, \
FileOutput
import codegen.createdefs
-except ImportError, e:
+except ImportError:
+ raise
template_classes_enabled=False
class Template(object):
@@ -445,7 +449,7 @@ class TemplateExtension(PkgConfigExtension):
if load_types:
del kwargs['load_types']
- if kwargs.has_key('output'):
+ if 'output' in kwargs:
kwargs['name'] = kwargs['output']
del kwargs['output']
diff --git a/setup.py b/setup.py
index 50f7abe..633e19d 100755
--- a/setup.py
+++ b/setup.py
@@ -20,21 +20,24 @@ from dsextras import get_m4_define, getoutput, have_pkgconfig, \
if '--yes-i-know-its-not-supported' in sys.argv:
sys.argv.remove('--yes-i-know-its-not-supported')
else:
- print '*'*70
- print 'Building PyGObject using distutils is NOT SUPPORTED.'
- print "It's mainly included to be able to easily build win32 installers"
- print "You may continue, but only if you agree to not ask any questions"
- print "To build PyGObject in a supported way, read the INSTALL file"
- print
- print "Build fixes are of course welcome and should be filed in bugzilla"
- print '*'*70
- input = raw_input('Not supported, ok [y/N]? ')
+ print ('*'*70)
+ print ('Building PyGObject using distutils is NOT SUPPORTED.')
+ print ("It's mainly included to be able to easily build win32 installers")
+ print ("You may continue, but only if you agree to not ask any questions")
+ print ("To build PyGObject in a supported way, read the INSTALL file")
+ print ("")
+ print ("Build fixes are of course welcome and should be filed in bugzilla")
+ print ('*'*70)
+ if sys.version_info < (3, 0):
+ input = raw_input('Not supported, ok [y/N]? ')
+ else:
+ input = input('Not supported, ok [y/N]? ')
if not input.startswith('y'):
raise SystemExit
if sys.version_info[:3] < (2, 3, 5):
- raise SystemExit, \
- "Python 2.3.5 or higher is required, %d.%d.%d found" % sys.version_info[:3]
+ raise SystemExit("Python 2.3.5 or higher is required, %d.%d.%d found"
+ % sys.version_info[:3])
MAJOR_VERSION = int(get_m4_define('pygobject_major_version'))
MINOR_VERSION = int(get_m4_define('pygobject_minor_version'))
@@ -174,7 +177,7 @@ py_modules = ['dsextras']
packages = ['codegen']
if not have_pkgconfig():
- print "Error, could not find pkg-config"
+ print ("Error, could not find pkg-config")
raise SystemExit
if glib.can_build():
@@ -197,8 +200,8 @@ if glib.can_build():
ext_modules.append(glib)
py_modules += ['glib.__init__', 'glib.option']
else:
- print
- print 'ERROR: Nothing to do, glib could not be found and is essential.'
+ print ("")
+ print ('ERROR: Nothing to do, glib could not be found and is essential.')
raise SystemExit
if gobject.can_build():
@@ -209,8 +212,8 @@ if gobject.can_build():
data_files.append((XSL_DIR, glob.glob('docs/xsl/*.xsl')))
py_modules += ['gobject.__init__', 'gobject.propertyhelper', 'gobject.constants']
else:
- print
- print 'ERROR: Nothing to do, gobject could not be found and is essential.'
+ print ('')
+ print ('ERROR: Nothing to do, gobject could not be found and is essential.')
raise SystemExit
if gio.can_build():
@@ -218,8 +221,8 @@ if gio.can_build():
py_modules += ['gio.__init__']
data_files.append((DEFS_DIR,('gio/gio-types.defs',)))
else:
- print
- print 'ERROR: Nothing to do, gio could not be found and is essential.'
+ print ('')
+ print ('ERROR: Nothing to do, gio could not be found and is essential.')
raise SystemExit
# Threading support
@@ -232,7 +235,7 @@ else:
try:
import thread
except ImportError:
- print "Warning: Could not import thread module, disabling threading"
+ print ("Warning: Could not import thread module, disabling threading")
enable_threading = False
else:
enable_threading = True