Blame bindings/python/lang.py

Packit Service 88ab54
# Lasso - A free implementation of the Liberty Alliance specifications.
Packit Service 88ab54
#
Packit Service 88ab54
# Copyright (C) 2004-2007 Entr'ouvert
Packit Service 88ab54
# http://lasso.entrouvert.org
Packit Service 88ab54
#
Packit Service 88ab54
# Authors: See AUTHORS file in top-level directory.
Packit Service 88ab54
#
Packit Service 88ab54
# This program is free software; you can redistribute it and/or modify
Packit Service 88ab54
# it under the terms of the GNU General Public License as published by
Packit Service 88ab54
# the Free Software Foundation; either version 2 of the License, or
Packit Service 88ab54
# (at your option) any later version.
Packit Service 88ab54
#
Packit Service 88ab54
# This program is distributed in the hope that it will be useful,
Packit Service 88ab54
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 88ab54
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 88ab54
# GNU General Public License for more details.
Packit Service 88ab54
#
Packit Service 88ab54
# You should have received a copy of the GNU General Public License
Packit Service 88ab54
# along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit Service 88ab54
Packit Service 88ab54
import os
Packit Service 88ab54
from six import print_
Packit Service 88ab54
import sys
Packit Service 88ab54
import re
Packit Service 88ab54
import textwrap
Packit Service 88ab54
from utils import *
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
def remove_bad_optional(args):
Packit Service 88ab54
    args.reverse()
Packit Service 88ab54
    non_opt = False
Packit Service 88ab54
    new_args = []
Packit Service 88ab54
    for x in args:
Packit Service 88ab54
        if not '=' in x:
Packit Service 88ab54
            non_opt = True
Packit Service 88ab54
        elif non_opt:
Packit Service 88ab54
            print_('W: changed', x, file=sys.stderr)
Packit Service 88ab54
            x = re.sub(' *=.*', '', x)
Packit Service 88ab54
            print_('to', x, file=sys.stderr)
Packit Service 88ab54
        new_args.append(x)
Packit Service 88ab54
    new_args.reverse()
Packit Service 88ab54
    return new_args
Packit Service 88ab54
Packit Service 88ab54
def defval_to_python_value(defval):
Packit Service 88ab54
    if defval is None:
Packit Service 88ab54
        return 'None'
Packit Service 88ab54
    if defval.startswith('b:'):
Packit Service 88ab54
        if defval[2:].lower() == 'true':
Packit Service 88ab54
            return 'True'
Packit Service 88ab54
        if defval[2:].lower() == 'false':
Packit Service 88ab54
            return 'False'
Packit Service 88ab54
    if defval.startswith('c:'):
Packit Service 88ab54
        try:
Packit Service 88ab54
            return str(int(defval[2:]))
Packit Service 88ab54
        except:
Packit Service 88ab54
            return defval[8:]
Packit Service 88ab54
    raise Exception('Could not convert %s to python value' % defval)
Packit Service 88ab54
Packit Service 88ab54
def get_python_arg_decl(arg):
Packit Service 88ab54
    if is_optional(arg):
Packit Service 88ab54
        return '%s = %s' % (arg_name(arg), defval_to_python_value(arg_default(arg)))
Packit Service 88ab54
    else:
Packit Service 88ab54
        return arg_name(arg)
Packit Service 88ab54
Packit Service 88ab54
class Binding:
Packit Service 88ab54
    def __init__(self, binding_data):
Packit Service 88ab54
        self.binding_data = binding_data
Packit Service 88ab54
        self.src_dir = os.path.dirname(__file__)
Packit Service 88ab54
Packit Service 88ab54
    def free_value(self, fd, type, name = None):
Packit Service 88ab54
        if not name:
Packit Service 88ab54
            name = arg_name(type)
Packit Service 88ab54
        if not name:
Packit Service 88ab54
            raise Exception('Cannot free, missing a name')
Packit Service 88ab54
        if is_cstring(type):
Packit Service 88ab54
            print_('    lasso_release_string(%s);' % name, file=fd)
Packit Service 88ab54
        elif is_int(type, self.binding_data) or is_boolean(type):
Packit Service 88ab54
            pass
Packit Service 88ab54
        elif is_xml_node(type):
Packit Service 88ab54
            print_('    lasso_release_xml_node(%s);' % name, file=fd)
Packit Service 88ab54
        elif is_glist(type):
Packit Service 88ab54
            etype = element_type(type)
Packit Service 88ab54
            if is_cstring(etype):
Packit Service 88ab54
                print_('    lasso_release_list_of_strings(%s);' % name, file=fd)
Packit Service 88ab54
            elif is_object(etype):
