summaryrefslogtreecommitdiffstats
path: root/bindings/python/lang.py
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2008-08-05 14:52:52 +0000
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2008-08-05 14:52:52 +0000
commit1fae093527f69de086934f5df750cf374eaa2f48 (patch)
treec182d67081132607753c96da70f7ce0995909ff4 /bindings/python/lang.py
parent0930e6046f5c6e30b9d16fef5bb7a543e8750281 (diff)
downloadlasso-1fae093527f69de086934f5df750cf374eaa2f48.tar.gz
lasso-1fae093527f69de086934f5df750cf374eaa2f48.tar.xz
lasso-1fae093527f69de086934f5df750cf374eaa2f48.zip
Move all python binding related files inside the python subdirectory
Diffstat (limited to 'bindings/python/lang.py')
-rw-r--r--bindings/python/lang.py887
1 files changed, 887 insertions, 0 deletions
diff --git a/bindings/python/lang.py b/bindings/python/lang.py
new file mode 100644
index 00000000..483e7614
--- /dev/null
+++ b/bindings/python/lang.py
@@ -0,0 +1,887 @@
+# Lasso - A free implementation of the Liberty Alliance specifications.
+#
+# Copyright (C) 2004-2007 Entr'ouvert
+# http://lasso.entrouvert.org
+#
+# Authors: See AUTHORS file in top-level directory.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+import sys
+import re
+import textwrap
+import utils
+
+class Binding:
+ def __init__(self, binding_data):
+ self.binding_data = binding_data
+
+ def is_pygobject(self, t):
+ if t:
+ m = re.match(r'(?:const\s*)?(.*)',t) # Remove const modifier
+ t = m.group(1)
+ return t not in ['char*', 'gchar*',
+ 'GList*', 'GHashTable*',
+ 'int', 'gint', 'gboolean', 'xmlNode*'] + self.binding_data.enums
+ else:
+ return False
+
+ def generate(self):
+ fd = open('lasso.py', 'w')
+ self.generate_header(fd)
+ self.generate_exceptions(fd)
+ self.generate_constants(fd)
+ for clss in self.binding_data.structs:
+ self.generate_class(clss, fd)
+ self.generate_functions(fd)
+ self.generate_footer(fd)
+ fd.close()
+
+ fd = open('_lasso.c', 'w')
+ self.generate_wrapper(fd)
+ fd.close()
+
+ def generate_header(self, fd):
+ print >> fd, '''\
+# this file has been generated automatically; do not edit
+
+import _lasso
+
+_lasso.init()
+
+def cptrToPy(cptr):
+ if cptr is None:
+ return None
+ klass = getattr(lasso, cptr.typename)
+ o = klass.__new__(klass)
+ o._cptr = cptr
+ return o
+
+class frozendict(dict):
+ \'\'\'Immutable dict\'\'\'
+ # from Python Cookbook:
+ # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/414283
+ def _blocked_attribute(obj):
+ raise AttributeError('A frozendict cannot be modified.')
+ _blocked_attribute = property(_blocked_attribute)
+
+ __delitem__ = __setitem__ = clear = _blocked_attribute
+ pop = popitem = setdefault = update = _blocked_attribute
+
+ def __new__(cls, *args):
+ new = dict.__new__(cls)
+ dict.__init__(new, *args)
+ return new
+
+ def __init__(self, *args):
+ pass
+
+ def __hash__(self):
+ try:
+ return self._cached_hash
+ except AttributeError:
+ h = self._cached_hash = hash(tuple(sorted(self.items())))
+ return h
+
+ def __repr__(self):
+ return 'frozendict(%s)' % dict.__repr__(self)
+'''
+
+ def generate_exceptions(self, fd):
+ done_cats = []
+ print >> fd, '''\
+class Error(Exception):
+ code = None
+
+ @staticmethod
+ def raise_on_rc(rc):
+ global exceptions_dict
+ exception = exceptions_dict.get(rc, Error())
+ exception.code = rc
+ raise exception
+
+ def __str__(self):
+ return '<lasso.%s(%s): %s>' % (self.__class__.__name__, self.code, _lasso.strError(self.code))
+
+ def __getitem__(self, i):
+ # compatibility with SWIG bindings
+ if i == 0:
+ return self.code
+ elif i == 1:
+ return _lasso.strError(self.code)
+ else:
+ raise IndexError()
+'''
+ for exc_cat in self.binding_data.overrides.findall('exception/category'):
+ cat = exc_cat.attrib.get('name')
+ done_cats.append(cat)
+ parent_cat = exc_cat.attrib.get('parent', '')
+ print >> fd, '''\
+class %sError(%sError):
+ pass
+''' % (cat, parent_cat)
+
+ exceptions_dict = {}
+
+ for c in self.binding_data.constants:
+ m = re.match(r'LASSO_(\w+)_ERROR_(.*)', c[1])
+ if not m:
+ continue
+ cat, detail = m.groups()
+ cat = cat.title().replace('_', '')
+ detail = (cat + '_' + detail).title().replace('_', '')
+ if not cat in done_cats:
+ done_cats.append(cat)
+ for exc_cat in self.binding_data.overrides.findall('exception/category'):
+ if exc_cat.attrib.get('name') == cat:
+ parent_cat = exc_cat.attrib.get('parent')
+ break
+ else:
+ parent_cat = ''
+
+ print >> fd, '''\
+class %sError(%sError):
+ pass
+''' % (cat, parent_cat)
+
+ exceptions_dict[detail] = c[1][6:]
+
+ if (detail, cat) == ('UnsupportedProfile', 'Logout'):
+ # skip Logout/UnsupportedProfile exception as its name would
+ # be the same as Profile/UnsupportedProfile; it is not a
+ # problem skipping it as they both inherit from ProfileError
+ # and the exception code will correctly be set by raise_on_rc
+ # afterwards. (actually it is even totally unnecessary to skip
+ # it here as Profile/UnsupportedProfile is handled after
+ # Logout/UnsupportedProfile, this is just done in the case the
+ # ordering would change)
+ continue
+
+ print >> fd, '''\
+class %sError(%sError):
+ pass
+''' % (detail, cat)
+
+ print >> fd, 'exceptions_dict = {'
+ for k, v in exceptions_dict.items():
+ print >> fd, ' _lasso.%s: %sError,' % (v, k)
+ print >> fd, '}'
+ print >> fd, ''
+
+ def generate_footer(self, fd):
+ print >> fd, '''
+
+import lasso
+
+# backward compatibility with the SWIG binding
+
+WSF_SUPPORT = WSF_ENABLED
+
+Profile.isIdentityDirty = property(Profile.hasDirtyIdentity)
+Profile.isSessionDirty = property(Profile.hasDirtySession)
+
+def identity_get_provider_ids(self):
+ return self.federations.keys()
+Identity.providerIds = property(identity_get_provider_ids)
+
+def server_get_provider_ids(self):
+ return self.providers.keys()
+Server.providerIds = property(server_get_provider_ids)
+
+def session_get_provider_ids(self):
+ return self.assertions.keys()
+Session.providerIds = property(session_get_provider_ids)
+
+Samlp2AuthnRequest.nameIDPolicy = Samlp2AuthnRequest.nameIdPolicy
+LibAuthnRequest.nameIDPolicy = LibAuthnRequest.nameIdPolicy
+Saml2Subject.nameID = Saml2Subject.nameId
+MiscTextNode.text_child = MiscTextNode.textChild
+NodeList = list
+StringList = list
+StringDict = dict
+registerIdWsf2DstService = registerIdwsf2DstService
+
+if WSF_SUPPORT:
+ DiscoDescription_newWithBriefSoapHttpDescription = DiscoDescription.newWithBriefSoapHttpDescription
+ Discovery.buildRequestMsg = Discovery.buildSoapRequestMsg
+ InteractionProfileService.buildRequestMsg = InteractionProfileService.buildSoapRequestMsg
+ InteractionProfileService.buildResponseMsg = InteractionProfileService.buildSoapResponseMsg
+ DataService.buildRequestMsg = DataService.buildSoapRequestMsg
+ DiscoModifyResponse.newEntryIds = DiscoModifyResponse.newEntryIDs
+'''
+
+ def generate_constants(self, fd):
+ print >> fd, '### Constants (both enums and defines)'
+ for c in self.binding_data.constants:
+ print >> fd, '%s = _lasso.%s' % (c[1][6:], c[1][6:])
+ for c in self.binding_data.overrides.findall('constant'):
+ name = c.attrib.get('name')
+ if c.attrib.get('value'):
+ name = name[6:] # dropping LASSO_
+ value = c.attrib.get('value')
+ if value == 'True':
+ print >> fd, '%s = True' % name
+ else:
+ print >> sys.stderr, 'E: unknown value for constant: %r' % value
+ print >> fd, ''
+
+ def generate_class(self, clss, fd):
+ klassname = clss.name[5:] # remove Lasso from class name
+ if clss.parent == 'GObject':
+ parentname = 'object'
+ else:
+ parentname = clss.parent[5:]
+
+ print >> fd, '''class %(klassname)s(%(parentname)s):''' % locals()
+ if not clss.members and not clss.methods:
+ print >> fd, ' pass'
+ print >> fd, ''
+ return
+
+ methods = clss.methods[:]
+ # constructor(s)
+ method_prefix = 'lasso_' + utils.format_as_underscored(klassname) + '_'
+ for m in self.binding_data.functions:
+ if m.name == method_prefix + 'new':
+ c_args = []
+ py_args = []
+ for o in m.args:
+ arg_type, arg_name, arg_options = o
+ if arg_options.get('optional'):
+ py_args.append('%s = None' % arg_name)
+ else:
+ py_args.append(arg_name)
+
+ if self.is_pygobject(arg_type):
+ c_args.append('%s._cptr' % arg_name)
+ else:
+ c_args.append(arg_name)
+
+ c_args = ', '.join(c_args)
+ py_args = ', ' + ', '.join(py_args)
+ print >> fd, ' def __init__(self%s):' % py_args
+ # XXX: could check self._cptr.typename to see if it got the
+ # right class type
+ print >> fd, ' self._cptr = _lasso.%s(%s)' % (
+ m.name[6:], c_args)
+ print >> fd, ' if self._cptr is None:'
+ print >> fd, ' raise Error(\'failed to create object\')'
+ print >> fd, ''
+
+ for m in self.binding_data.functions:
+ if m.name.startswith(method_prefix + 'new_'):
+ constructor_name = utils.format_as_camelcase(m.name[len(method_prefix):])
+ c_args = []
+ py_args = []
+ for o in m.args:
+ arg_type, arg_name, arg_options = o
+ if arg_options.get('optional'):
+ py_args.append('%s = None' % arg_name)
+ else:
+ py_args.append(arg_name)
+
+ if self.is_pygobject(arg_type):
+ c_args.append('%s._cptr' % arg_name)
+ else:
+ c_args.append(arg_name)
+ c_args = ', '.join(c_args)
+ py_args = ', ' + ', '.join(py_args)
+ print >> fd, ' @classmethod'
+ print >> fd, ' def %s(cls%s):' % (constructor_name, py_args)
+ print >> fd, ' obj = cls.__new__(cls)'
+ print >> fd, ' obj._cptr = _lasso.%s(%s)' % (m.name[6:], c_args)
+ print >> fd, ' if obj._cptr is None:'
+ print >> fd, ' raise RuntimeError(\'lasso failed to create object\')'
+ print >> fd, ' return obj'
+ print >> fd, ''
+
+ # create properties for members
+ for m in clss.members:
+ mname = utils.format_as_camelcase(m[1])
+ options = m[2]
+ print >> fd, ' def get_%s(self):' % mname
+ if self.is_pygobject(m[0]):
+ print >> fd, ' t = _lasso.%s_%s_get(self._cptr)' % (
+ klassname, mname)
+ print >> fd, ' return cptrToPy(t)'
+ elif m[0] == 'GList*' and options.get('elem_type') not in ('char*', 'xmlNode*'):
+ print >> fd, ' l = _lasso.%s_%s_get(self._cptr)' % (
+ klassname, mname)
+ print >> fd, ' if not l: return l'
+ print >> fd, ' return tuple([cptrToPy(x) for x in l])'
+ elif m[0] == 'GHashTable*':
+ print >> fd, ' d = _lasso.%s_%s_get(self._cptr)' % (
+ klassname, mname)
+ print >> fd, ' if not d: return d'
+ if options.get('elem_type') != 'char*':
+ print >> fd, ' d2 = {}'
+ print >> fd, ' for k, v in d.items():'
+ print >> fd, ' d2[k] = cptrToPy(v)'
+ print >> fd, ' return frozendict(d2)'
+ else:
+ print >> fd, ' return frozendict(d)'
+ else:
+ print >> fd, ' return _lasso.%s_%s_get(self._cptr)' % (
+ klassname, mname)
+ print >> fd, ' def set_%s(self, value):' % mname
+ if self.is_pygobject(m[0]):
+ print >> fd, ' if value is not None:'
+ print >> fd, ' value = value._cptr'
+ elif m[0] == 'GList*' and options.get('elem_type') not in ('char*', 'xmlNode*'):
+ print >> fd, ' if value is not None:'
+ print >> fd, ' value = tuple([x._cptr for x in value])'
+ print >> fd, ' _lasso.%s_%s_set(self._cptr, value)' % (
+ klassname, mname)
+ print >> fd, ' %s = property(get_%s, set_%s)' % (mname, mname, mname)
+ print >> fd, ''
+
+ # first pass on methods, getting accessors
+ for m in clss.methods:
+ if not ('_get_' in m.name and len(m.args) == 1):
+ continue
+ methods.remove(m)
+ try:
+ setter_name = m.name.replace('_get_', '_set_')
+ setter = [x for x in methods if x.name == setter_name][0]
+ methods.remove(setter)
+ except IndexError:
+ setter = None
+ if m.rename:
+ mname = m.rename
+ if mname.startswith('lasso_'):
+ mname = mname[6:]
+ mname = '%s%s' % (mname[0].lower(), mname[1:])
+ print >> fd, ' def get_%s(self):' % mname
+ function_name = m.rename
+ if function_name.startswith('lasso_'):
+ function_name = function_name[6:]
+ else:
+ mname = m.name
+ mname = re.match(r'lasso_.*_get_(\w+)', mname).group(1)
+ mname = utils.format_underscore_as_camelcase(mname)
+ print >> fd, ' def get_%s(self):' % mname
+ function_name = m.name[6:]
+
+ if self.is_pygobject(m.return_type):
+ print >> fd, ' t = _lasso.%s(self._cptr)' % function_name
+ print >> fd, ' return cptrToPy(t)'
+ else:
+ print >> fd, ' return _lasso.%s(self._cptr)' % function_name
+
+ if mname[0] == mname[0].lower() and not m.rename:
+ # API compatibility with SWIG bindings which didn't have
+ # accessors for those methods and used totally pythonified
+ # method name instead, such as getNextProviderId
+ print >> fd, ' get%s%s = get_%s' % (
+ mname[0].upper(), mname[1:], mname)
+ if setter:
+ print >> fd, ' def set_%s(self, value):' % mname
+ print >> fd, ' _lasso.%s(self._cptr, value)' % setter.name[6:]
+ print >> fd, ' %s = property(get_%s, set_%s)' % (mname, mname, mname)
+ else:
+ print >> fd, ' %s = property(get_%s)' % (mname, mname)
+ print >> fd, ''
+
+ # second pass on methods, real methods
+ for m in methods:
+ if m.name.endswith('_new') or m.name.endswith('_new_from_dump') or \
+ m.name.endswith('_new_full'):
+ continue
+ if not m.name.startswith(method_prefix):
+ print >> sys.stderr, 'W:', m.name, 'vs', method_prefix
+ continue
+
+ if m.rename:
+ mname = m.rename[len(method_prefix):]
+ function_name = m.rename[6:]
+ else:
+ mname = m.name[len(method_prefix):]
+ function_name = m.name[6:]
+ py_args = []
+ c_args = []
+ for o in m.args[1:]:
+ arg_type, arg_name, arg_options = o
+ if arg_options.get('optional'):
+ if arg_options.get('default'):
+ defval = arg_options.get('default')
+ if defval.startswith('c:'): # constant
+ py_args.append('%s = %s' % (arg_name, defval[8:]))
+ elif defval.startswith('b:'): # boolean
+ py_args.append('%s = %s' % (arg_name, defval[2:]))
+ else:
+ print >> sys.stderr, "E: don't know what to do with %s" % defval
+ sys.exit(1)
+ else:
+ py_args.append('%s = None' % arg_name)
+ else:
+ py_args.append(arg_name)
+ if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*', 'xmlNode*') or \
+ arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] or \
+ arg_type in self.binding_data.enums:
+ c_args.append(arg_name)
+ else:
+ c_args.append('%s._cptr' % arg_name)
+
+ if py_args:
+ py_args = ', ' + ', '.join(py_args)
+ else:
+ py_args = ''
+ if c_args:
+ c_args = ', ' + ', '.join(c_args)
+ else:
+ c_args = ''
+
+ print >> fd, ' def %s(self%s):' % (
+ utils.format_underscore_as_camelcase(mname), py_args)
+ if m.docstring:
+ print >> fd, " '''"
+ print >> fd, self.format_docstring(m, mname, 8)
+ print >> fd, " '''"
+ if m.return_type in (None, 'void'):
+ print >> fd, ' _lasso.%s(self._cptr%s)' % (
+ function_name, c_args)
+ elif m.return_type in ('gint', 'int'):
+ print >> fd, ' rc = _lasso.%s(self._cptr%s)' % (
+ function_name, c_args)
+ print >> fd, ' if rc == 0:'
+ print >> fd, ' return'
+ print >> fd, ' raise Error.raise_on_rc(rc)'
+ elif m.return_type == 'GList*' and self.is_pygobject(m.return_type_qualifier):
+ print >> fd, ' value = _lasso.%s(self._cptr%s)' % (
+ function_name, c_args)
+ print >> fd, ' if value is not None:'
+ print >> fd, ' value = tuple([cptrToPy(x) for x in value])'
+ print >> fd, ' return value'
+ elif self.is_pygobject(m.return_type):
+ print >> fd, ' return cptrToPy(_lasso.%s(self._cptr%s))' % (
+ function_name, c_args)
+ else:
+ print >> fd, ' return _lasso.%s(self._cptr%s)' % (
+ function_name, c_args)
+ print >> fd, ''
+
+ print >> fd, ''
+
+ def format_docstring(self, func, method_name, indent):
+ if func.args:
+ first_arg_name = func.args[0][1]
+ else:
+ first_arg_name = None
+
+ def format_inlines_sub(s):
+ type = s.group(1)[0]
+ var = s.group(1)[1:]
+ if type == '#': # struct
+ if var.startswith('Lasso'):
+ return 'L{%s}' % var[5:]
+ elif type == '%': # %TRUE, %FALSE
+ if var == 'TRUE':
+ return 'True'
+ if var == 'FALSE':
+ return 'False'
+ print >> sys.stderr, 'W: unknown docstring thingie: %s' % s.group(1)
+ elif type == '@':
+ if var == first_arg_name:
+ var = 'self'
+ return 'C{%s}' % var
+ return s.group(1)
+
+ regex = re.compile(r'([\#%@]\w+)', re.DOTALL)
+
+ def format_inline(s):
+ s = regex.sub(format_inlines_sub, s)
+ return s.replace('NULL', 'None')
+
+ docstring = func.docstring
+ s = []
+
+ if docstring.description:
+ for paragraph in docstring.description.split('\n\n'):
+ if '<itemizedlist>' in paragraph:
+ before, after = paragraph.split('<itemizedlist>' ,1)
+ if before:
+ s.append('\n'.join(textwrap.wrap(
+ format_inline(before), 70)))
+
+ # remove tags
+ after = after.replace('<itemizedlist>', '')
+ after = after.replace('</itemizedlist>', '')
+
+ for listitem in after.split('<listitem><para>'):
+ listitem = listitem.replace('</para></listitem>', '').strip()
+ s.append('\n'.join(textwrap.wrap(
+ format_inline(listitem), 70,
+ initial_indent = ' - ',
+ subsequent_indent = ' ')))
+ s.append('\n\n')
+
+ else:
+ s.append('\n'.join(textwrap.wrap(
+ format_inline(paragraph), 70)))
+ s.append('\n\n')
+
+ for param in docstring.parameters:
+ s.append('\n'.join(textwrap.wrap(
+ format_inline(param[1]), 70,
+ initial_indent = '@param %s: ' % param[0],
+ subsequent_indent = 4*' ')))
+ s.append('\n')
+ if docstring.return_value:
+ rv = docstring.return_value
+ exceptions_instead = ['0 on success; or a negative value otherwise.',
+ '0 on success; a negative value if an error occured.',
+ '0 on success; another value if an error occured.']
+ if not rv in exceptions_instead:
+ owner_info = ['This xmlnode must be freed by caller.',
+ 'The string must be freed by the caller.',
+ 'It must be freed by the caller.',
+ 'This string must be freed by the caller.']
+ for o_i in owner_info:
+ rv = rv.replace(o_i, '')
+ s.append('\n'.join(textwrap.wrap(
+ format_inline(rv), 70,
+ initial_indent = '@return: ',
+ subsequent_indent = 4*' ')))
+ s.append('\n')
+
+
+ s[-1] = s[-1].rstrip() # remove trailing newline from last line
+
+ return '\n'.join([(indent*' ')+x for x in ''.join(s).splitlines()])
+
+
+ def generate_functions(self, fd):
+ for m in self.binding_data.functions:
+ if m.name.endswith('_new') or '_new_' in m.name:
+ continue
+ if m.rename:
+ pname = m.rename
+ name = m.rename
+ if name.startswith('lasso_'):
+ name = name[6:]
+ pname = utils.format_as_camelcase(name)
+ else:
+ name = m.name[6:]
+ pname = utils.format_as_camelcase(name)
+ print >> fd, '%s = _lasso.%s' % (pname, name)
+
+
+ def generate_wrapper(self, fd):
+ print >> fd, open('wrapper_top.c').read()
+ for h in self.binding_data.headers:
+ print >> fd, '#include <%s>' % h
+ print >> fd, ''
+
+ self.generate_constants_wrapper(fd)
+
+ self.wrapper_list = []
+ for m in self.binding_data.functions:
+ self.generate_function_wrapper(m, fd)
+ for c in self.binding_data.structs:
+ self.generate_member_wrapper(c, fd)
+ for m in c.methods:
+ self.generate_function_wrapper(m, fd)
+ self.generate_wrapper_list(fd)
+ print >> fd, open('wrapper_bottom.c').read()
+
+ def generate_constants_wrapper(self, fd):
+ print >> fd, '''static void
+register_constants(PyObject *d)
+{
+ PyObject *obj;
+'''
+ for c in self.binding_data.constants:
+ if c[0] == 'i':
+ print >> fd, ' obj = PyInt_FromLong(%s);' % c[1]
+ elif c[0] == 's':
+ print >> fd, ' obj = PyString_FromString(%s);' % c[1]
+ elif c[0] == 'b':
+ print >> fd, '''\
+#ifdef %s
+ obj = Py_True;
+#else
+ obj = Py_False;
+#endif''' % c[1]
+ else:
+ print >> sys.stderr, 'E: unknown constant type: %r' % c[0]
+ print >> fd, ' PyDict_SetItemString(d, "%s", obj);' % c[1][6:]
+ print >> fd, ' Py_DECREF(obj);'
+ print >> fd, '}'
+ print >> fd, ''
+
+
+ def generate_member_wrapper(self, c, fd):
+ klassname = c.name
+ for m in c.members:
+ mname = utils.format_as_camelcase(m[1])
+ # getter
+ print >> fd, '''static PyObject*
+%s_%s_get(PyObject *self, PyObject *args)
+{''' % (klassname[5:], mname)
+ self.wrapper_list.append('%s_%s_get' % (klassname[5:], mname))
+
+ ftype = m[0]
+ if ftype in ('char*', 'const char*', 'gchar*', 'const gchar*'):
+ ftype = 'char*'
+ print >> fd, ' %s return_value;' % ftype
+ print >> fd, ' PyObject* return_pyvalue;'
+ print >> fd, ' PyGObjectPtr* cvt_this;'
+ print >> fd, ' %s* this;' % klassname
+ print >> fd, ''
+ print >> fd, ' if (! PyArg_ParseTuple(args, "O", &cvt_this)) return NULL;'
+ print >> fd, ' this = (%s*)cvt_this->obj;' % klassname
+
+ if self.is_pygobject(ftype):
+ print >> fd, ' return_value = this->%s;' % m[1];
+ elif ftype in ('char*',):
+ print >> fd, ' return_value = g_strdup(this->%s);' % m[1]
+ else:
+ print >> fd, ' return_value = this->%s;' % m[1];
+
+ self.return_value(fd, ftype, m[2])
+
+ print >> fd, ' return return_pyvalue;'
+ print >> fd, '}'
+ print >> fd, ''
+
+ # setter
+ print >> fd, '''static PyObject*
+%s_%s_set(PyObject *self, PyObject *args)
+{''' % (klassname[5:], mname)
+ self.wrapper_list.append('%s_%s_set' % (klassname[5:], mname))
+
+ print >> fd, ' PyGObjectPtr* cvt_this;'
+ print >> fd, ' %s* this;' % klassname
+ arg_type = m[0]
+ # Determine type class
+ if m[0] in ('char*', 'const char*', 'gchar*', 'const gchar*'):
+ arg_type = arg_type.replace('const ', '')
+ parse_format = 'z'
+ parse_arg = '&value'
+ print >> fd, ' %s value;' % arg_type
+ elif arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums:
+ parse_format = 'i'
+ parse_arg = '&value'
+ print >> fd, ' %s value;' % arg_type
+ elif arg_type in ('GList*','GHashTable*', 'xmlNode*'):
+ parse_format = 'O'
+ print >> fd, ' PyObject *cvt_value;'
+ parse_arg = '&cvt_value'
+ else:
+ parse_format = 'O'
+ print >> fd, ' PyGObjectPtr *cvt_value;'
+ parse_arg = '&cvt_value'
+ # Get GObject
+ print >> fd, ' if (! PyArg_ParseTuple(args, "O%s", &cvt_this, %s)) return NULL;' % (
+ parse_format, parse_arg)
+ print >> fd, ' this = (%s*)cvt_this->obj;' % klassname
+ # Change value
+ if parse_format == 'i':
+ print >> fd, ' this->%s = value;' % m[1]
+ elif parse_format in ('s', 'z'):
+ print >> fd, ' if (this->%s) g_free(this->%s);' % (m[1], m[1])
+ print >> fd, ' this->%s = g_strdup(value);' % m[1]
+ elif parse_format == 'O' and arg_type == 'GList*':
+ elem_type = m[2].get('elem_type')
+ if elem_type == 'char*':
+ print >> fd, ' set_list_of_strings(&this->%s, cvt_value);' % m[1]
+ elif elem_type == 'xmlNode*':
+ print >> fd, ' set_list_of_xml_nodes(&this->%s, cvt_value);' % m[1]
+ else:
+ print >> fd, ' set_list_of_pygobject(&this->%s, cvt_value);' % m[1]
+ elif parse_format == 'O' and arg_type == 'GHashTable*':
+ print >> fd, ' set_hashtable_of_pygobject(this->%s, cvt_value);' % m[1]
+ elif parse_format == 'O' and arg_type == 'xmlNode*':
+ print >> fd, ' if (this->%s) xmlFreeNode(this->%s);' % (m[1], m[1])
+ print >> fd, ' this->%s = get_xml_node_from_pystring(cvt_value);' % m[1]
+ elif parse_format == 'O':
+ print >> fd, ' set_object_field((GObject**)&this->%s, cvt_value);' % m[1]
+ print >> fd, ' return noneRef();'
+ print >> fd, '}'
+ print >> fd, ''
+
+
+ def return_value(self, fd, vtype, options):
+ if vtype == 'gboolean':
+ print >> fd, ' if (return_value) {'
+ print >> fd, ' Py_INCREF(Py_True);'
+ print >> fd, ' return_pyvalue = Py_True;'
+ print >> fd, ' } else {'
+ print >> fd, ' Py_INCREF(Py_False);'
+ print >> fd, ' return_pyvalue = Py_False;'
+ print >> fd, ' }'
+ elif vtype in ['int', 'gint'] + self.binding_data.enums:
+ print >> fd, ' return_pyvalue = PyInt_FromLong(return_value);'
+ elif vtype in ('char*', 'gchar*'):
+ print >> fd, ' if (return_value) {'
+ print >> fd, ' return_pyvalue = PyString_FromString(return_value);'
+ print >> fd, ' g_free(return_value);'
+ print >> fd, ' } else {'
+ print >> fd, ' return_pyvalue = noneRef();'
+ print >> fd, ' }'
+ elif vtype in ('const char*', 'const gchar*'):
+ print >> fd, ' if (return_value) {'
+ print >> fd, ' return_pyvalue = PyString_FromString(return_value);'
+ print >> fd, ' } else {'
+ print >> fd, ' return_pyvalue = noneRef();'
+ print >> fd, ' }'
+ elif vtype in ('const GList*', 'GList*',):
+ elem_type = options.get('elem_type')
+ if elem_type == 'char*':
+ print >> fd, ' return_pyvalue = get_list_of_strings(return_value);'
+ elif elem_type == 'xmlNode*':
+ print >> fd, ' return_pyvalue = get_list_of_xml_nodes(return_value);'
+ else:
+ print >> fd, ' return_pyvalue = get_list_of_pygobject(return_value);'
+ elif vtype in ('GHashTable*',):
+ elem_type = options.get('elem_type')
+ if elem_type == 'char*':
+ print >> fd, ' return_pyvalue = get_dict_from_hashtable_of_strings(return_value);'
+ else:
+ print >> fd, ' return_pyvalue = get_dict_from_hashtable_of_objects(return_value);'
+ elif vtype == 'xmlNode*':
+ # convert xmlNode* to strings
+ print >> fd, ' if (return_value) {'
+ print >> fd, ' return_pyvalue = get_pystring_from_xml_node(return_value);'
+ print >> fd, ' } else {'
+ print >> fd, ' return_pyvalue = noneRef();'
+ print >> fd, ' }'
+ else:
+ # return a PyGObjectPtr (wrapper around GObject)
+ print >> fd, '''\
+ if (return_value) {
+ return_pyvalue = PyGObjectPtr_New(G_OBJECT(return_value));
+ } else {
+ return_pyvalue = noneRef();
+ }
+'''
+
+ def generate_function_wrapper(self, m, fd):
+ if m.rename:
+ name = m.rename
+ if name.startswith('lasso_'):
+ name = name[6:]
+ else:
+ name = m.name[6:]
+ self.wrapper_list.append(name)
+ print >> fd, '''static PyObject*
+%s(PyObject *self, PyObject *args)
+{''' % name
+ parse_tuple_format = []
+ parse_tuple_args = []
+ for arg in m.args:
+ arg_type, arg_name, arg_options = arg
+ if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*'):
+ arg_type = arg_type.replace('const ', '')
+ if arg_options.get('optional'):
+ if not '|' in parse_tuple_format:
+ parse_tuple_format.append('|')
+ parse_tuple_format.append('z')
+ else:
+ parse_tuple_format.append('s')
+ parse_tuple_args.append('&%s' % arg_name)
+ print >> fd, ' %s %s = NULL;' % (arg[0], arg[1])
+ elif arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums:
+ if arg_options.get('optional'):
+ if not '|' in parse_tuple_format:
+ parse_tuple_format.append('|')
+ parse_tuple_format.append('i')
+ parse_tuple_args.append('&%s' % arg_name)
+ if arg_options.get('default'):
+ defval = arg_options.get('default')
+ if defval.startswith('b:'):
+ defval = defval[2:].upper()
+ else:
+ defval = defval[2:]
+ print >> fd, ' %s %s = %s;' % (arg[0], arg[1], defval)
+ else:
+ print >> fd, ' %s %s;' % (arg[0], arg[1])
+ elif arg_type in ('GList*', 'xmlNode*'):
+ parse_tuple_format.append('O')
+ parse_tuple_args.append('&cvt_%s' % arg_name)
+ print >> fd, ' %s %s = NULL;' % (arg[0], arg[1])
+ print >> fd, ' PyObject *cvt_%s = NULL;' % arg_name
+ else:
+ parse_tuple_format.append('O')
+ parse_tuple_args.append('&cvt_%s' % arg_name)
+ print >> fd, ' %s %s = NULL;' % (arg[0], arg[1])
+ print >> fd, ' PyGObjectPtr *cvt_%s = NULL;' % arg_name
+
+ if m.return_type:
+ print >> fd, ' %s return_value;' % m.return_type
+ print >> fd, ' PyObject* return_pyvalue;'
+ print >> fd, ''
+
+ parse_tuple_args = ', '.join(parse_tuple_args)
+ if parse_tuple_args:
+ parse_tuple_args = ', ' + parse_tuple_args
+
+ print >> fd, ' if (! PyArg_ParseTuple(args, "%s"%s)) return NULL;' % (
+ ''.join(parse_tuple_format), parse_tuple_args)
+
+ for f, arg in zip(parse_tuple_format, m.args):
+ if arg[0] == 'GList*':
+ qualifier = arg[2].get('elem_type')
+ if qualifier == 'char*':
+ print >> fd, ' set_list_of_strings(&%s, cvt_%s);' % (arg[1], arg[1])
+ elif qualifier == 'xmlNode*':
+ print >> fd, ' set_list_of_xml_nodes(&%s, cvt_%s);' % (arg[1], arg[1])
+ elif qualifier == 'LassoNode':
+ print >> fd, ' set_list_of_pygobject(&%s, cvt_%s);' % (arg[1], arg[1])
+ else:
+ print >> sys.stderr, 'E: unqualified GList argument in', name
+ elif arg[0] == 'xmlNode*':
+ print >> fd, ' %s = get_xml_node_from_pystring(cvt_%s);' % (arg[1], arg[1])
+ elif f == 'O':
+ print >> fd, ' %s = (%s)cvt_%s->obj;' % (arg[1], arg[0], arg[1])
+
+ if m.return_type:
+ print >> fd, ' return_value =',
+ if 'new' in m.name:
+ print >> fd, '(%s)' % m.return_type,
+ print >> fd, '%s(%s);' % (m.name, ', '.join([x[1] for x in m.args]))
+
+ for f, arg in zip(parse_tuple_format, m.args):
+ if arg[0] == 'GList*':
+ qualifier = arg[2].get('elem_type')
+ if qualifier == 'char*':
+ print >> fd, ' free_list(&%s, (GFunc)g_free);' % arg[1]
+ elif qualifier == 'xmlNode*':
+ print >> fd, ' free_list(&%s, (GFunc)xmlFreeNode);' % arg[1]
+ elif qualifier == 'LassoNode':
+ print >> fd, ' free_list(&%s, (GFunc)g_object_unref);' % arg[1]
+
+ if not m.return_type:
+ print >> fd, ' return noneRef();'
+ else:
+ # Constructor so decrease refcount (it was incremented by PyGObjectPtr_New called
+ # in self.return_value
+ self.return_value(fd, m.return_type, {'elem_type': m.return_type_qualifier})
+ if m.return_owner and self.is_pygobject(m.return_type):
+ print >> fd, ' if (return_value) g_object_unref(return_value);'
+ print >> fd, ' return return_pyvalue;'
+ print >> fd, '}'
+ print >> fd, ''
+
+ def generate_wrapper_list(self, fd):
+ print >> fd, '''
+static PyMethodDef lasso_methods[] = {'''
+ for m in self.wrapper_list:
+ print >> fd, ' {"%s", %s, METH_VARARGS, NULL},' % (m, m)
+ print >> fd, ' {NULL, NULL, 0, NULL}'
+ print >> fd, '};'
+ print >> fd, ''
+