diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/dbus_bindings.pyx | 119 | ||||
| -rw-r--r-- | python/decorators.py | 12 | ||||
| -rw-r--r-- | python/proxies.py | 11 | ||||
| -rw-r--r-- | python/service.py | 43 | 
4 files changed, 124 insertions, 61 deletions
| diff --git a/python/dbus_bindings.pyx b/python/dbus_bindings.pyx index 4bf0893c..fe6e7777 100644 --- a/python/dbus_bindings.pyx +++ b/python/dbus_bindings.pyx @@ -77,9 +77,74 @@ class ByteArray(str):      def __init__(self, value):          str.__init__(self, value) +class SignatureIter(object): +    def __init__(self, string): +        object.__init__(self) +        self.remaining = string + +    def next(self): +        if self.remaining == '': +            raise StopIteration + +        signature = self.remaining +        block_depth = 0 +        block_type = None +        end = len(signature) + +        for marker in range(0, end): +            cur_sig = ord(signature[marker]) + +            if cur_sig == TYPE_ARRAY: +                pass +            elif cur_sig == DICT_ENTRY_BEGIN or cur_sig == STRUCT_BEGIN: +                if block_type == None: +                    block_type = cur_sig + +                if block_type == cur_sig: +                    block_depth = block_depth + 1 + +            elif cur_sig == DICT_ENTRY_END: +                if block_type == DICT_ENTRY_BEGIN: +                    block_depth = block_depth - 1 + +                if block_depth == 0: +                    end = marker +                    break + +            elif cur_sig == STRUCT_END: +                if block_type == STRUCT_BEGIN: +                    block_depth = block_depth - 1 + +                if block_depth == 0: +                    end = marker +                    break + +            else: +                if block_depth == 0: +                    end = marker +                    break + +        end = end + 1 +        self.remaining = signature[end:] +        return Signature(signature[0:end]) +  class Signature(str): +    """An iterable method signature. Iterating gives the signature of each +    argument in turn."""      def __init__(self, value): -        str.__init__(self, value) +        return str.__init__(self, value) + +    def __iter__(self): +        return SignatureIter(self) + +class VariantSignature(object): +    """A fake method signature which when iterated, is an endless stream +    of variants (handy with zip()). It has no string representation.""" +    def __iter__(self): +        return self + +    def next(self): +        return 'v'  class Byte(int):      def __init__(self, value): @@ -937,47 +1002,6 @@ cdef class MessageIter:          return ret -    def parse_signature_block(self, signature): -        remainder = '' -        sig = '' -        block_depth = 0 -        block_type = None -        -        for marker in range(0, len(signature)): -            cur_sig = ord(signature[marker]) - -            if cur_sig == TYPE_ARRAY: -                pass -            elif cur_sig == DICT_ENTRY_BEGIN or cur_sig == STRUCT_BEGIN: -                if block_type == None: -                    block_type = cur_sig - -                if block_type == cur_sig: -                    block_depth = block_depth + 1 - -            elif cur_sig == DICT_ENTRY_END: -                if block_type == DICT_ENTRY_BEGIN: -                    block_depth = block_depth - 1 - -                if block_depth == 0: -                    break - -            elif cur_sig == STRUCT_END: -                if block_type == STRUCT_BEGIN: -                    block_depth = block_depth - 1 - -                if block_depth == 0: -                    break - -            else: -                if block_depth == 0: -                    break -         -        marker = marker + 1 -        sig = signature[0:marker] -        remainder = signature[marker:] -        return (sig, remainder) -        def append_strict(self, value, sig):          if sig == TYPE_INVALID or sig == None: @@ -986,7 +1010,7 @@ cdef class MessageIter:          sig_type = ord(sig[0])          if sig_type == TYPE_STRING: -            retval = self.append(value) +            retval = self.append_string(value)          elif sig_type == TYPE_INT16:              retval = self.append_int16(value)          elif sig_type == TYPE_UINT16: @@ -1201,13 +1225,14 @@ cdef class MessageIter:              dict_entry_iter.__cinit__(&c_dict_entry_iter)              if signature: -                (tmp_sig, remainder) = self.parse_signature_block(signature) +                signature_iter = iter(Signature(signature)) +                tmp_sig = signature_iter.next()                  if not dict_entry_iter.append_strict(key, tmp_sig):                      dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)                      dbus_message_iter_close_container(self.iter, dict_iter.iter)                      return False -                (tmp_sig, remainder) = self.parse_signature_block(remainder) +                tmp_sig = signature_iter.next()                  if not dict_entry_iter.append_strict(value, tmp_sig):                      dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)                      dbus_message_iter_close_container(self.iter, dict_iter.iter) @@ -1239,10 +1264,10 @@ cdef class MessageIter:          struct_iter = MessageIter(level)          struct_iter.__cinit__(&c_struct_iter) -        remainder = signature +        signature_iter = iter(Signature(signature))          for item in python_struct:              if signature: -                (sig, remainder) = self.parse_signature_block(remainder) +                sig = signature_iter.next()                  if sig == '':                      dbus_message_iter_close_container(self.iter, struct_iter.iter) diff --git a/python/decorators.py b/python/decorators.py index b94babc4..8b553736 100644 --- a/python/decorators.py +++ b/python/decorators.py @@ -1,20 +1,22 @@ -import _util  +import _util  import inspect  import dbus_bindings -def method(dbus_interface): +def method(dbus_interface, in_signature=None, out_signature=None):      _util._validate_interface_or_name(dbus_interface)      def decorator(func):          func._dbus_is_method = True          func._dbus_interface = dbus_interface +        func._dbus_in_signature = in_signature +        func._dbus_out_signature = out_signature          func._dbus_args = inspect.getargspec(func)[0]          func._dbus_args.pop(0)          return func      return decorator -def signal(dbus_interface): +def signal(dbus_interface, signature=None):      _util._validate_interface_or_name(dbus_interface)      def decorator(func):          def emit_signal(self, *args, **keywords): @@ -27,9 +29,11 @@ def signal(dbus_interface):              self._connection.send(message) +        emit_signal.__name__ = func.__name__ +        emit_signal.__doc__ = func.__doc__          emit_signal._dbus_is_signal = True          emit_signal._dbus_interface = dbus_interface -        emit_signal.__name__ = func.__name__ +        emit_signal._dbus_signature = signature          emit_signal._dbus_args = inspect.getargspec(func)[0]          emit_signal._dbus_args.pop(0)          return emit_signal diff --git a/python/proxies.py b/python/proxies.py index efa2b501..f1f33941 100644 --- a/python/proxies.py +++ b/python/proxies.py @@ -62,14 +62,13 @@ class ProxyMethod:          # Add the arguments to the function          iter = message.get_iter(True) -	remainder = self._introspect_sig -        for arg in args: -            if self._introspect_sig: -                (sig, remainder) = iter.parse_signature_block(remainder) +        if self._introspect_sig: +            for (arg, sig) in zip(args, dbus_bindings.Signature(self._introspect_sig)):                  iter.append_strict(arg, sig) -            else: +        else: +            for arg in args:                  iter.append(arg) -        +          if ignore_reply:              result = self._connection.send(message)              args_tuple = (result,) diff --git a/python/service.py b/python/service.py index 0cc2ed9f..ce251ed5 100644 --- a/python/service.py +++ b/python/service.py @@ -1,6 +1,7 @@  import dbus_bindings   import _dbus +import operator  from exceptions import UnknownMethodException  from decorators import method  from decorators import signal @@ -57,14 +58,48 @@ def _dispatch_dbus_method_call(target_methods, self, argument_list, message):              error_name = e.__class__.__name__          else:              error_name = e.__module__ + '.' + str(e.__class__.__name__) -            error_contents = str(e) -            reply = dbus_bindings.Error(message, error_name, error_contents) + +        error_contents = str(e) +        reply = dbus_bindings.Error(message, error_name, error_contents)      else:          reply = dbus_bindings.MethodReturn(message) -        if retval != None: + +        # temporary - about to replace the method lookup code... +        target_parent = target_method +        target_name = str(target_method) + +        # do strict adding if an output signature was provided +        if target_parent._dbus_out_signature != None: +            # iterate signature into list of complete types +            signature = tuple(dbus_bindings.Signature(target_parent._dbus_out_signature)) + +            if retval == None: +                if len(signature) != 0: +                    raise TypeError('%s returned nothing but output signature is %s' % +                        (target_name, target_parent._dbus_out_signature)) +            elif len(signature) == 1: +                iter = reply.get_iter(append=True) +                iter.append_strict(retval, signature[0]) +            elif len(signature) > 1: +                if operator.isSequenceType(retval): +                    if len(signature) > len(retval): +                        raise TypeError('output signature %s is longer than the number of values returned by %s' % +                            (target_parent._dbus_out_signature, target_name)) +                    elif len(retval) > len(signature): +                        raise TypeError('output signature %s is shorter than the number of values returned by %s' % +                            (target_parent._dbus_out_signature, target_name)) +                    else: +                        iter = reply.get_iter(append=True) +                        for (value, sig) in zip(retval, signature): +                            iter.append_strict(value, sig) +                else: +                    raise TypeError('output signature %s has multiple values but %s didn\'t return a sequence type' % +                        (target_parent._dbus_out_signature, target_name)) + +        # try and guess the return type +        elif retval != None:              iter = reply.get_iter(append=True)              iter.append(retval) -	          return reply  class ObjectType(type): | 
