diff options
| author | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2010-01-04 09:13:36 +0000 |
|---|---|---|
| committer | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2010-01-04 09:13:36 +0000 |
| commit | 5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184 (patch) | |
| tree | fc571c8d011bd0b73d932601e0b026f338e5d675 /bindings | |
| parent | 42062ff986a344f3f33a4465e106fede10aeaa6a (diff) | |
| download | lasso-5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184.tar.gz lasso-5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184.tar.xz lasso-5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184.zip | |
Bindings: make the binding infrastructure understand GObject-introspections annotations
* bindings/bindings.py
* bindings/utils.py:
add convenience function to treat arguments tuple:
(type,name,{annotations}).
introduce new argument options, fix that arguments are 3-tuple of the
form (type,name,annotations), where annotations is a dictionary.
Key of this dictionnary can be:
- optional, wheter the argument is necessary, it means it has a
default value.
- out, means that the pointer is a pointer of pointer, for bindings
that can return exceptions, it will be returned instead of the
integer error code, the only way to access error codes will be
exceptions.
- element-type, contained type of a list or an array,
- key-type, value-type, type of respectively the key and value of a
GHashTable.
- transfer, wheter a the callee(for arguments)/caller(for return
values) owns the values passed, it can be none,container(if the
callee/caller only owns the container not the contained value) or
full.
doc.parameters is now a 3-tuple of (attribute-name,
attribute-description, attribute-annotations) where
attribute-annotations is a string of the form '(option1)(option2
option-arguments) etc.'.
- add predicates for xml, list and time_t values. improve predicates
for cstring and const modifier.
* bindings/overrides.xml:
'out' arguments are not well supported for java, so skip functions
using them.
* bindings/java/lang.py bindings/php5/php_code.py
bindings/php5/wrapper_source.py bindings/python/lang.py:
- update language specifig binding generators for handling new
annotations.
- improve python method declaration, handle optional arguments with
default values, factorize this chode in two methods,
get_python_arg_decl and defval_to_python_value.
* bindings/python/tests/Makefile.am
bindings/python/tests/idwsf1_tests.py
bindings/python/tests/idwsf2_tests.py:
make test work with out of source build dir.
Diffstat (limited to 'bindings')
| -rw-r--r-- | bindings/bindings.py | 80 | ||||
| -rw-r--r-- | bindings/java/lang.py | 57 | ||||
| -rw-r--r-- | bindings/overrides.xml | 14 | ||||
| -rw-r--r-- | bindings/php5/php_code.py | 21 | ||||
| -rw-r--r-- | bindings/php5/wrapper_source.py | 100 | ||||
| -rw-r--r-- | bindings/python/lang.py | 211 | ||||
| -rw-r--r-- | bindings/python/tests/Makefile.am | 2 | ||||
| -rwxr-xr-x | bindings/python/tests/idwsf1_tests.py | 41 | ||||
| -rwxr-xr-x | bindings/python/tests/idwsf2_tests.py | 2 | ||||
| -rw-r--r-- | bindings/utils.py | 111 |
10 files changed, 481 insertions, 158 deletions
diff --git a/bindings/bindings.py b/bindings/bindings.py index a00b8cea..eaa69a37 100644 --- a/bindings/bindings.py +++ b/bindings/bindings.py @@ -25,7 +25,7 @@ import os import re import sys -import utils +from utils import * from optparse import OptionParser @@ -241,12 +241,14 @@ class Function: class DocString: orig_docstring = None - parameters = [] + parameters = None return_value = None description = None def __init__(self, function, docstring): self.orig_docstring = docstring + self.parameters = [] + self.params = {} lines = docstring.splitlines() # ignore the first line, it has the symbol name lines = lines[1:] @@ -260,8 +262,52 @@ class DocString: self.parameters = [] if lines[0][0] == '@': - param_name, param_desc = lines[0][1:].split(':', 1) - self.parameters.append([param_name, param_desc]) + + splits = lines[0][1:].split(':', 2) + param_name = splits[0] + if len(splits) > 2: + param_options = splits[1] + param_desc = splits[2] + self.parameters.append([param_name, param_desc, param_options]) + self.params[param_name] = { 'desc': param_desc, 'options': param_options } + for a in function.args: + if a[1] == param_name: + arg = a + break + else: + raise Exception('should not happen ' + param_name + ' ' + lines[0] + repr(function)) + if 'allow-none' in param_options: + arg[2]['optional'] = True + if re.search('\(\s*out\s*\)', param_options): + arg[2]['out'] = True + if arg[2].get('optional'): + m = re.search('\(\s*default\s*(.*)\s*\)', param_options) + if m: + prefix = '' + if is_boolean(arg): + prefix = 'b:' + elif is_int(arg): + prefix = 'c:' + else: + raise Exception('should not happen: could not found type for default: ' + param_options) + arg[2]['default'] = prefix + m.group(1) + m = re.search('\(\s*element-type\s+(\w+)(?:\s+(\w+))?', param_options) + if m: + if len(m.groups()) > 2: + arg[2]['key-type'] = \ + convert_type_from_gobject_annotation(m.group(1)) + arg[2]['value-type'] = \ + convert_type_from_gobject_annotation(m.group(2)) + else: + arg[2]['element-type'] = \ + convert_type_from_gobject_annotation(m.group(1)) + m = re.search('\(\s*transfer\s+(\w+)', param_options) + if m: + arg[2]['transfer'] = m.group(1) + else: + param_desc = splits[1] + self.parameters.append([param_name, param_desc]) + self.params[param_name] = { 'desc': param_desc } else: # continuation of previous description self.parameters[-1][1] = self.parameters[-1][1] + ' ' + lines[0].strip() @@ -359,9 +405,7 @@ def parse_header(header_file): elif line.startswith('struct _'): m = re.match('struct ([a-zA-Z0-9_]+)', line) struct_name = m.group(1) - #print struct_name if struct_name in struct_names: - #print struct_name in_struct = Struct(struct_name) in_struct_private = False elif in_struct: @@ -399,23 +443,21 @@ def parse_header(header_file): i += 1 line = line[:-1] + lines[i].lstrip() - m = re.match(r'LASSO_EXPORT\s+((?:const |)[\w]+\s*\*?)\s+(OFTYPE\(.*?\)\s*)?(\*?\w+)\s*\((.*?)\)', line) - if m and not m.group(3).endswith('_get_type'): - return_type, oftype, function_name, args = m.groups() + m = re.match(r'LASSO_EXPORT(.*(?:\s|\*))(\w+)\s*\((.*?)\)', line) + if m and not m.group(2).endswith('_get_type'): + return_type, function_name, args = m.groups() return_type = return_type.strip() f = Function() if function_name[0] == '*': return_type += '*' function_name = function_name[1:] if binding.functions_toskip.get(function_name) != 1: + if re.search('\<const\>', return_type): + f.return_owner = False + # clean the type + return_type = clean_type(return_type) if return_type != 'void': f.return_type = return_type - if return_type.startswith('const'): - f.return_owner = False - if oftype: - oftype_parse = re.match(r'OFTYPE\((.*)\)', oftype) - if oftype_parse: - f.return_type_qualifier = oftype_parse.group(1) if function_name.endswith('_destroy'): # skip the _destroy functions, they are just wrapper over # g_object_unref @@ -424,12 +466,14 @@ def parse_header(header_file): f.name = function_name f.args = [] for arg in [x.strip() for x in args.split(',')]: + arg = clean_type(arg) if arg == 'void' or arg == '': continue - m = re.match(r'((const\s+)?\w+\*?)\s+(\*?\w+)', arg) - # TODO: Add parsing of OFTYPE + m = re.match(r'(.*(?:\s|\*))(\w+)', arg) + type, name = m.groups() + type = clean_type(type) if m: - f.args.append(list(normalise_var(m.group(1), m.group(3))) + [{}]) + f.args.append(list((type, name, {}))) else: print >>sys.stderr, 'failed to process:', arg, 'in line:', line f.apply_overrides() diff --git a/bindings/java/lang.py b/bindings/java/lang.py index c854ff85..21fb5bd5 100644 --- a/bindings/java/lang.py +++ b/bindings/java/lang.py @@ -24,7 +24,7 @@ import sys import re import textwrap -import utils +from utils import * lasso_package_name = 'com.entrouvert.lasso' lasso_java_path = 'com/entrouvert/lasso/' @@ -39,15 +39,25 @@ def with_return_owner(d): def generate_arg_list(self,args): def arg_to_decl(arg): type, name, option = arg - return self.JNI_arg_type(type) + ' ' + utils.format_as_camelcase(name) - return ', '.join([ arg_to_decl(x) for x in args ]) + return self.JNI_arg_type(type) + ' ' + format_as_camelcase(name) + return ', '.join([ arg_to_decl(x) for x in args if not is_out(x)]) def generate_arg_list2(args): def arg_to_decl(arg): type, name, option = arg - return utils.format_as_camelcase(name) + if is_out(arg): + return 'output' + return format_as_camelcase(name) return ', '.join([ arg_to_decl(x) for x in args ]) +def generate_arg_list3(self,args): + def arg_to_decl(arg): + type, name, option = arg + if is_out(arg): + return 'Object[] output' + return self.JNI_arg_type(type) + ' ' + format_as_camelcase(name) + return ', '.join([ arg_to_decl(x) for x in args]) + def convert_class_name(lasso_name): return lasso_name[5:] @@ -85,8 +95,8 @@ def error_to_exception(error_name): super = 'Lasso' else: super, name = re.match('LASSO(_.*)_ERROR(_.*)', error_name).groups() - super = utils.format_as_camelcase(super.lower()) - name = utils.format_as_camelcase(name.lower()) + super = format_as_camelcase(super.lower()) + name = format_as_camelcase(name.lower()) return (super+name+'Exception',super+'Exception') def wrapper_decl(name, jnitype, fd): @@ -274,17 +284,17 @@ protected static native void destroy(long cptr); else: jtype = self.JNI_return_type(m.return_type) name = self.JNI_function_name(m) - print >> fd, ' public static native %s %s(%s);' % (jtype,name, generate_arg_list(self,m.args)) + print >> fd, ' public static native %s %s(%s);' % (jtype,name, generate_arg_list3(self,m.args)) def JNI_member_function_prefix(self,c,m): klassname = c.name[5:] - mname = utils.format_as_camelcase(m[1]) + mname = format_as_camelcase(m[1]) return '%s_%s' % (klassname,mname) def generate_JNI_member(self, c, fd): for m in c.members: prefix = self.JNI_member_function_prefix(c,m) - mname = utils.format_as_camelcase(m[1]) + mname = format_as_camelcase(m[1]) mtype = m[0] jtype = self.JNI_member_type(m) @@ -691,7 +701,7 @@ protected static native void destroy(long cptr); continue name, = re.match('LASSO_ERROR(.*)',orig).groups() name = name.lower() - name = utils.format_underscore_as_camelcase(name) + name = format_underscore_as_camelcase(name) name = 'Lasso%sException' % name self.generate_exception_class(name, 'LassoException', 0, orig) self.generate_exception_switch_case(efd, name, orig) @@ -726,7 +736,7 @@ protected static native void destroy(long cptr); if m.rename: return m.rename else: - name = utils.format_as_camelcase(m.name[6:]) + name = format_as_camelcase(m.name[6:]) name = name[prefix:] return name[0].lower() + name[1:] for c in self.binding_data.structs: @@ -776,7 +786,7 @@ protected static native void destroy(long cptr); for m in c.members: type, name, options = m prefix = self.JNI_member_function_prefix(c,m) - jname = utils.format_as_camelcase('_'+name) + jname = format_as_camelcase('_'+name) jtype = self.JNI_member_type(m) if type == 'GList*' or type == 'const GList*': print >> fd, ' public void set%s(List list) {' % jname @@ -859,8 +869,10 @@ protected static native void destroy(long cptr); else: print >> fd, ' /**\n' print >> fd, ' *' - for name, desc in doc.parameters: - print >> fd, normalize(desc, ' * @param %s ' % utils.format_as_camelcase(name)) + for p in doc.parameters: + name = p[0] + desc = p[1] + print >> fd, normalize(desc, ' * @param %s ' % format_as_camelcase(name)) if doc.return_value: print >> fd, normalize(doc.return_value, ' * @return ') if m.errors: @@ -868,7 +880,22 @@ protected static native void destroy(long cptr); err = error_to_exception(err)[0] print >> fd, normalize(err,' * @throws ') print >> fd, ' **/' - if m.return_type == 'GList*' or m.return_type == 'const GList*': + outarg = None + for a in args: + if is_out(a): + # only one output arg supported + assert not outarg + outarg = a + if outarg: + assert is_int(make_arg(m.return_type), self.binding_data) + new_return_type = self.JNI_return_type(var_type(outarg)) + print >> fd, ' public %s %s(%s) {' % (new_return_type, mname, generate_arg_list(self, args[1:])) + print >> fd, ' Object[] output = new Object[1];' + print >> fd, ' LassoException.throwError(LassoJNI.%s(this, %s));' % (jni_name, generate_arg_list2(args[1:])) + print >> fd, ' return (%s)output[0];' % new_return_type + print >> fd, ' }' + + elif m.return_type == 'GList*' or m.return_type == 'const GList*': print >> fd, ' public List %s(%s) {' % (mname,generate_arg_list(self,args[1:])) arglist = generate_arg_list2(args[1:]) if arglist: diff --git a/bindings/overrides.xml b/bindings/overrides.xml index eedcec3e..d85657de 100644 --- a/bindings/overrides.xml +++ b/bindings/overrides.xml @@ -37,14 +37,14 @@ <!-- LassoWsfProfile --> <func name="lasso_wsf_profile_get_identity" return_owner="false" /> <func name="lasso_wsf_profile_get_session" return_owner="false" /> - <func name="lasso_wsf_profile_get_remote_provider" skip="true"/> - <func name="lasso_data_service_get_answer" skip="true"/> - <func name="lasso_data_service_get_query_item" skip="true"/> - <func name="lasso_data_service_add_modification" skip="true"/> + <func name="lasso_wsf_profile_get_remote_provider" skip="java"/> + <func name="lasso_data_service_get_answer" skip="java"/> + <func name="lasso_data_service_get_query_item" skip="java"/> + <func name="lasso_data_service_add_modification" skip="java"/> + <func name="lasso_data_service_get_answers" skip="java"/> + <func name="lasso_data_service_get_answers_by_select" skip="java"/> + <func name="lasso_data_service_get_answers_by_item_id" skip="java"/> <func name="lasso_saml2_encrypted_element_decrypt" skip="true"/> - <func name="lasso_data_service_get_answers" skip="true"/> - <func name="lasso_data_service_get_answers_by_select" skip="true"/> - <func name="lasso_data_service_get_answers_by_item_id" skip="true"/> <!-- LassoIdentity --> <func name="lasso_identity_get_federation" return_owner="false" /> <func name="lasso_identity_get_svc_md_ids" return_type_qualifier="char*"/> diff --git a/bindings/php5/php_code.py b/bindings/php5/php_code.py index 76bae23d..64439778 100644 --- a/bindings/php5/php_code.py +++ b/bindings/php5/php_code.py @@ -22,7 +22,7 @@ import re import sys -import utils +from utils import * class PhpCode: def __init__(self, binding_data, fd): @@ -135,7 +135,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) { print >> self.fd, '' def generate_constructors(self, klass): - method_prefix = utils.format_as_underscored(klass.name) + '_' + method_prefix = format_as_underscored(klass.name) + '_' for m in self.binding_data.functions: if m.name == method_prefix + 'new': php_args = [] @@ -183,7 +183,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) { for m in klass.members: mtype = m[0] - mname = utils.format_as_camelcase(m[1]) + mname = format_as_camelcase(m[1]) options = m[2] # Getters @@ -253,7 +253,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) { except IndexError: setter = None mname = re.match(r'lasso_.*_get_(\w+)', meth_name).group(1) - mname =utils.format_as_camelcase(mname) + mname = format_as_camelcase(mname) print >> self.fd, ' /**' print >> self.fd, ' * @return %s' % self.get_docstring_return_type(m.return_type) @@ -278,7 +278,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) { print >> self.fd, '' # second pass on methods, real methods - method_prefix = utils.format_as_underscored(klass.name) + '_' + method_prefix = format_as_underscored(klass.name) + '_' for m in methods: if m.name.endswith('_new') or m.name.endswith('_new_from_dump') or \ m.name.endswith('_new_full'): @@ -295,9 +295,13 @@ function lassoRegisterIdWsf2DstService($prefix, $href) { mname = mname[len(method_prefix):] php_args = [] c_args = [] + outarg = None for arg in m.args[1:]: arg_type, arg_name, arg_options = arg arg_name = '$' + arg_name + if is_out(arg): + assert not outarg + outarg = arg if arg_options.get('optional'): if arg_options.get('default'): defval = arg_options.get('default') @@ -318,6 +322,11 @@ function lassoRegisterIdWsf2DstService($prefix, $href) { c_args.append(arg_name) else: c_args.append('%s._cptr' % arg_name) + if is_out(arg): + php_args.pop() + php_args.append(arg_name) + c_args.pop() + c_args.append(arg_name) if php_args: php_args = ', '.join(php_args) @@ -331,7 +340,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) { if m.docstring: print >> self.fd, self.generate_docstring(m, mname, 4) print >> self.fd, ' public function %s(%s) {' % ( - utils.format_underscore_as_camelcase(mname), php_args) + format_underscore_as_camelcase(mname), php_args) if m.return_type == 'void': print >> self.fd, ' %s($this->_cptr%s);' % (cname, c_args) elif m.return_type in ('gint', 'int'): diff --git a/bindings/php5/wrapper_source.py b/bindings/php5/wrapper_source.py index 690c4adb..5775b7be 100644 --- a/bindings/php5/wrapper_source.py +++ b/bindings/php5/wrapper_source.py @@ -22,7 +22,7 @@ import sys import os -import utils +from utils import * class WrapperSource: def __init__(self, binding_data, fd): @@ -32,7 +32,7 @@ class WrapperSource: self.src_dir = os.path.dirname(__file__) def is_object(self, t): - return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*', + return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*', 'GType', 'xmlNode*', 'int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums def generate(self): @@ -101,12 +101,81 @@ PHP_MSHUTDOWN_FUNCTION(lasso) ''' + def set_zval(self, zval_name, c_variable, type, free = False): + '''Emit code to set a zval* of name zval_name, from the value of the C variable called c_variable type, type. + ''' + # first we free the previous value + p = (zval_name, c_variable) + q = { 'zval_name' : zval_name, 'c_variable' : c_variable } + print >> self.fd, ' zval_dtor(%s);' % zval_name + if is_pointer(type): + print >> self.fd, ' if (! %s) {' % c_variable + print >> self.fd, ' ZVAL_NULL(%s);' % zval_name + print >> self.fd, ' } else {' + if is_int(type, self.binding_data): + print >> self.fd, ' ZVAL_LONG(%s, %s);' % p + elif is_boolean(type): + print >> self.fd, ' ZVAL_BOOL(%s, %s);' % p + elif is_cstring(type): + print >> self.fd, ' ZVAL_STRING(%s, %s, 1);' % p + if free and not is_const(type): + print >> self.fd, 'g_free(%s)' % c_variable + elif arg_type(type) == 'xmlNode*': + print >> self.fd, '''\ + { + char* xmlString = get_string_from_xml_node(%(c_variable)s); + if (xmlString) { + ZVAL_STRING(%(zval_name)s, xmlString, 0); + } else { + ZVAL_NULL(%(zval_name)s); + } + } +''' % q + elif arg_type(type) == 'GList*': + elem_type = make_arg(element_type(type)) + if not arg_type(elem_type): + raise Exception('unknown elem_type: ' + repr(type)) + if is_cstring(elem_type): + function = 'set_array_from_list_of_strings' + free_function = 'free_glist(%(c_variable)s, (GFunc)free);' + elif arg_type(elem_type).startswith('xmlNode'): + function = 'set_array_from_list_of_xmlnodes' + free_function = 'free_glist(%(c_variable)s, (GFunc)xmlFree);' + elif is_object(elem_type): + function = 'set_array_from_list_of_objects' + free_function = 'g_list_free(%(c_variable)s);' + else: + raise Exception('unknown elem_type: ' + repr(type)) + print >> self.fd, ' %s(%s, &%s);' % (function, c_variable, zval_name) + if free: + print >> self.fd, ' ', free_function % q + elif is_object(type): + print >> self.fd, '''\ + if (G_IS_OBJECT(%(c_variable)s)) { + PhpGObjectPtr *obj = PhpGObjectPtr_New(G_OBJECT(%(c_variable)s)); + ZEND_REGISTER_RESOURCE(%(zval_name)s, obj, le_lasso_server); + } else { + ZVAL_NULL(%(zval_name)s); + }''' % q + if free: + print >> self.fd, '''\ + if (%(c_variable)s) { + g_object_unref(%(c_variable)s); // If constructor ref is off by one' + }''' % q + + else: + raise Exception('unknown type: ' + repr(type) + unconstify(arg_type(type))) + if is_pointer(type): + print >> self.fd, ' }' + + + def return_value(self, vtype, options, free = False): if vtype is None: return elif vtype == 'gboolean': print >> self.fd, ' RETVAL_BOOL(return_c_value);' - elif vtype in ['int', 'gint'] + self.binding_data.enums: + elif vtype in ['int', 'gint', 'GType', ] + self.binding_data.enums: print >> self.fd, ' RETVAL_LONG(return_c_value);' elif vtype in ('char*', 'gchar*'): print >> self.fd, '''\ @@ -186,7 +255,12 @@ PHP_MSHUTDOWN_FUNCTION(lasso) 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*'): + if is_out(arg): + print >> self.fd, ' zval *php_out_%s = NULL;' % arg_name + print >> self.fd, ' %s %s;' % (var_type(arg), arg_name) + parse_tuple_format.append('z!') + parse_tuple_args.append('&php_out_%s' % arg_name) + elif arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*'): arg_type = arg_type.replace('const ', '') parse_tuple_format.append('s!') parse_tuple_args.append('&%s_str, &%s_len' % (arg_name, arg_name)) @@ -232,7 +306,9 @@ PHP_MSHUTDOWN_FUNCTION(lasso) ''' % (''.join(parse_tuple_format), parse_tuple_args) for f, arg in zip(parse_tuple_format, m.args): - if arg[0] == 'xmlNode*': + if is_out(arg): + continue + elif arg[0] == 'xmlNode*': print >> self.fd, '''\ %(name)s = get_xml_node_from_string(%(name)s_str);''' % {'name': arg[1]} elif f.startswith('s'): @@ -259,12 +335,18 @@ PHP_MSHUTDOWN_FUNCTION(lasso) print >> self.fd, '(%s)' % m.return_type, else: print >> self.fd, ' ', - print >> self.fd, '%s(%s);' % (m.name, ', '.join([x[1] for x in m.args])) + print >> self.fd, '%s(%s);' % (m.name, ', '.join([ref_name(x) for x in m.args])) # Free the converted arguments for f, arg in zip(parse_tuple_format, m.args): argtype, argname, argoptions = arg - if argtype == 'xmlNode*': + if is_out(arg): + # export the returned variable + free = is_transfer_full(unref_type(arg)) + print m + self.set_zval('php_out_%s' % argname, argname, unref_type(arg), free = free) + pass + elif argtype == 'xmlNode*': print >> self.fd, ' xmlFree(%s);' % argname elif f.startswith('a'): elem_type = arg[2].get('elem_type') @@ -289,7 +371,7 @@ PHP_MSHUTDOWN_FUNCTION(lasso) print >> sys.stderr, 'E: GList argument : %s of %s, with type : %s' % (m_name, klassname, m_options.get('elem_type')) return - function_name = '%s_%s_get' % (klassname, utils.format_as_camelcase(m_name)) + function_name = '%s_%s_get' % (klassname, format_as_camelcase(m_name)) print >> self.fd, '''PHP_FUNCTION(%s) {''' % function_name self.functions_list.append(function_name) @@ -333,7 +415,7 @@ PHP_MSHUTDOWN_FUNCTION(lasso) print >> sys.stderr, 'E: GList argument : %s of %s, with type : %s' % (m_name, klassname, m_options.get('elem_type')) return - function_name = '%s_%s_set' % (klassname, utils.format_as_camelcase(m_name)) + function_name = '%s_%s_set' % (klassname, format_as_camelcase(m_name)) print >> self.fd, '''PHP_FUNCTION(%s) {''' % function_name self.functions_list.append(function_name) diff --git a/bindings/python/lang.py b/bindings/python/lang.py index 57d67273..ff06b746 100644 --- a/bindings/python/lang.py +++ b/bindings/python/lang.py @@ -23,7 +23,25 @@ import os import sys import re import textwrap -import utils +from utils import * + +def defval_to_python_value(defval): + if defval is None: + return 'None' + if defval.startswith('b:'): + if defval[2:].lower() == 'true': + return 'True' + if defval[2:].lower() == 'false': + return 'False' + if defval.startswith('c:'): + return defval[8:] + raise Exception('Could not convert %s to python value' % defval) + +def get_python_arg_decl(arg): + if is_optional(arg): + return '%s = %s' % (arg_name(arg), defval_to_python_value(arg_default(arg))) + else: + return arg_name(arg) class Binding: def __init__(self, binding_data): @@ -31,14 +49,7 @@ class Binding: self.src_dir = os.path.dirname(__file__) 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 ['guchar*', 'guchar*', 'char*', 'gchar*', - 'GList*', 'GHashTable*', - 'int', 'gint', 'gboolean', 'xmlNode*'] + self.binding_data.enums - else: - return False + return t and is_object((t,'',{})) and t not in self.binding_data.enums def generate(self): fd = open('lasso.py', 'w') @@ -254,17 +265,14 @@ if WSF_SUPPORT: methods = clss.methods[:] # constructor(s) - method_prefix = 'lasso_' + utils.format_as_underscored(klassname) + '_' + method_prefix = 'lasso_' + 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) + py_args.append(get_python_arg_decl(o)) if self.is_pygobject(arg_type): c_args.append('%s._cptr' % arg_name) @@ -284,15 +292,12 @@ if WSF_SUPPORT: 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):]) + constructor_name = 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) + py_args.append(get_python_arg_decl(o)) if self.is_pygobject(arg_type): c_args.append('%s._cptr' % arg_name) @@ -311,7 +316,7 @@ if WSF_SUPPORT: # create properties for members for m in clss.members: - mname = utils.format_as_camelcase(m[1]) + mname = format_as_camelcase(m[1]) options = m[2] print >> fd, ' def get_%s(self):' % mname if self.is_pygobject(m[0]): @@ -372,7 +377,7 @@ if WSF_SUPPORT: else: mname = m.name mname = re.match(r'lasso_.*_get_(\w+)', mname).group(1) - mname = utils.format_underscore_as_camelcase(mname) + mname = format_underscore_as_camelcase(mname) print >> fd, ' def get_%s(self):' % mname function_name = m.name[6:] @@ -413,25 +418,21 @@ if WSF_SUPPORT: function_name = m.name[6:] py_args = [] c_args = [] + outarg = None 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) + if is_out(o): + assert not outarg + outarg = o + outvar = '_%s_out' % arg_name else: - py_args.append(arg_name) - if arg_type in ('char*', 'const char*', 'guchar*', 'const guchar*', 'gchar*', 'const gchar*', 'xmlNode*') or \ + py_args.append(get_python_arg_decl(o)) + + if is_out(o): + c_args.append(outvar) + elif arg_type in ('char*', 'const char*', 'guchar*', 'const guchar*', 'gchar*', 'const gchar*', 'xmlNode*') or \ arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] or \ - arg_type in self.binding_data.enums: + arg_type in self.binding_data.enums or is_time_t_pointer(o): c_args.append(arg_name) else: c_args.append('%s._cptr' % arg_name) @@ -446,32 +447,39 @@ if WSF_SUPPORT: c_args = '' print >> fd, ' def %s(self%s):' % ( - utils.format_underscore_as_camelcase(mname), py_args) + 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'): + + if outarg: + print >> fd, " %s = list((None,))" % outvar + return_type = m.return_type + return_type_qualifier = m.return_type_qualifier + assert is_int(make_arg(return_type),self.binding_data) or not outarg + if 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, ' if rc != 0:' + print >> fd, ' raise Error.raise_on_rc(rc)' + elif return_type in (None, 'void'): + print >> fd, ' _lasso.%s(self._cptr%s)' % ( + function_name, c_args) + elif return_type == 'GList*' and self.is_pygobject(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): + elif self.is_pygobject(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) + if outarg: + print >> fd, ' return %s[0]' % outvar print >> fd, '' print >> fd, '' @@ -573,10 +581,10 @@ if WSF_SUPPORT: name = m.rename if name.startswith('lasso_'): name = name[6:] - pname = utils.format_as_camelcase(name) + pname = format_as_camelcase(name) else: name = m.name[6:] - pname = utils.format_as_camelcase(name) + pname = format_as_camelcase(name) print >> fd, '%s = _lasso.%s' % (pname, name) @@ -627,7 +635,7 @@ register_constants(PyObject *d) def generate_member_wrapper(self, c, fd): klassname = c.name for m in c.members: - mname = utils.format_as_camelcase(m[1]) + mname = format_as_camelcase(m[1]) # getter print >> fd, '''static PyObject* %s_%s_get(G_GNUC_UNUSED PyObject *self, PyObject *args) @@ -715,60 +723,62 @@ register_constants(PyObject *d) print >> fd, '' - def return_value(self, fd, vtype, options): + def return_value(self, fd, vtype, options, return_var_name = 'return_value', return_pyvar_name = 'return_pyvalue'): if vtype == 'gboolean': - print >> fd, ' if (return_value) {' + print >> fd, ' if (%s) {' % return_var_name print >> fd, ' Py_INCREF(Py_True);' - print >> fd, ' return_pyvalue = Py_True;' + print >> fd, ' %s = Py_True;' % return_pyvar_name print >> fd, ' } else {' print >> fd, ' Py_INCREF(Py_False);' - print >> fd, ' return_pyvalue = Py_False;' + print >> fd, ' %s = Py_False;' % return_pyvar_name print >> fd, ' }' elif vtype in ['int', 'gint'] + self.binding_data.enums: - print >> fd, ' return_pyvalue = PyInt_FromLong(return_value);' + print >> fd, ' %s = PyInt_FromLong(%s);' % (return_pyvar_name, return_var_name) elif vtype in ('char*', 'guchar*', 'const guchar*', 'gchar*'): - print >> fd, ' if (return_value) {' - print >> fd, ' return_pyvalue = PyString_FromString(return_value);' - print >> fd, ' g_free(return_value);' + print >> fd, ' if (%s) {' % return_var_name + print >> fd, ' %s = PyString_FromString(%s);' % (return_pyvar_name, return_var_name) + print >> fd, ' g_free(%s);' % return_var_name print >> fd, ' } else {' - print >> fd, ' return_pyvalue = noneRef();' + print >> fd, ' %s = noneRef();' % return_pyvar_name print >> fd, ' }' elif vtype in ('const char*', 'const gchar*'): - print >> fd, ' if (return_value) {' - print >> fd, ' return_pyvalue = PyString_FromString(return_value);' + print >> fd, ' if (%s) {' % return_var_name + print >> fd, ' %s = PyString_FromString(%s);' % (return_pyvar_name, return_var_name) print >> fd, ' } else {' - print >> fd, ' return_pyvalue = noneRef();' + print >> fd, ' %s = noneRef();' % return_pyvar_name 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);' + if not elem_type or self.is_pygobject(elem_type): + print >> fd, ' %s = get_list_of_pygobject(%s);' % (return_pyvar_name, return_var_name) + elif elem_type == 'char*': + print >> fd, ' %s = get_list_of_strings(%s);' % (return_pyvar_name, return_var_name) + elif elem_type.startswith('xmlNode'): + print >> fd, ' %s = get_list_of_xml_nodes(%s);' % (return_pyvar_name, return_var_name) else: - print >> fd, ' return_pyvalue = get_list_of_pygobject(return_value);' + raise Exception('Should not happen: %s %s ' % (repr(options), vtype)) 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);' + print >> fd, ' %s = get_dict_from_hashtable_of_strings(%s);' % (return_pyvar_name, return_var_name) else: - print >> fd, ' return_pyvalue = get_dict_from_hashtable_of_objects(return_value);' + print >> fd, ' %s = get_dict_from_hashtable_of_objects(%s);' % (return_pyvar_name, return_var_name) 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, ' if (%s) {' % return_var_name + print >> fd, ' %s = get_pystring_from_xml_node(%s);' % (return_pyvar_name, return_var_name) print >> fd, ' } else {' - print >> fd, ' return_pyvalue = noneRef();' + print >> fd, ' %s = noneRef();' % return_pyvar_name print >> fd, ' }' else: # return a PyGObjectPtr (wrapper around GObject) print >> fd, '''\ - if (return_value) { - return_pyvalue = PyGObjectPtr_New(G_OBJECT(return_value)); + if (%s) { + %s = PyGObjectPtr_New(G_OBJECT(%s)); } else { - return_pyvalue = noneRef(); + %s = noneRef(); } -''' +''' % (return_var_name, return_pyvar_name, return_var_name, return_pyvar_name) def generate_function_wrapper(self, m, fd): if m.rename: @@ -785,6 +795,9 @@ register_constants(PyObject *d) parse_tuple_args = [] for arg in m.args: arg_type, arg_name, arg_options = arg + arg_def = None + python_cvt_def = None + defval = None if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*'): arg_type = arg_type.replace('const ', '') if arg_options.get('optional'): @@ -794,7 +807,7 @@ register_constants(PyObject *d) else: parse_tuple_format.append('s') parse_tuple_args.append('&%s' % arg_name) - print >> fd, ' %s %s = NULL;' % (arg[0], arg[1]) + arg_def = ' %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: @@ -807,23 +820,34 @@ register_constants(PyObject *d) defval = defval[2:].upper() else: defval = defval[2:] - print >> fd, ' %s %s = %s;' % (arg[0], arg[1], defval) + arg_def = ' %s %s = %s;' % (arg[0], arg[1], defval) else: - print >> fd, ' %s %s;' % (arg[0], arg[1]) - elif arg_type in ('GList*', 'xmlNode*'): + arg_def = ' %s %s;' % (arg[0], arg[1]) + elif is_xml_node(arg) or is_list(arg) or is_time_t_pointer(arg): 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 + arg_def = ' %s %s = NULL;' % (arg[0], arg[1]) + python_cvt_def = ' 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 + arg_def = ' %s %s = NULL;' % (arg[0], arg[1]) + python_cvt_def = ' PyGObjectPtr *cvt_%s = NULL;' % arg_name + if is_out(arg): + arg_def = ' %s %s = NULL;' % (var_type(arg), arg[1]) + parse_tuple_format.pop() + parse_tuple_format.append('O') + parse_tuple_args.pop() + parse_tuple_args.append('&cvt_%s_out' % arg_name) + python_cvt_def = ' PyObject *cvt_%s_out = NULL;' % arg_name + print >> fd, ' PyObject *out_pyvalue = NULL;' + print >> fd, arg_def + if python_cvt_def: + print >> fd, python_cvt_def if m.return_type: print >> fd, ' %s return_value;' % m.return_type - print >> fd, ' PyObject* return_pyvalue;' + print >> fd, ' PyObject* return_pyvalue = NULL;' print >> fd, '' parse_tuple_args = ', '.join(parse_tuple_args) @@ -834,7 +858,9 @@ register_constants(PyObject *d) ''.join(parse_tuple_format), parse_tuple_args) for f, arg in zip(parse_tuple_format, m.args): - if arg[0] == 'GList*': + if is_out(arg): + continue + if is_list(arg): qualifier = arg[2].get('elem_type') if qualifier == 'char*': print >> fd, ' set_list_of_strings(&%s, cvt_%s);' % (arg[1], arg[1]) @@ -844,8 +870,10 @@ register_constants(PyObject *d) 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*': + elif is_xml_node(arg): print >> fd, ' %s = get_xml_node_from_pystring(cvt_%s);' % (arg[1], arg[1]) + elif is_time_t_pointer(arg): + print >> fd, ' %s = get_time_t(cvt_%s);' % (arg[1], arg[1]) elif f == 'O': print >> fd, ' %s = (%s)cvt_%s->obj;' % (arg[1], arg[0], arg[1]) @@ -853,10 +881,15 @@ register_constants(PyObject *d) 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])) + else: + print >> fd, ' ', + print >> fd, '%s(%s);' % (m.name, ', '.join([ref_name(x) for x in m.args])) for f, arg in zip(parse_tuple_format, m.args): - if arg[0] == 'GList*': + if is_out(arg): + self.return_value(fd, var_type(arg), {'elem_type': element_type(arg)}, return_var_name = arg[1], return_pyvar_name = 'out_pyvalue') + print >> fd, ' PyList_SetItem(cvt_%s_out, 0, out_pyvalue);' % arg[1] + elif arg[0] == 'GList*': qualifier = arg[2].get('elem_type') if qualifier == 'char*': print >> fd, ' free_list(&%s, (GFunc)g_free);' % arg[1] @@ -864,6 +897,8 @@ register_constants(PyObject *d) print >> fd, ' free_list(&%s, (GFunc)xmlFreeNode);' % arg[1] elif qualifier == 'LassoNode': print >> fd, ' free_list(&%s, (GFunc)g_object_unref);' % arg[1] + elif is_time_t_pointer(arg): + print >> fd, ' if (%s) free(%s);' % (arg[1], arg[1]) if not m.return_type: print >> fd, ' return noneRef();' diff --git a/bindings/python/tests/Makefile.am b/bindings/python/tests/Makefile.am index 64dfc090..c2130fb3 100644 --- a/bindings/python/tests/Makefile.am +++ b/bindings/python/tests/Makefile.am @@ -1,6 +1,8 @@ MAINTAINERCLEANFILES = Makefile.in TESTS = # +TESTS_ENVIRONMENT=TOP_SRCDIR=$(top_srcdir) + if PYTHON_ENABLED TESTS += profiles_tests.py binding_tests.py endif diff --git a/bindings/python/tests/idwsf1_tests.py b/bindings/python/tests/idwsf1_tests.py index a2f26b83..a37cd838 100755 --- a/bindings/python/tests/idwsf1_tests.py +++ b/bindings/python/tests/idwsf1_tests.py @@ -36,7 +36,7 @@ import lasso try: dataDir except NameError: - dataDir = '../../../tests/data' + dataDir = os.path.join(os.environ['TOP_SRCDIR'], 'tests', 'data') wsp_metadata = os.path.join(dataDir, 'sp1-la/metadata.xml') wsp_private_key = os.path.join(dataDir, 'sp1-la/private-key-raw.pem') @@ -51,6 +51,12 @@ idp_public_key = os.path.join(dataDir, 'idp1-la/public-key.pem') abstract_description = "Personal Profile Resource" resource_id = "http://idp/user/resources/1" +def __LINE__(): + try: + raise Exception + except: + return sys.exc_info()[2].tb_frame.f_back.f_lineno + class IdWsf1TestCase(unittest.TestCase): def get_wsp_server(self): server = lasso.Server(wsp_metadata, wsp_private_key, None, None) @@ -144,7 +150,7 @@ class IdWsf1TestCase(unittest.TestCase): # Process query idp_disco = lasso.Discovery(self.idp) - idp_disco.processQueryMsg(wsc_disco.msgBody) + idp_disco.processRequestMsg(wsc_disco.msgBody) idp_disco.setIdentityFromDump(idp_identity_dump) idp_disco.getIdentity().addResourceOffering(self.get_resource_offering()) idp_disco.buildResponseMsg() @@ -158,10 +164,12 @@ class DiscoveryQueryTestCase(IdWsf1TestCase): '''Test a discovery query''' service = self.get_pp_service() # Check service attributes - self.failUnless(service.resourceId is not None) - self.failUnless(service.resourceId.content == resource_id) - self.failUnless(service.providerId == self.wsc.providerIds[0]) - self.failUnless(service.abstractDescription == abstract_description) + resource_offering = service.getResourceOffering() + self.failUnless(resource_offering is not None) + self.failUnless(resource_offering.resourceId is not None) + self.failUnless(resource_offering.resourceId.content == resource_id) + self.failUnless(resource_offering.serviceInstance.providerId == self.wsc.providerIds[0]) + self.failUnless(resource_offering.abstract == abstract_description) class DiscoveryModifyTestCase(IdWsf1TestCase): def test01(self): @@ -177,16 +185,18 @@ class DiscoveryModifyTestCase(IdWsf1TestCase): wsp_disco = lasso.Discovery(self.wsp) wsp_disco.setIdentityFromDump(sp_identity_dump) wsp_disco.setSessionFromDump(sp_session_dump) - wsp_disco.initInsert(self.get_resource_offering()) + resource_offering = self.get_resource_offering() + wsp_disco.initModify() + wsp_disco.addInsertEntry(resource_offering.serviceInstance, resource_offering.resourceId) wsp_disco.buildRequestMsg() # Process Modify request_type = lasso.getRequestTypeFromSoapMsg(wsp_disco.msgBody) self.failUnless(request_type == lasso.REQUEST_TYPE_DISCO_MODIFY) idp_disco = lasso.Discovery(self.idp) - idp_disco.processModifyMsg(wsp_disco.msgBody) + idp_disco.processRequestMsg(wsp_disco.msgBody) idp_disco.setIdentityFromDump(idp_identity_dump) - idp_disco.buildModifyResponseMsg() + idp_disco.buildResponseMsg() offerings = idp_disco.identity.getOfferings() self.failUnless('<disco:Status code="OK"/>' in idp_disco.msgBody) self.failUnless('<disco:ModifyResponse newEntryIDs="%s"' % offerings[0].entryId in idp_disco.msgBody) @@ -211,20 +221,21 @@ class DiscoveryRemoveTestCase(IdWsf1TestCase): wsp_disco = lasso.Discovery(self.wsp) wsp_disco.setIdentityFromDump(sp_identity_dump) wsp_disco.setSessionFromDump(sp_session_dump) - wsp_disco.initRemove('0') + wsp_disco.initModify() + wsp_disco.addRemoveEntry('0') wsp_disco.buildRequestMsg() # Process Modify request_type = lasso.getRequestTypeFromSoapMsg(wsp_disco.msgBody) self.failUnless(request_type == lasso.REQUEST_TYPE_DISCO_MODIFY) idp_disco = lasso.Discovery(self.idp) - idp_disco.processModifyMsg(wsp_disco.msgBody) + idp_disco.processRequestMsg(wsp_disco.msgBody) idp_disco.setIdentityFromDump(idp_identity_dump) offering = self.get_resource_offering() idp_disco.getIdentity().addResourceOffering(offering) self.failUnless('<disco:ServiceType>urn:liberty:id-sis-pp:2003-08</disco:ServiceType>' in idp_disco.identity.dump()) - idp_disco.buildModifyResponseMsg() + idp_disco.buildResponseMsg() self.failUnless('<disco:Status code="OK"/>' in idp_disco.msgBody) self.failIf('<disco:ServiceType>urn:liberty:id-sis-pp:2003-08</disco:ServiceType>' in idp_disco.identity.dump()) @@ -237,17 +248,19 @@ class DataServiceQueryTestCase(IdWsf1TestCase): '''Test a data service query''' wsc_service = self.get_pp_service() wsc_service.initQuery('/pp:PP/pp:InformalName', 'name') - wsc_service.buildRequestMsg() + wsc_service.buildSoapRequestMsg() self.failUnless(lasso.getRequestTypeFromSoapMsg(wsc_service.msgBody) == lasso.REQUEST_TYPE_DST_QUERY) self.wsp = self.get_wsp_server() wsp_service = lasso.DataService(self.wsp) - wsp_service.processQueryMsg(wsc_service.msgBody) + wsp_service.processRequestMsg(wsc_service.msgBody) + self.failUnless(isinstance(wsp_service.request, lasso.DstQuery)) wsp_service.resourceData = ''' <PP xmlns="urn:liberty:id-sis-pp:2003-08"> <InformalName>Damien</InformalName> </PP>''' + wsp_service.validateRequest() wsp_service.buildResponseMsg() wsc_service.processQueryResponseMsg(wsp_service.msgBody) diff --git a/bindings/python/tests/idwsf2_tests.py b/bindings/python/tests/idwsf2_tests.py index bbc66c5d..aff03816 100755 --- a/bindings/python/tests/idwsf2_tests.py +++ b/bindings/python/tests/idwsf2_tests.py @@ -40,7 +40,7 @@ import lasso try: dataDir except NameError: - dataDir = '../../../tests/data' + dataDir = os.path.join(os.environ['TOP_SRCDIR'], 'tests', 'data') class IdWsf2TestCase(unittest.TestCase): diff --git a/bindings/utils.py b/bindings/utils.py index a2370b9c..e1248d92 100644 --- a/bindings/utils.py +++ b/bindings/utils.py @@ -22,6 +22,18 @@ import re import string +_mapping_convert_type_from_gobject_annotation = { + 'utf8': 'char8' +} + +def convert_type_from_gobject_annotation(type): + return _mapping_convert_type_from_gobject_annotation.get(type, type) + +def clean_type(type): + type = type.strip() + type = re.sub('\s+', ' ', type) + return re.sub('\s*\*\s*', '*', type) + def format_as_camelcase(var): '''Format an identifier name into CamelCase''' if '_' in var: @@ -100,3 +112,102 @@ def group(list): +def _test_arg(arg, what): + return bool(arg[2].get(what)) + +def is_optional(arg): + return _test_arg(arg, 'optional') + +def element_type(arg): + return arg[2].get('element-type') + +def key_type(arg): + return arg[2].get('key-type') + +def value_type(arg): + return arg[2].get('value-type') + +def is_out(arg): + return _test_arg(arg, 'out') or arg_type(arg).endswith('**') + +def is_glist(arg): + return re.match('GList\>', var_type(arg)) + +def is_hashtable(arg): + return re.match('GHashTable\>', var_type(arg)) + +def var_type(arg): + '''Return the type of variable to store content''' + if is_out(arg): + return arg[0][:-1] + else: + return arg[0] + +def unref_type(arg): + return (var_type(arg), arg[1], arg[2]) + +def ref_name(arg): + if is_out(arg): + return '&%s' % arg[1] + else: + return arg[1] + +def arg_type(arg): + return arg[0] + +def arg_name(arg): + return arg[1] + +def unconstify(type): + return re.sub(r'\bconst\b\s*', '', type).strip() + +def make_arg(type): + return (type,'',{}) + +def arg_default(arg): + return arg[2].get('default') + +def remove_modifiers(type): + type = re.sub(r'\s*\bunsigned\b\s*', ' ', type).strip() + type = re.sub(r'\s*\bconst\b\s*', ' ', type).strip() + type = re.sub(r'\s*\bsigned\b\s*', ' ', type).strip() + type = re.sub(r'\s*\bvolatile\b\s*', ' ', type).strip() + return clean_type(type) + +def is_const(arg): + return bool(re.search(r'\bconst\b', arg_type(arg))) + +def is_cstring(arg): + return unconstify(arg_type(arg)) in ('char*','gchar*','guchar*') + +def is_xml_node(arg): + return unconstify(arg_type(arg)).startswith('xmlNode') + +def is_boolean(arg): + return arg_type(arg) in ('gboolean','bool') + +def is_pointer(arg): + return arg_type(arg).endswith('*') + +def is_list(arg): + return unconstify(arg_type(arg)).startswith('GList') + +def is_int(arg, binding_data): + return arg_type(arg) in [ 'int', 'gint', 'long', 'glong'] + binding_data.enums + +def is_time_t_pointer(arg): + return re.match(r'\btime_t*', unconstify(arg_type(arg))) + +def is_transfer_full(arg): + transfer = arg[2].get('transfer') + if transfer: + return transfer == 'full' + else: + return is_out(arg) or is_object(arg) + +_not_objects = ( 'GHashTable', 'GList', 'GType' ) + +def is_object(arg): + + t = unconstify(arg_type(arg)) + return t[0] in string.uppercase and not [ x for x in _not_objects if x in t ] |