Packit Service 88ab54
                print_('    lasso_release_list_of_gobjects(%s);' % name, file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('Unsupported caller owned return type %s' % ((repr(type), name),))
Packit Service 88ab54
        elif is_hashtable(type):
Packit Service 88ab54
            el_type = element_type(type)
Packit Service 88ab54
            k_type = key_type(type)
Packit Service 88ab54
            v_type = value_type(type)
Packit Service 88ab54
            if is_cstring(el_type) or (is_cstring(k_type) and is_cstring(v_type)):
Packit Service 88ab54
                print_('    g_hash_table_destroy(%s);' % name, file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('Unsupported free value of type GHashTable: %s' % type)
Packit Service 88ab54
        elif is_object(type):
Packit Service 88ab54
            print_('    if (return_value) g_object_unref(%s);' % name, file=fd)
Packit Service 88ab54
        else:
Packit Service 88ab54
            raise Exception('Unsupported caller owned return type %s' % ((repr(type), name),))
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
    def generate(self):
Packit Service 88ab54
        fd = open('lasso.py', 'w')
Packit Service 88ab54
        self.generate_header(fd)
Packit Service 88ab54
        self.generate_exceptions(fd)
Packit Service 88ab54
        self.generate_constants(fd)
Packit Service 88ab54
        for clss in self.binding_data.structs:
Packit Service 88ab54
            self.generate_class(clss, fd)
Packit Service 88ab54
        self.generate_functions(fd)
Packit Service 88ab54
        self.generate_footer(fd)
Packit Service 88ab54
        fd.close()
Packit Service 88ab54
Packit Service 88ab54
        fd = open('_lasso.c', 'w')
Packit Service 88ab54
        self.generate_wrapper(fd)
Packit Service 88ab54
        fd.close()
Packit Service 88ab54
Packit Service 88ab54
    def generate_header(self, fd):
Packit Service 88ab54
        print_('''\
Packit Service 88ab54
# this file has been generated automatically; do not edit
Packit Service 88ab54
Packit Service 88ab54
import _lasso
Packit Service 88ab54
import sys
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
def cptrToPy(cptr):
Packit Service 88ab54
    if cptr is None:
Packit Service 88ab54
        return None
Packit Service 88ab54
    klass = getattr(lasso, cptr.typename)
Packit Service 88ab54
    o = klass.__new__(klass)
Packit Service 88ab54
    o._cptr = cptr
Packit Service 88ab54
    return o
Packit Service 88ab54
Packit Service 88ab54
if sys.version_info >= (3,):
Packit Service 88ab54
    def str2lasso(s):
Packit Service 88ab54
        return s
Packit Service 88ab54
else: # Python 2.x
Packit Service 88ab54
    def str2lasso(s):
Packit Service 88ab54
        if isinstance(s, unicode):
Packit Service 88ab54
            return s.encode('utf-8')
Packit Service 88ab54
        return s
Packit Service 88ab54
Packit Service 88ab54
class frozendict(dict):
Packit Service 88ab54
    \'\'\'Immutable dict\'\'\'
Packit Service 88ab54
    # from Python Cookbook:
Packit Service 88ab54
    #   http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/414283
Packit Service 88ab54
    def _blocked_attribute(obj):
Packit Service 88ab54
        raise AttributeError('A frozendict cannot be modified.')
Packit Service 88ab54
    _blocked_attribute = property(_blocked_attribute)
Packit Service 88ab54
Packit Service 88ab54
    __delitem__ = __setitem__ = clear = _blocked_attribute
Packit Service 88ab54
    pop = popitem = setdefault = update = _blocked_attribute
Packit Service 88ab54
Packit Service 88ab54
    def __new__(cls, *args):
Packit Service 88ab54
        new = dict.__new__(cls)
Packit Service 88ab54
        dict.__init__(new, *args)
Packit Service 88ab54
        return new
Packit Service 88ab54
Packit Service 88ab54
    def __init__(self, *args):
Packit Service 88ab54
        pass
Packit Service 88ab54
Packit Service 88ab54
    def __hash__(self):
Packit Service 88ab54
        try:
Packit Service 88ab54
            return self._cached_hash
Packit Service 88ab54
        except AttributeError:
Packit Service 88ab54
            h = self._cached_hash = hash(tuple(sorted(self.items())))
Packit Service 88ab54
            return h
Packit Service 88ab54
Packit Service 88ab54
    def __repr__(self):
Packit Service 88ab54
        return 'frozendict(%s)' % dict.__repr__(self)
Packit Service 88ab54
''', file=fd)
Packit Service 88ab54
Packit Service 88ab54
    def generate_exceptions(self, fd):
Packit Service 88ab54
        done_cats = []
Packit Service 88ab54
        print_('''\
Packit Service 88ab54
class Error(Exception):
Packit Service 88ab54
    code = None
Packit Service 88ab54
Packit Service 88ab54
    @staticmethod
Packit Service 88ab54
    def raise_on_rc(rc):
Packit Service 88ab54
        global exceptions_dict
Packit Service 88ab54
        if rc != 0:
Packit Service 88ab54
            exception = exceptions_dict.get(rc, Error())
Packit Service 88ab54
            exception.code = rc
Packit Service 88ab54
            raise exception
Packit Service 88ab54
Packit Service 88ab54
    def __str__(self):
Packit Service 88ab54
        if self.code:
Packit Service 88ab54
            return '<lasso.%s(%s): %s>' % (self.__class__.__name__, self.code, _lasso.strError(self.code))
Packit Service 88ab54
        else:
Packit Service 88ab54
            return '<lasso.%s: %s>' % (self.__class__.__name__, self.message)
Packit Service 88ab54
Packit Service 88ab54
    def __getitem__(self, i):
Packit Service 88ab54
        # compatibility with SWIG bindings
Packit Service 88ab54
        if i == 0:
Packit Service 88ab54
            return self.code
Packit Service 88ab54
        elif i == 1:
Packit Service 88ab54
            return _lasso.strError(self.code)
Packit Service 88ab54
        else:
Packit Service 88ab54
            raise IndexError()
Packit Service 88ab54
''', file=fd)
Packit Service 88ab54
        for exc_cat in self.binding_data.overrides.findall('exception/category'):
Packit Service 88ab54
            cat = exc_cat.attrib.get('name')
Packit Service 88ab54
            done_cats.append(cat)
Packit Service 88ab54
            parent_cat = exc_cat.attrib.get('parent', '')
Packit Service 88ab54
            print_('''\
Packit Service 88ab54
class %sError(%sError):
Packit Service 88ab54
    pass
Packit Service 88ab54
''' % (cat, parent_cat), file=fd)
Packit Service 88ab54
Packit Service 88ab54
        exceptions_dict = {}
Packit Service 88ab54
Packit Service 88ab54
        for c in self.binding_data.constants:
Packit Service 88ab54
            m = re.match(r'LASSO_(\w+)_ERROR_(.*)', c[1])
Packit Service 88ab54
            if not m:
Packit Service 88ab54
                continue
Packit Service 88ab54
            cat, detail = m.groups()
Packit Service 88ab54
            cat = cat.title().replace('_', '')
Packit Service 88ab54
            detail = (cat + '_' + detail).title().replace('_', '')
Packit Service 88ab54
            if not cat in done_cats:
Packit Service 88ab54
                done_cats.append(cat)
Packit Service 88ab54
                for exc_cat in self.binding_data.overrides.findall('exception/category'):
Packit Service 88ab54
                    if exc_cat.attrib.get('name') == cat:
Packit Service 88ab54
                        parent_cat = exc_cat.attrib.get('parent')
Packit Service 88ab54
                        break
Packit Service 88ab54
                else:
Packit Service 88ab54
                    parent_cat = ''
Packit Service 88ab54
Packit Service 88ab54
                print_('''\
Packit Service 88ab54
class %sError(%sError):
Packit Service 88ab54
    pass
Packit Service 88ab54
''' % (cat, parent_cat), file=fd)
Packit Service 88ab54
Packit Service 88ab54
            exceptions_dict[detail] = c[1][6:]
Packit Service 88ab54
Packit Service 88ab54
            if (detail, cat) == ('UnsupportedProfile', 'Logout'):
Packit Service 88ab54
                # skip Logout/UnsupportedProfile exception as its name would
Packit Service 88ab54
                # be the same as Profile/UnsupportedProfile; it is not a
Packit Service 88ab54
                # problem skipping it as they both inherit from ProfileError
Packit Service 88ab54
                # and the exception code will correctly be set by raise_on_rc
Packit Service 88ab54
                # afterwards.  (actually it is even totally unnecessary to skip
Packit Service 88ab54
                # it here as Profile/UnsupportedProfile is handled after
Packit Service 88ab54
                # Logout/UnsupportedProfile, this is just done in the case the
Packit Service 88ab54
                # ordering would change)
Packit Service 88ab54
                continue
Packit Service 88ab54
Packit Service 88ab54
            print_('''\
Packit Service 88ab54
class %sError(%sError):
Packit Service 88ab54
    pass
Packit Service 88ab54
''' % (detail, cat), file=fd)
Packit Service 88ab54
Packit Service 88ab54
        print_('exceptions_dict = {', file=fd)
Packit Service 88ab54
        for k, v in exceptions_dict.items():
Packit Service 88ab54
            print_('    _lasso.%s: %sError,' % (v, k), file=fd)
Packit Service 88ab54
        print_('}', file=fd)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
    def generate_footer(self, fd):
Packit Service 88ab54
        print_('''
Packit Service 88ab54
Packit Service 88ab54
import lasso
Packit Service 88ab54
Packit Service 88ab54
# backward compatibility with the SWIG binding
Packit Service 88ab54
Packit Service 88ab54
WSF_SUPPORT = WSF_ENABLED
Packit Service 88ab54
Packit Service 88ab54
Profile.isIdentityDirty = property(Profile.hasDirtyIdentity)
Packit Service 88ab54
Profile.isSessionDirty = property(Profile.hasDirtySession)
Packit Service 88ab54
Packit Service 88ab54
def identity_get_provider_ids(self):
Packit Service 88ab54
    return self.federations.keys()
Packit Service 88ab54
Identity.providerIds = property(identity_get_provider_ids)
Packit Service 88ab54
Packit Service 88ab54
def server_get_provider_ids(self):
Packit Service 88ab54
    return self.providers.keys()
Packit Service 88ab54
Server.providerIds = property(server_get_provider_ids)
Packit Service 88ab54
Packit Service 88ab54
def session_get_provider_ids(self):
Packit Service 88ab54
    return self.assertions.keys()
Packit Service 88ab54
Session.providerIds = property(session_get_provider_ids)
Packit Service 88ab54
Packit Service 88ab54
def LassoNode__getstate__(self):
Packit Service 88ab54
    return { '__dump__': self.dump() }
Packit Service 88ab54
Packit Service 88ab54
def LassoNode__setstate__(self, d):
Packit Service 88ab54
    self._cptr = _lasso.node_new_from_dump(d.pop('__dump__'))
Packit Service 88ab54
Packit Service 88ab54
Node.__getstate__ = LassoNode__getstate__
Packit Service 88ab54
Node.__setstate__ = LassoNode__setstate__
Packit Service 88ab54
Packit Service 88ab54
Samlp2AuthnRequest.nameIDPolicy = Samlp2AuthnRequest.nameIdPolicy
Packit Service 88ab54
LibAuthnRequest.nameIDPolicy = LibAuthnRequest.nameIdPolicy
Packit Service 88ab54
Saml2Subject.nameID = Saml2Subject.nameId
Packit Service 88ab54
MiscTextNode.text_child = MiscTextNode.textChild
Packit Service 88ab54
NodeList = list
Packit Service 88ab54
StringList = list
Packit Service 88ab54
StringDict = dict
Packit Service 88ab54
registerIdWsf2DstService = registerIdwsf2DstService
Packit Service 88ab54
Packit Service 88ab54
if WSF_SUPPORT:
Packit Service 88ab54
    DiscoDescription_newWithBriefSoapHttpDescription = DiscoDescription.newWithBriefSoapHttpDescription
Packit Service 88ab54
    Discovery.buildRequestMsg = Discovery.buildSoapRequestMsg
Packit Service 88ab54
    InteractionProfileService.buildRequestMsg = InteractionProfileService.buildSoapRequestMsg
Packit Service 88ab54
    InteractionProfileService.buildResponseMsg = InteractionProfileService.buildSoapResponseMsg
Packit Service 88ab54
    DataService.buildRequestMsg = DataService.buildSoapRequestMsg
Packit Service 88ab54
    DiscoModifyResponse.newEntryIds = DiscoModifyResponse.newEntryIDs
Packit Service 88ab54
''', file=fd)
Packit Service 88ab54
Packit Service 88ab54
    def generate_constants(self, fd):
Packit Service 88ab54
        print_('### Constants (both enums and defines)', file=fd)
Packit Service 88ab54
        for c in self.binding_data.constants:
Packit Service 88ab54
            print_('%s = _lasso.%s' % (c[1][6:], c[1][6:]), file=fd)
Packit Service 88ab54
        for c in self.binding_data.overrides.findall('constant'):
Packit Service 88ab54
            name = c.attrib.get('name')
Packit Service 88ab54
            if c.attrib.get('value'):
Packit Service 88ab54
                name = name[6:] # dropping LASSO_
Packit Service 88ab54
                value = c.attrib.get('value')
Packit Service 88ab54
                if value == 'True':
Packit Service 88ab54
                    print_('%s = True' % name, file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    print_('E: unknown value for constant: %r' % value, file=sys.stderr)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
    def generate_class(self, clss, fd):
Packit Service 88ab54
        klassname = clss.name[5:] # remove Lasso from class name
Packit Service 88ab54
        if clss.parent == 'GObject':
Packit Service 88ab54
            parentname = 'object'
Packit Service 88ab54
        else:
Packit Service 88ab54
            parentname = clss.parent[5:]
Packit Service 88ab54
Packit Service 88ab54
        print_('''class %(klassname)s(%(parentname)s):''' % locals(), file=fd)
Packit Service 88ab54
Packit Service 88ab54
        methods = clss.methods[:]
Packit Service 88ab54
        # constructor(s)
Packit Service 88ab54
        method_prefix = 'lasso_' + format_as_underscored(klassname) + '_'
Packit Service 88ab54
        empty = True
Packit Service 88ab54
        for m in self.binding_data.functions:
Packit Service 88ab54
            if m.name == method_prefix + 'new':
Packit Service 88ab54
                empty = False
Packit Service 88ab54
                c_args = []
Packit Service 88ab54
                py_args = []
Packit Service 88ab54
                for arg in m.args:
Packit Service 88ab54
                    py_args.append(get_python_arg_decl(arg))
Packit Service 88ab54
                    if not is_int(arg, self.binding_data) and is_object(arg):
Packit Service 88ab54
                        c_args.append('%(name)s and %(name)s._cptr' % { 'name' : arg_name(arg) })
Packit Service 88ab54
                    elif is_cstring(arg):
Packit Service 88ab54
                        c_args.append('str2lasso(%s)' % arg_name(arg))
Packit Service 88ab54
                    else:
Packit Service 88ab54
                        c_args.append(arg_name(arg))
Packit Service 88ab54
                py_args = remove_bad_optional(py_args)
Packit Service 88ab54
Packit Service 88ab54
                c_args = ', '.join(c_args)
Packit Service 88ab54
                py_args = ', ' + ', '.join(py_args)
Packit Service 88ab54
                print_('    def __init__(self%s):' % py_args, file=fd)
Packit Service 88ab54
                # XXX: could check self._cptr.typename to see if it got the
Packit Service 88ab54
                # right class type
Packit Service 88ab54
                print_('        self._cptr = _lasso.%s(%s)' % (
Packit Service 88ab54
                        m.name[6:], c_args), file=fd)
Packit Service 88ab54
                print_('        if self._cptr is None:', file=fd)
Packit Service 88ab54
                print_('            raise Error(\'failed to create object\')', file=fd)
Packit Service 88ab54
                print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
        for m in self.binding_data.functions:
Packit Service 88ab54
            if m.name.startswith(method_prefix + 'new_'):
Packit Service 88ab54
                empty = False
Packit Service 88ab54
                constructor_name = format_as_camelcase(m.name[len(method_prefix):])
Packit Service 88ab54
                c_args = []
Packit Service 88ab54
                py_args = []
Packit Service 88ab54
                for arg in m.args:
Packit Service 88ab54
                    aname = arg_name(arg)
Packit Service 88ab54
                    py_args.append(get_python_arg_decl(arg))
Packit Service 88ab54
Packit Service 88ab54
                    if not is_int(arg, self.binding_data) and is_object(arg):
Packit Service 88ab54
                        c_args.append('%s and %s._cptr' % (aname, aname))
Packit Service 88ab54
                    elif is_cstring(arg):
Packit Service 88ab54
                        c_args.append('str2lasso(%s)' % arg_name(arg))
Packit Service 88ab54
                    else:
Packit Service 88ab54
                        c_args.append(aname)
Packit Service 88ab54
                opt = False
Packit Service 88ab54
                py_args = remove_bad_optional(py_args)
Packit Service 88ab54
                for x in py_args:
Packit Service 88ab54
                    if '=' in x:
Packit Service 88ab54
                        opt = True
Packit Service 88ab54
                    elif opt:
Packit Service 88ab54
                        print_('W: non-optional follows optional,', m, file=sys.stderr)
Packit Service 88ab54
                c_args = ', '.join(c_args)
Packit Service 88ab54
                py_args = ', ' + ', '.join(py_args)
Packit Service 88ab54
                print_('    @classmethod', file=fd)
Packit Service 88ab54
                print_('    def %s(cls%s):' % (constructor_name, py_args), file=fd)
Packit Service 88ab54
                print_('         return cptrToPy(_lasso.%s(%s))' % (m.name[6:], c_args), file=fd)
Packit Service 88ab54
                print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
        # create properties for members
Packit Service 88ab54
        for m in clss.members:
Packit Service 88ab54
            empty = False
Packit Service 88ab54
            mname = format_as_camelcase(m[1])
Packit Service 88ab54
            options = m[2]
Packit Service 88ab54
            # getter
Packit Service 88ab54
            print_('    def get_%s(self):' % mname, file=fd)
Packit Service 88ab54
            print_('        t = _lasso.%s_%s_get(self._cptr)' % (
Packit Service 88ab54
                    klassname, mname), file=fd)
Packit Service 88ab54
            if is_int(m, self.binding_data) or is_xml_node(m) or is_cstring(m) or is_boolean(m):
Packit Service 88ab54
                pass
Packit Service 88ab54
            elif is_object(m):
Packit Service 88ab54
                print_('        t = cptrToPy(t)', file=fd)
Packit Service 88ab54
            elif is_glist(m):
Packit Service 88ab54
                el_type = element_type(m)
Packit Service 88ab54
                if is_cstring(el_type):
Packit Service 88ab54
                    pass
Packit Service 88ab54
                elif is_xml_node(el_type):
Packit Service 88ab54
                    pass
Packit Service 88ab54
                elif is_object(el_type):
Packit Service 88ab54
                    print_('        if not t: return t', file=fd)
Packit Service 88ab54
                    print_('        t = tuple([cptrToPy(x) for x in t])', file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    raise Exception('Unsupported python getter %s.%s' % (clss, m))
Packit Service 88ab54
            elif is_hashtable(m):
Packit Service 88ab54
                el_type = element_type(m)
Packit Service 88ab54
                print_('        if not t: return t', file=fd)
Packit Service 88ab54
                if is_object(el_type):
Packit Service 88ab54
                    print_('        d2 = {}', file=fd)
Packit Service 88ab54
                    print_('        for k, v in t.items():', file=fd)
Packit Service 88ab54
                    print_('            d2[k] = cptrToPy(v)', file=fd)
Packit Service 88ab54
                    print_('        t = frozendict(d2)', file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    print_('        t = frozendict(t)', file=fd)
Packit Service 88ab54
            elif is_boolean(m) or is_int(m, self.binding_data) or is_xml_node(m) or is_cstring(m):
Packit Service 88ab54
                pass
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('Unsupported python getter %s.%s' % (clss, m))
Packit Service 88ab54
            print_('        return t;', file=fd)
Packit Service 88ab54
            # setter
Packit Service 88ab54
            print_('    def set_%s(self, value):' % mname, file=fd)
Packit Service 88ab54
            if is_int(m, self.binding_data) or is_xml_node(m) or is_boolean(m):
Packit Service 88ab54
                pass
Packit Service 88ab54
            elif is_cstring(m):
Packit Service 88ab54
                print_('        value = str2lasso(value)', file=fd)
Packit Service 88ab54
            elif is_object(m):
Packit Service 88ab54
                print_('        if value is not None:', file=fd)
Packit Service 88ab54
                print_('            value = value and value._cptr', file=fd)
Packit Service 88ab54
            elif is_glist(m):
Packit Service 88ab54
                el_type = element_type(m)
Packit Service 88ab54
                if is_cstring(el_type) or is_xml_node(el_type):
Packit Service 88ab54
                    pass
Packit Service 88ab54
                elif is_object(el_type):
Packit Service 88ab54
                    print_('        if value is not None:', file=fd)
Packit Service 88ab54
                    print_('            value = tuple([x._cptr for x in value])', file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    raise Exception('Unsupported python setter %s.%s' % (clss, m))
Packit Service 88ab54
            elif is_hashtable(m):
Packit Service 88ab54
                print_('W: unsupported setter for hashtable %s' % (m,), file=sys.stderr)
Packit Service 88ab54
            else:
Packit Service 88ab54
                print_('W: unsupported setter for %s' % (m,), file=sys.stderr)
Packit Service 88ab54
            print_('        _lasso.%s_%s_set(self._cptr, value)' % (
Packit Service 88ab54
                    klassname, mname), file=fd)
Packit Service 88ab54
            print_('    %s = property(get_%s, set_%s)' % (mname, mname, mname), file=fd)
Packit Service 88ab54
            old_mname = old_format_as_camelcase(m[1])
Packit Service 88ab54
            if mname != old_mname:
Packit Service 88ab54
                print_('    %s = %s' % (old_mname, mname), file=fd)
Packit Service 88ab54
            print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
        # first pass on methods, getting accessors
Packit Service 88ab54
        # second pass on methods, real methods
Packit Service 88ab54
        for m in methods:
Packit Service 88ab54
            empty = False
Packit Service 88ab54
            if m.name.endswith('_new') or m.name.endswith('_new_from_dump') or \
Packit Service 88ab54
                    m.name.endswith('_new_full'):
Packit Service 88ab54
                continue
Packit Service 88ab54
            if not m.name.startswith(method_prefix):
Packit Service 88ab54
                print_('W:', m.name, 'vs', method_prefix, file=sys.stderr)
Packit Service 88ab54
                continue
Packit Service 88ab54
Packit Service 88ab54
            if m.rename:
Packit Service 88ab54
                mname = m.rename[len(method_prefix):]
Packit Service 88ab54
                function_name = m.rename[6:]
Packit Service 88ab54
            else:
Packit Service 88ab54
                mname = m.name[len(method_prefix):]
Packit Service 88ab54
                function_name = m.name[6:]
Packit Service 88ab54
            py_args = []
Packit Service 88ab54
            c_args = []
Packit Service 88ab54
            outarg = None
Packit Service 88ab54
            for arg in m.args[1:]:
Packit Service 88ab54
                if is_out(arg):
Packit Service 88ab54
                    assert not outarg
Packit Service 88ab54
                    outarg = arg
Packit Service 88ab54
                    outvar = '_%s_out' % arg_name(arg)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    py_args.append(get_python_arg_decl(arg))
Packit Service 88ab54
Packit Service 88ab54
                if is_out(arg):
Packit Service 88ab54
                    c_args.append(outvar)
Packit Service 88ab54
                elif is_cstring(arg):
Packit Service 88ab54
                    c_args.append('str2lasso(%s)' % arg_name(arg))
Packit Service 88ab54
                elif is_xml_node(arg) or is_boolean(arg) or is_cstring(arg) or is_int(arg, self.binding_data) or is_glist(arg) or is_hashtable(arg) or is_time_t_pointer(arg):
Packit Service 88ab54
                    c_args.append(arg_name(arg))
Packit Service 88ab54
                elif is_object(arg):
Packit Service 88ab54
                    c_args.append('%(name)s and %(name)s._cptr' % { 'name': arg_name(arg) })
Packit Service 88ab54
                else:
Packit Service 88ab54
                    raise Exception('Does not handle argument of type: %s' % ((m, arg),))
Packit Service 88ab54
            # check py_args
Packit Service 88ab54
            py_args = remove_bad_optional(py_args)
Packit Service 88ab54
            opt = False
Packit Service 88ab54
            for x in py_args:
Packit Service 88ab54
                if '=' in x:
Packit Service 88ab54
                    opt = True
Packit Service 88ab54
                elif opt:
Packit Service 88ab54
                    print_('W: non-optional follow optional,', m, file=sys.stderr)
Packit Service 88ab54
Packit Service 88ab54
            if py_args:
Packit Service 88ab54
                py_args = ', ' + ', '.join(py_args)
Packit Service 88ab54
            else:
Packit Service 88ab54
                py_args = ''
Packit Service 88ab54
            if c_args:
Packit Service 88ab54
                c_args = ', ' + ', '.join(c_args)
Packit Service 88ab54
            else:
Packit Service 88ab54
                c_args = ''
Packit Service 88ab54
Packit Service 88ab54
            print_('    def %s(self%s):' % (
Packit Service 88ab54
                    format_underscore_as_camelcase(mname), py_args), file=fd)
Packit Service 88ab54
            if m.docstring:
Packit Service 88ab54
                print_("        '''", file=fd)
Packit Service 88ab54
                print_(self.format_docstring(m, mname, 8), file=fd)
Packit Service 88ab54
                print_("        '''", file=fd)
Packit Service 88ab54
Packit Service 88ab54
            if outarg:
Packit Service 88ab54
                print_("        %s = list((None,))" % outvar, file=fd)
Packit Service 88ab54
            return_type = m.return_type
Packit Service 88ab54
            return_type_qualifier = m.return_type_qualifier
Packit Service 88ab54
            assert is_int(make_arg(return_type),self.binding_data) or not outarg
Packit Service 88ab54
            if return_type in (None, 'void'):
Packit Service 88ab54
                print_('        _lasso.%s(self._cptr%s)' % (
Packit Service 88ab54
                        function_name, c_args), file=fd)
Packit Service 88ab54
            elif is_rc(m.return_arg):
Packit Service 88ab54
                print_('        rc = _lasso.%s(self._cptr%s)' % (
Packit Service 88ab54
                        function_name, c_args), file=fd)
Packit Service 88ab54
                print_('        Error.raise_on_rc(rc)', file=fd)
Packit Service 88ab54
            elif (is_int(m.return_arg, self.binding_data) or is_xml_node(m.return_arg) or
Packit Service 88ab54
                    is_cstring(m.return_arg) or is_boolean(m.return_arg) or
Packit Service 88ab54
                    is_hashtable(m.return_arg)):
Packit Service 88ab54
                print_('        return _lasso.%s(self._cptr%s)' % (
Packit Service 88ab54
                        function_name, c_args), file=fd)
Packit Service 88ab54
            elif is_glist(m.return_arg):
Packit Service 88ab54
                el_type = element_type(m.return_arg)
Packit Service 88ab54
                if is_object(el_type):
Packit Service 88ab54
                    print_('        value = _lasso.%s(self._cptr%s)' % (
Packit Service 88ab54
                            function_name, c_args), file=fd)
Packit Service 88ab54
                    print_('        if value is not None:', file=fd)
Packit Service 88ab54
                    print_('            value = tuple([cptrToPy(x) for x in value])', file=fd)
Packit Service 88ab54
                    print_('        return value', file=fd)
Packit Service 88ab54
                elif is_cstring(el_type) or is_xml_node(el_type):
Packit Service 88ab54
                    print_('        return _lasso.%s(self._cptr%s)' % (
Packit Service 88ab54
                            function_name, c_args), file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    raise Exception('Return Type GList<%s> is not supported' % el_type)
Packit Service 88ab54
            elif is_object(m.return_arg):
Packit Service 88ab54
                print_('        return cptrToPy(_lasso.%s(self._cptr%s))' % (
Packit Service 88ab54
                        function_name, c_args), file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('Return type %s is unsupported' % (m.return_arg,))
Packit Service 88ab54
            if outarg:
Packit Service 88ab54
                print_('        return %s[0]' % outvar, file=fd)
Packit Service 88ab54
            print_('', file=fd)
Packit Service 88ab54
        # transform methods to properties
Packit Service 88ab54
        for m in methods:
Packit Service 88ab54
            if len(m.args) > 1:
Packit Service 88ab54
                continue
Packit Service 88ab54
            name = m.rename or m.name
Packit Service 88ab54
            suffix = name[len(method_prefix)+len('get_'):]
Packit Service 88ab54
            if clss.getMember(suffix):
Packit Service 88ab54
                print_('W: method %s and member %s clashes' % (m.name, arg_name(clss.getMember(suffix))), file=sys.stderr)
Packit Service 88ab54
                continue
Packit Service 88ab54
            if not name.startswith(method_prefix) or not name[len(method_prefix):].startswith('get_'):
Packit Service 88ab54
                continue
Packit Service 88ab54
            setter_suffix = 'set_' + suffix
Packit Service 88ab54
            setter = None
Packit Service 88ab54
            for n in methods:
Packit Service 88ab54
                if n.name.endswith(setter_suffix) and len(n.args) == 2:
Packit Service 88ab54
                    setter = n
Packit Service 88ab54
            pname = format_as_camelcase(name[len(method_prefix)+len('get_'):])
Packit Service 88ab54
            fname = format_as_camelcase(name[len(method_prefix):])
Packit Service 88ab54
            if not setter:
Packit Service 88ab54
                print_('    %s = property(%s)' % (pname, fname), file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                f2name = format_as_camelcase(setter.name[len(method_prefix):])
Packit Service 88ab54
                print_('    %s = property(%s, %s)' % (pname, fname, f2name), file=fd)
Packit Service 88ab54
        if empty:
Packit Service 88ab54
            print_('    pass', file=fd)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
    def format_docstring(self, func, method_name, indent):
Packit Service 88ab54
        if func.args:
Packit Service 88ab54
            first_arg_name = func.args[0][1]
Packit Service 88ab54
        else:
Packit Service 88ab54
            first_arg_name = None
Packit Service 88ab54
Packit Service 88ab54
        def format_inlines_sub(s):
Packit Service 88ab54
            type = s.group(1)[0]
Packit Service 88ab54
            var = s.group(1)[1:]
Packit Service 88ab54
            if type == '#': # struct
Packit Service 88ab54
                if var.startswith('Lasso'):
Packit Service 88ab54
                    return 'L{%s}' % var[5:]
Packit Service 88ab54
            elif type == '%': # %TRUE, %FALSE
Packit Service 88ab54
                if var == 'TRUE':
Packit Service 88ab54
                    return 'True'
Packit Service 88ab54
                if var == 'FALSE':
Packit Service 88ab54
                    return 'False'
Packit Service 88ab54
                print_('W: unknown docstring thingie: %s' % s.group(1), file=sys.stderr)
Packit Service 88ab54
            elif type == '@':
Packit Service 88ab54
                if var == first_arg_name:
Packit Service 88ab54
                    var = 'self'
Packit Service 88ab54
                return 'C{%s}' % var
Packit Service 88ab54
            return s.group(1)
Packit Service 88ab54
Packit Service 88ab54
        regex = re.compile(r'([\#%@]\w+)', re.DOTALL)
Packit Service 88ab54
Packit Service 88ab54
        def format_inline(s):
Packit Service 88ab54
            s = regex.sub(format_inlines_sub, s)
Packit Service 88ab54
            return s.replace('NULL', 'None')
Packit Service 88ab54
Packit Service 88ab54
        docstring = func.docstring
Packit Service 88ab54
        s = []
Packit Service 88ab54
Packit Service 88ab54
        if docstring.description:
Packit Service 88ab54
            for paragraph in docstring.description.split('\n\n'):
Packit Service 88ab54
                if '<itemizedlist>' in paragraph:
Packit Service 88ab54
                    before, after = paragraph.split('<itemizedlist>' ,1)
Packit Service 88ab54
                    if before:
Packit Service 88ab54
                        s.append('\n'.join(textwrap.wrap(
Packit Service 88ab54
                                        format_inline(before), 70)))
Packit Service 88ab54
Packit Service 88ab54
                    # remove tags
Packit Service 88ab54
                    after = after.replace('<itemizedlist>', '')
Packit Service 88ab54
                    after = after.replace('</itemizedlist>', '')
Packit Service 88ab54
Packit Service 88ab54
                    for listitem in after.split('<listitem><para>'):
Packit Service 88ab54
                        listitem = listitem.replace('</para></listitem>', '').strip()
Packit Service 88ab54
                        s.append('\n'.join(textwrap.wrap(
Packit Service 88ab54
                                        format_inline(listitem), 70,
Packit Service 88ab54
                                        initial_indent = ' - ',
Packit Service 88ab54
                                        subsequent_indent = '   ')))
Packit Service 88ab54
                        s.append('\n\n')
Packit Service 88ab54
Packit Service 88ab54
                else:
Packit Service 88ab54
                    s.append('\n'.join(textwrap.wrap(
Packit Service 88ab54
                                    format_inline(paragraph), 70)))
Packit Service 88ab54
                    s.append('\n\n')
Packit Service 88ab54
Packit Service 88ab54
        for param in docstring.parameters:
Packit Service 88ab54
            s.append('\n'.join(textwrap.wrap(
Packit Service 88ab54
                            format_inline(param[1]), 70,
Packit Service 88ab54
                            initial_indent = '@param %s: ' % param[0],
Packit Service 88ab54
                            subsequent_indent = 4*' ')))
Packit Service 88ab54
            s.append('\n')
Packit Service 88ab54
        if docstring.return_value:
Packit Service 88ab54
            rv = docstring.return_value
Packit Service 88ab54
            exceptions_instead = ['0 on success; or a negative value otherwise.',
Packit Service 88ab54
                    '0 on success; a negative value if an error occured.',
Packit Service 88ab54
                    '0 on success; another value if an error occured.']
Packit Service 88ab54
            if not rv in exceptions_instead:
Packit Service 88ab54
                owner_info = ['This xmlnode must be freed by caller.',
Packit Service 88ab54
                        'The string must be freed by the caller.',
Packit Service 88ab54
                        'It must be freed by the caller.',
Packit Service 88ab54
                        'This string must be freed by the caller.']
Packit Service 88ab54
                for o_i in owner_info:
Packit Service 88ab54
                    rv = rv.replace(o_i, '')
Packit Service 88ab54
                s.append('\n'.join(textwrap.wrap(
Packit Service 88ab54
                                format_inline(rv), 70,
Packit Service 88ab54
                                initial_indent = '@return: ',
Packit Service 88ab54
                                subsequent_indent = 4*' ')))
Packit Service 88ab54
                s.append('\n')
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
        if s:
Packit Service 88ab54
            s[-1] = s[-1].rstrip() # remove trailing newline from last line
Packit Service 88ab54
Packit Service 88ab54
        return '\n'.join([(indent*' ')+x for x in ''.join(s).splitlines()])
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
    def generate_functions(self, fd):
Packit Service 88ab54
        for m in self.binding_data.functions:
Packit Service 88ab54
            if m.name.endswith('_new') or '_new_' in m.name:
Packit Service 88ab54
                continue
Packit Service 88ab54
            if m.rename:
Packit Service 88ab54
                pname = m.rename
Packit Service 88ab54
                name = m.rename
Packit Service 88ab54
                if name.startswith('lasso_'):
Packit Service 88ab54
                    name = name[6:]
Packit Service 88ab54
                    pname = format_as_camelcase(name)
Packit Service 88ab54
            else:
Packit Service 88ab54
                name = m.name[6:]
Packit Service 88ab54
                pname = format_as_camelcase(name)
Packit Service 88ab54
            print_('%s = _lasso.%s' % (pname, name), file=fd)
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
    def generate_wrapper(self, fd):
Packit Service 88ab54
        print_(open(os.path.join(self.src_dir,'wrapper_top.c')).read(), file=fd)
Packit Service 88ab54
        for h in self.binding_data.headers:
Packit Service 88ab54
            print_('#include <%s>' % h, file=fd)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
        self.generate_constants_wrapper(fd)
Packit Service 88ab54
Packit Service 88ab54
        self.wrapper_list = []
Packit Service 88ab54
        for m in self.binding_data.functions:
Packit Service 88ab54
            self.generate_function_wrapper(m, fd)
Packit Service 88ab54
        for c in self.binding_data.structs:
Packit Service 88ab54
            self.generate_member_wrapper(c, fd)
Packit Service 88ab54
            for m in c.methods:
Packit Service 88ab54
                self.generate_function_wrapper(m, fd)
Packit Service 88ab54
        self.generate_wrapper_list(fd)
Packit Service 88ab54
        print_(open(os.path.join(self.src_dir,'wrapper_bottom.c')).read(), file=fd)
Packit Service 88ab54
Packit Service 88ab54
    def generate_constants_wrapper(self, fd):
Packit Service 88ab54
        print_('''static void
Packit Service 88ab54
register_constants(PyObject *d)
Packit Service 88ab54
{
Packit Service 88ab54
    PyObject *obj;
Packit Service 88ab54
''', file=fd)
Packit Service 88ab54
        for c in self.binding_data.constants:
Packit Service 88ab54
            if c[0] == 'i':
Packit Service 88ab54
                print_('    obj = PyInt_FromLong(%s);' % c[1], file=fd)
Packit Service 88ab54
            elif c[0] == 's':
Packit Service 88ab54
                print_('    obj = PyString_FromString((char*)%s);' % c[1], file=fd)
Packit Service 88ab54
            elif c[0] == 'b':
Packit Service 88ab54
                print_('''\
Packit Service 88ab54
#ifdef %s
Packit Service 88ab54
    obj = Py_True;
Packit Service 88ab54
#else
Packit Service 88ab54
    obj = Py_False;
Packit Service 88ab54
#endif''' % c[1], file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                print_('E: unknown constant type: %r' % c[0], file=sys.stderr)
Packit Service 88ab54
            print_('    PyDict_SetItemString(d, "%s", obj);' % c[1][6:], file=fd)
Packit Service 88ab54
            print_('    Py_DECREF(obj);', file=fd)
Packit Service 88ab54
        print_('}', file=fd)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
    def generate_member_wrapper(self, c, fd):
Packit Service 88ab54
        klassname = c.name
Packit Service 88ab54
        for m in c.members:
Packit Service 88ab54
            name = arg_name(m)
Packit Service 88ab54
            mname = format_as_camelcase(arg_name(m))
Packit Service 88ab54
            # getter
Packit Service 88ab54
            print_('''static PyObject*
Packit Service 88ab54
%s_%s_get(G_GNUC_UNUSED PyObject *self, PyObject *args)
Packit Service 88ab54
{''' % (klassname[5:], mname), file=fd)
Packit Service 88ab54
            self.wrapper_list.append('%s_%s_get' % (klassname[5:], mname))
Packit Service 88ab54
Packit Service 88ab54
            ftype = arg_type(m)
Packit Service 88ab54
            if is_cstring(m):
Packit Service 88ab54
                ftype = 'char*'
Packit Service 88ab54
            print_('    %s return_value;' % ftype, file=fd)
Packit Service 88ab54
            print_('    PyObject* return_pyvalue;', file=fd)
Packit Service 88ab54
            print_('    PyGObjectPtr* cvt_this;', file=fd)
Packit Service 88ab54
            print_('    %s* this;' % klassname, file=fd)
Packit Service 88ab54
            print_('', file=fd)
Packit Service 88ab54
            print_('    if (! PyArg_ParseTuple(args, "O", &cvt_this)) return NULL;', file=fd)
Packit Service 88ab54
            print_('    this = (%s*)cvt_this->obj;' % klassname, file=fd)
Packit Service 88ab54
            print_('    return_value = this->%s;' % arg_name(m), file=fd)
Packit Service 88ab54
            try:
Packit Service 88ab54
                self.return_value(fd, m)
Packit Service 88ab54
            except:
Packit Service 88ab54
                print_('W: cannot make an assignment for', c, m, file=sys.stderr)
Packit Service 88ab54
                raise
Packit Service 88ab54
            print_('    return return_pyvalue;', file=fd)
Packit Service 88ab54
            print_('}', file=fd)
Packit Service 88ab54
            print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
            # setter
Packit Service 88ab54
            print_('''static PyObject*
Packit Service 88ab54
%s_%s_set(G_GNUC_UNUSED PyObject *self, PyObject *args)
Packit Service 88ab54
{''' % (klassname[5:], mname), file=fd)
Packit Service 88ab54
            self.wrapper_list.append('%s_%s_set' % (klassname[5:], mname))
Packit Service 88ab54
Packit Service 88ab54
            print_('    PyGObjectPtr* cvt_this;', file=fd)
Packit Service 88ab54
            print_('    %s* this;' % klassname, file=fd)
Packit Service 88ab54
            type = m[0]
Packit Service 88ab54
            # Determine type class
Packit Service 88ab54
            if is_cstring(m):
Packit Service 88ab54
                type = type.replace('const ', '')
Packit Service 88ab54
                parse_format = 'z'
Packit Service 88ab54
                parse_arg = '&value'
Packit Service 88ab54
                print_('    %s value;' % type, file=fd)
Packit Service 88ab54
            elif is_int(m, self.binding_data):
Packit Service 88ab54
                parse_format = 'l'
Packit Service 88ab54
                parse_arg = '&value'
Packit Service 88ab54
                print_('    long value;', file=fd)
Packit Service 88ab54
            elif is_glist(m) or is_hashtable(m) or is_xml_node(m) or is_boolean(m):
Packit Service 88ab54
                parse_format = 'O'
Packit Service 88ab54
                print_('    PyObject *cvt_value;', file=fd)
Packit Service 88ab54
                parse_arg = '&cvt_value'
Packit Service 88ab54
            elif is_object(m):
Packit Service 88ab54
                parse_format = 'O'
Packit Service 88ab54
                print_('    PyGObjectPtr *cvt_value;', file=fd)
Packit Service 88ab54
                parse_arg = '&cvt_value'
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('Unsupported field: %s' % (m,))
Packit Service 88ab54
            # Get GObject
Packit Service 88ab54
            print_('    if (! PyArg_ParseTuple(args, "O%s", &cvt_this, %s)) return NULL;' % (
Packit Service 88ab54
                    parse_format, parse_arg), file=fd)
Packit Service 88ab54
            print_('    this = (%s*)cvt_this->obj;' % klassname, file=fd)
Packit Service 88ab54
            # Change value
Packit Service 88ab54
            if is_int(m, self.binding_data):
Packit Service 88ab54
                print_('    this->%s = value;' % name, file=fd)
Packit Service 88ab54
            elif is_boolean(m):
Packit Service 88ab54
                print_('    this->%s = PyInt_AS_LONG(cvt_value) ? TRUE : FALSE;' % name, file=fd)
Packit Service 88ab54
            elif is_cstring(m):
Packit Service 88ab54
                print_('    lasso_assign_string(this->%s, value);' % name, file=fd)
Packit Service 88ab54
            elif is_xml_node(m):
Packit Service 88ab54
                print_('    if (this->%s) xmlFreeNode(this->%s);' % (name, name), file=fd)
Packit Service 88ab54
                print_('    this->%s = get_xml_node_from_pystring(cvt_value);' % name, file=fd)
Packit Service 88ab54
            elif is_glist(m):
Packit Service 88ab54
                el_type = element_type(m)
Packit Service 88ab54
                if is_cstring(el_type):
Packit Service 88ab54
                    print_('    set_list_of_strings(&this->%s, cvt_value);' % name, file=fd)
Packit Service 88ab54
                elif is_xml_node(el_type):
Packit Service 88ab54
                    print_('    set_list_of_xml_nodes(&this->%s, cvt_value);' % name, file=fd)
Packit Service 88ab54
                elif is_object(el_type):
Packit Service 88ab54
                    print_('    set_list_of_pygobject(&this->%s, cvt_value);' % name, file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    raise Exception('Unsupported setter for %s' % (m,))
Packit Service 88ab54
            elif is_hashtable(m):
Packit Service 88ab54
                el_type = element_type(m)
Packit Service 88ab54
                if is_object(el_type):
Packit Service 88ab54
                    print_('    set_hashtable_of_pygobject(this->%s, cvt_value);' % name, file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    print_('    set_hashtable_of_strings(this->%s, cvt_value);' % name, file=fd)
Packit Service 88ab54
            elif is_object(m):
Packit Service 88ab54
                print_('    set_object_field((GObject**)&this->%s, cvt_value);' % name, file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('Unsupported member %s.%s' % (klassname, m))
Packit Service 88ab54
            print_('    return noneRef();', file=fd)
Packit Service 88ab54
            print_('}', file=fd)
Packit Service 88ab54
            print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
    def return_value(self, fd, arg, return_var_name = 'return_value', return_pyvar_name = 'return_pyvalue'):
Packit Service 88ab54
        if is_boolean(arg):
Packit Service 88ab54
            print_('    if (%s) {' % return_var_name, file=fd)
Packit Service 88ab54
            print_('        Py_INCREF(Py_True);', file=fd)
Packit Service 88ab54
            print_('        %s = Py_True;' % return_pyvar_name, file=fd)
Packit Service 88ab54
            print_('    } else {', file=fd)
Packit Service 88ab54
            print_('        Py_INCREF(Py_False);', file=fd)
Packit Service 88ab54
            print_('        %s = Py_False;' % return_pyvar_name, file=fd)
Packit Service 88ab54
            print_('    }', file=fd)
Packit Service 88ab54
        elif is_int(arg, self.binding_data):
Packit Service 88ab54
            print_('    %s = PyInt_FromLong(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
        elif is_cstring(arg) and is_transfer_full(arg):
Packit Service 88ab54
            print_('    if (%s) {' % return_var_name, file=fd)
Packit Service 88ab54
            print_('        %s = PyString_FromString(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
            print_('    } else {', file=fd)
Packit Service 88ab54
            print_('        %s = noneRef();' % return_pyvar_name, file=fd)
Packit Service 88ab54
            print_('    }', file=fd)
Packit Service 88ab54
        elif is_cstring(arg):
Packit Service 88ab54
            print_('    if (%s) {' % return_var_name, file=fd)
Packit Service 88ab54
            print_('        %s = PyString_FromString(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
            print_('    } else {', file=fd)
Packit Service 88ab54
            print_('        %s = noneRef();' % return_pyvar_name, file=fd)
Packit Service 88ab54
            print_('    }', file=fd)
Packit Service 88ab54
        elif is_glist(arg):
Packit Service 88ab54
            el_type = element_type(arg)
Packit Service 88ab54
            if is_object(el_type):
Packit Service 88ab54
                print_('    %s = get_list_of_pygobject(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
            elif is_cstring(el_type):
Packit Service 88ab54
                print_('    %s = get_list_of_strings(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
            elif is_xml_node(el_type):
Packit Service 88ab54
                print_('    %s = get_list_of_xml_nodes(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('failed to make an assignment for %s' % (arg,))
Packit Service 88ab54
        elif is_hashtable(arg):
Packit Service 88ab54
            el_type = element_type(arg)
Packit Service 88ab54
            if is_object(el_type):
Packit Service 88ab54
                print_('    %s = get_dict_from_hashtable_of_objects(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
            else:
Packit Service 88ab54
                print_('    %s = get_dict_from_hashtable_of_strings(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
        elif is_xml_node(arg):
Packit Service 88ab54
            # convert xmlNode* to strings
Packit Service 88ab54
            print_('    if (%s) {' % return_var_name, file=fd)
Packit Service 88ab54
            print_('        %s = get_pystring_from_xml_node(%s);' % (return_pyvar_name, return_var_name), file=fd)
Packit Service 88ab54
            print_('    } else {', file=fd)
Packit Service 88ab54
            print_('        %s = noneRef();' % return_pyvar_name, file=fd)
Packit Service 88ab54
            print_('    }', file=fd)
Packit Service 88ab54
        elif is_object(arg):
Packit Service 88ab54
            # return a PyGObjectPtr (wrapper around GObject)
Packit Service 88ab54
            print_('''\
Packit Service 88ab54
    if (%s) {
Packit Service 88ab54
        %s = PyGObjectPtr_New(G_OBJECT(%s));
Packit Service 88ab54
    } else {
Packit Service 88ab54
        %s = noneRef();
Packit Service 88ab54
    }
Packit Service 88ab54
''' % (return_var_name, return_pyvar_name, return_var_name, return_pyvar_name), file=fd)
Packit Service 88ab54
        else:
Packit Service 88ab54
            raise Exception('failed to make an assignment for %s' % (arg,))
Packit Service 88ab54
Packit Service 88ab54
    def generate_function_wrapper(self, m, fd):
Packit Service 88ab54
        if m.rename:
Packit Service 88ab54
            name = m.rename
Packit Service 88ab54
            if name.startswith('lasso_'):
Packit Service 88ab54
                name = name[6:]
Packit Service 88ab54
        else:
Packit Service 88ab54
            name = m.name[6:]
Packit Service 88ab54
        self.wrapper_list.append(name)
Packit Service 88ab54
        print_('''static PyObject*
Packit Service 88ab54
%s(G_GNUC_UNUSED PyObject *self, PyObject *args)
Packit Service 88ab54
{''' % name, file=fd)
Packit Service 88ab54
        parse_tuple_format = []
Packit Service 88ab54
        parse_tuple_args = []
Packit Service 88ab54
        for arg in m.args:
Packit Service 88ab54
            atype = arg_type(arg)
Packit Service 88ab54
            aname = arg_name(arg)
Packit Service 88ab54
            arg_def = None
Packit Service 88ab54
            python_cvt_def = None
Packit Service 88ab54
            defval = None
Packit Service 88ab54
            if is_optional(arg):
Packit Service 88ab54
                if not '|' in parse_tuple_format:
Packit Service 88ab54
                    parse_tuple_format.append('|')
Packit Service 88ab54
            if is_cstring(arg):
Packit Service 88ab54
                atype = unconstify(atype) 
Packit Service 88ab54
                if is_optional(arg):
Packit Service 88ab54
                    parse_tuple_format.append('z')
Packit Service 88ab54
                else:
Packit Service 88ab54
                    parse_tuple_format.append('s')
Packit Service 88ab54
                parse_tuple_args.append('&%s' % aname)
Packit Service 88ab54
                arg_def = '    %s %s = NULL;' % (arg[0], arg[1])
Packit Service 88ab54
            elif is_int(arg, self.binding_data) or is_boolean(arg):
Packit Service 88ab54
                parse_tuple_format.append('i')
Packit Service 88ab54
                parse_tuple_args.append('&%s' % aname)
Packit Service 88ab54
                if arg_default(arg):
Packit Service 88ab54
                    defval = arg_default(arg)
Packit Service 88ab54
                    if defval.startswith('b:'):
Packit Service 88ab54
                        defval = defval[2:].upper()
Packit Service 88ab54
                    else:
Packit Service 88ab54
                        defval = defval[2:]
Packit Service 88ab54
                    arg_def = '    %s %s = %s;' % (arg[0], arg[1], defval)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    arg_def = '    %s %s;' % (arg[0], arg[1])
Packit Service 88ab54
            elif is_hashtable(arg) or is_xml_node(arg) or is_list(arg) or is_time_t_pointer(arg):
Packit Service 88ab54
                parse_tuple_format.append('O')
Packit Service 88ab54
                parse_tuple_args.append('&cvt_%s' % aname)
Packit Service 88ab54
                arg_def = '    %s %s = NULL;' % (arg[0], arg[1])
Packit Service 88ab54
                python_cvt_def = '    PyObject *cvt_%s = NULL;' % aname
Packit Service 88ab54
            else:
Packit Service 88ab54
                parse_tuple_format.append('O')
Packit Service 88ab54
                parse_tuple_args.append('&cvt_%s' % aname)
Packit Service 88ab54
                arg_def = '    %s %s = NULL;' % (arg[0], arg[1])
Packit Service 88ab54
                python_cvt_def = '    PyGObjectPtr *cvt_%s = NULL;' % aname
Packit Service 88ab54
            if is_out(arg):
Packit Service 88ab54
                arg_def = '    %s %s = NULL;' % (var_type(arg), arg[1])
Packit Service 88ab54
                parse_tuple_format.pop()
Packit Service 88ab54
                parse_tuple_format.append('O')
Packit Service 88ab54
                parse_tuple_args.pop()
Packit Service 88ab54
                parse_tuple_args.append('&cvt_%s_out' % aname)
Packit Service 88ab54
                python_cvt_def = '    PyObject *cvt_%s_out = NULL;' % aname
Packit Service 88ab54
                print_('    PyObject *out_pyvalue = NULL;', file=fd)
Packit Service 88ab54
            print_(arg_def, file=fd)
Packit Service 88ab54
            if python_cvt_def:
Packit Service 88ab54
                print_(python_cvt_def, file=fd)
Packit Service 88ab54
Packit Service 88ab54
        if m.return_type:
Packit Service 88ab54
            print_('    %s return_value;' % m.return_type, file=fd)
Packit Service 88ab54
            print_('    PyObject* return_pyvalue = NULL;', file=fd)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
        parse_tuple_args = ', '.join(parse_tuple_args)
Packit Service 88ab54
        if parse_tuple_args:
Packit Service 88ab54
            parse_tuple_args = ', ' + parse_tuple_args
Packit Service 88ab54
Packit Service 88ab54
        print_('    if (! PyArg_ParseTuple(args, "%s"%s)) return NULL;' % (
Packit Service 88ab54
                ''.join(parse_tuple_format), parse_tuple_args), file=fd)
Packit Service 88ab54
Packit Service 88ab54
        for f, arg in zip([ x for x in parse_tuple_format if x != '|'], m.args):
Packit Service 88ab54
            if is_out(arg):
Packit Service 88ab54
                continue
Packit Service 88ab54
            if is_list(arg):
Packit Service 88ab54
                qualifier = element_type(arg)
Packit Service 88ab54
                if is_cstring(qualifier):
Packit Service 88ab54
                    print_('    set_list_of_strings(&%s, cvt_%s);' % (arg[1], arg[1]), file=fd)
Packit Service 88ab54
                elif is_xml_node(qualifier):
Packit Service 88ab54
                    print_('    set_list_of_xml_nodes(&%s, cvt_%s);' % (arg[1], arg[1]), file=fd)
Packit Service 88ab54
                elif isinstance(qualifier, str) and qualifier.startswith('Lasso'):
Packit Service 88ab54
                    print_('    set_list_of_pygobject(&%s, cvt_%s);' % (arg[1], arg[1]), file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    print_('E: unqualified GList argument in', name, qualifier, arg, file=sys.stderr)
Packit Service 88ab54
            elif is_xml_node(arg):
Packit Service 88ab54
                print_('    %s = get_xml_node_from_pystring(cvt_%s);' % (arg[1], arg[1]), file=fd)
Packit Service 88ab54
            elif is_time_t_pointer(arg):
Packit Service 88ab54
                print_('    %s = get_time_t(cvt_%s);' % (arg[1], arg[1]), file=fd)
Packit Service 88ab54
            elif is_hashtable(arg):
Packit Service 88ab54
                el_type = element_type(arg)
Packit Service 88ab54
                k_type = key_type(arg)
Packit Service 88ab54
                v_type = value_type(arg)
Packit Service 88ab54
                if is_cstring(el_type) or (is_cstring(k_type) and is_cstring(v_type)):
Packit Service 88ab54
Packit Service 88ab54
                    print_('    %s = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);' % arg[1], file=fd)
Packit Service 88ab54
                    print_('    set_hashtable_of_strings(%s, cvt_%s);' % (arg[1], arg[1]), file=fd)
Packit Service 88ab54
            elif f == 'O':
Packit Service 88ab54
                if is_optional(arg):
Packit Service 88ab54
                    print_('    if (PyObject_TypeCheck((PyObject*)cvt_%s, &PyGObjectPtrType)) {' % arg[1], file=fd)
Packit Service 88ab54
                    print_('        %s = (%s)cvt_%s->obj;' % (arg[1], arg[0], arg[1]), file=fd)
Packit Service 88ab54
                    print_('    } else {', file=fd)
Packit Service 88ab54
                    print_('        %s = NULL;' % arg[1], file=fd)
Packit Service 88ab54
                    print_('    }', file=fd)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    print_('    if (PyObject_TypeCheck((PyObject*)cvt_%s, &PyGObjectPtrType)) {' % arg[1], file=fd)
Packit Service 88ab54
                    print_('        %s = (%s)cvt_%s->obj;' % (arg[1], arg[0], arg[1]), file=fd)
Packit Service 88ab54
                    print_('    } else {', file=fd)
Packit Service 88ab54
                    print_('        PyErr_SetString(PyExc_TypeError, "value should be a PyGObject");', file=fd)
Packit Service 88ab54
                    print_('        return NULL;', file=fd)
Packit Service 88ab54
                    print_('    }', file=fd)
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
        if m.return_type:
Packit Service 88ab54
            print_('    return_value =', file=fd)
Packit Service 88ab54
            if 'new' in m.name:
Packit Service 88ab54
                print_('(%s)' % m.return_type, file=fd)
Packit Service 88ab54
        else:
Packit Service 88ab54
            print_('   ', file=fd)
Packit Service 88ab54
        print_('%s(%s);' % (m.name, ', '.join([ref_name(x) for x in m.args])), file=fd)
Packit Service 88ab54
Packit Service 88ab54
        if m.return_type:
Packit Service 88ab54
            # Constructor so decrease refcount (it was incremented by PyGObjectPtr_New called
Packit Service 88ab54
            # in self.return_value
Packit Service 88ab54
            try:
Packit Service 88ab54
                self.return_value(fd, m.return_arg)
Packit Service 88ab54
            except:
Packit Service 88ab54
                print_('W: cannot assign return value of', m, file=sys.stderr)
Packit Service 88ab54
                raise
Packit Service 88ab54
Packit Service 88ab54
            if is_transfer_full(m.return_arg, default=True):
Packit Service 88ab54
                self.free_value(fd, m.return_arg, name = 'return_value')
Packit Service 88ab54
        for f, arg in zip(parse_tuple_format, m.args):
Packit Service 88ab54
            if is_out(arg):
Packit Service 88ab54
                self.return_value(fd, arg, return_var_name = arg[1], return_pyvar_name = 'out_pyvalue')
Packit Service 88ab54
                print_('    PyList_SetItem(cvt_%s_out, 0, out_pyvalue);' % arg[1], file=fd)
Packit Service 88ab54
            elif arg[0] == 'GList*':
Packit Service 88ab54
                qualifier = arg[2].get('element-type')
Packit Service 88ab54
                if is_cstring(qualifier):
Packit Service 88ab54
                    print_('    free_list(&%s, (GFunc)g_free);' % arg[1], file=fd)
Packit Service 88ab54
                elif is_xml_node(qualifier):
Packit Service 88ab54
                    print_('    free_list(&%s, (GFunc)xmlFreeNode);' % arg[1], file=fd)
Packit Service 88ab54
                elif is_object(qualifier):
Packit Service 88ab54
                    print_('    free_list(&%s, (GFunc)g_object_unref);' % arg[1], file=fd)
Packit Service 88ab54
            elif is_time_t_pointer(arg):
Packit Service 88ab54
                print_('    if (%s) free(%s);' % (arg[1], arg[1]), file=fd)
Packit Service 88ab54
            elif not is_transfer_full(arg) and is_hashtable(arg):
Packit Service 88ab54
                self.free_value(fd, arg)
Packit Service 88ab54
            elif not is_transfer_full(arg) and is_xml_node(arg):
Packit Service 88ab54
                self.free_value(fd, arg)
Packit Service 88ab54
Packit Service 88ab54
        if not m.return_type:
Packit Service 88ab54
            print_('    return noneRef();', file=fd)
Packit Service 88ab54
        else:
Packit Service 88ab54
            print_('    return return_pyvalue;', file=fd)
Packit Service 88ab54
        print_('}', file=fd)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54
Packit Service 88ab54
    def generate_wrapper_list(self, fd):
Packit Service 88ab54
        print_('''
Packit Service 88ab54
static PyMethodDef lasso_methods[] = {''', file=fd)
Packit Service 88ab54
        for m in self.wrapper_list:
Packit Service 88ab54
            print_('    {"%s", %s, METH_VARARGS, NULL},' % (m, m), file=fd)
Packit Service 88ab54
        print_('    {NULL, NULL, 0, NULL}', file=fd)
Packit Service 88ab54
        print_('};', file=fd)
Packit Service 88ab54
        print_('', file=fd)
Packit Service 88ab54