Public feed #377217

Something

public text v1 · immutable
Raw Edit
·published 2007-03-01 16:00 UTC
rendered paste body
class FallbackObject(dbus.service.Object):
    """A base class for exporting your own Objects across the Bus.

    Just inherit from Object and provide a list of methods to share
    across the Bus
    """
    def __init__(self, bus_name, fallback_object_path):
        self._object_path = fallback_object_path
        self._name = bus_name 
        self._bus = bus_name.get_bus()
            
        self._connection = self._bus.get_connection()
        self._connection._register_object_path(fallback_object_path, self._message_cb, self._unregister_cb, True)

    def _message_cb(self, connection, message):
        try:
            # lookup candidate method and parent method
            method_name = message.get_member()
            interface_name = message.get_interface()
            (candidate_method, parent_method) = dbus.service._method_lookup(self, method_name, interface_name)

            # set up method call parameters
            args = message.get_args_list()
            keywords = {}

            # iterate signature into list of complete types
            if parent_method._dbus_out_signature:
                signature = tuple(dbus.types.Signature(parent_method._dbus_out_signature))
            else:
                signature = None

            # set up async callback functions
            if parent_method._dbus_async_callbacks:
                (return_callback, error_callback) = parent_method._dbus_async_callbacks
                keywords[return_callback] = lambda *retval: dbus.service._method_reply_return(connection, message, method_name, signature, *retval)
                keywords[error_callback] = lambda exception: dbus.service._method_reply_error(connection, message, exception)

            # include the sender if desired
            if parent_method._dbus_sender_keyword:
                keywords[parent_method._dbus_sender_keyword] = message.get_sender()

            if parent_method._dbus_message_keyword:
                keywords[parent_method._dbus_message_keyword] = message

            # call method
            retval = candidate_method(self, *args, **keywords)

            # we're done - the method has got callback functions to reply with
            if parent_method._dbus_async_callbacks:
                return

            # otherwise we send the return values in a reply. if we have a
            # signature, use it to turn the return value into a tuple as
            # appropriate
            if parent_method._dbus_out_signature:
                # if we have zero or one return values we want make a tuple
                # for the _method_reply_return function, otherwise we need
                # to check we're passing it a sequence
                if len(signature) == 0:
                    if retval == None:
                        retval = ()
                    else:
                        raise TypeError('%s has an empty output signature but did not return None' %
                            method_name)
                elif len(signature) == 1:
                    retval = (retval,)
                else:
                    if operator.isSequenceType(retval):
                        # multi-value signature, multi-value return... proceed unchanged
                        pass
                    else:
                        raise TypeError('%s has multiple output values in signature %s but did not return a sequence' %
                            (method_name, signature))

            # no signature, so just turn the return into a tuple and send it as normal
            else:
                signature = None
                if retval == None:
                    retval = ()
                else:
                    retval = (retval,)

            dbus.service._method_reply_return(connection, message, method_name, signature, *retval)
        except Exception, exception:
            # send error reply
            dbus.service._method_reply_error(connection, message, exception)

    @method('org.freedesktop.DBus.Introspectable', in_signature='', out_signature='s', dbus_message_keyword="dbus_message")
    def Introspect(self, dbus_message=None):
        reflection_data = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">\n'
        op = dbus_message.get_path()
        reflection_data += '<node name="%s">\n' % (op)

        interfaces = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__]
        for (name, funcs) in interfaces.iteritems():
            reflection_data += '  <interface name="%s">\n' % (name)

            for func in funcs.values():
                if getattr(func, '_dbus_is_method', False):
                    reflection_data += self.__class__._reflect_on_method(func)
                elif getattr(func, '_dbus_is_signal', False):
                    reflection_data += self.__class__._reflect_on_signal(func)

            reflection_data += '  </interface>\n'

        reflection_data += '</node>\n'

        return reflection_data

    def __repr__(self):
        return '<dbus_helpers.FallbackObject %s on %r at %#x>' % (self._object_path, self._name, id(self))
    __str__ = __repr__