telepathy-python

Services in telepathy-python are built off the service publishing built into dbus-python. However, to make implementing services easier, telepathy-python already provides interfaces and abstract base classes with all of the method decoration required already supplied.

12.2.1. Implementing a D-Bus Object

telepathy-python provides interfaces and abstract base classes for most Telepathy services you need to implement in the telepathy.server namespace. To implement a D-Bus object which can be published on the bus, you just need to subclass as many of these classes as required for the interfaces provided by your particular object.

Example 12-8 demonstrates publishing an Observer on the bus that implements Client.Observer and DBus.Properties.

Example 12-8Implementing Client.Observer and D-Bus Properties
class ExampleObserver(telepathy.server.Observer,
                      telepathy.server.DBusProperties):

    def __init__(self, *args):
        telepathy.server.Observer.__init__(self, *args)
        telepathy.server.DBusProperties.__init__(self)

        self._implement_property_get(CLIENT, {
            'Interfaces': lambda: [ CLIENT_OBSERVER ],
          })
        self._implement_property_get(CLIENT_OBSERVER, {
            'ObserverChannelFilter': lambda: dbus.Array([
                    dbus.Dictionary({
                    }, signature='sv')
                ], signature='a{sv}')
          })

    def ObserveChannels(self, account, connection, channels, dispatch_operation,
                        requests_satisfied, observer_info):
        print "Incoming channels on %s:" % (connection)
        for object, props in channels:
            print " - %s :: %s" % (props[CHANNEL + '.ChannelType'],
                                   props[CHANNEL + '.TargetID'])

Complete Source Code

The ObserveChannels method is already decorated with dbus.service.method by the telepathy.server.ClientObserver parent class, so doesn't need to be decorated in your subclass. However, we can redecorate the method if we want to change any of the parameters to dbus.service.method (e.g. using async_callbacks, which is useful when you need to emit a signal after returning from a D-Bus call). When doing this, the input and output signatures need to be provided again. See Example 12-9.

Emitting Signals after 'Returning'

Many times, the Telepathy specification requires a service to return from a method call before emitting any signals. The async_callbacks parameter to the dbus.service.method decorator is how to implement this.

See Example 12-9 for an example.

Example 12-9Redecorating a Method Call
@dbus.service.method(CONNECTION_INTERFACE_REQUESTS,
    in_signature='a{sv}', out_signature='boa{sv}',
    async_callbacks=('_success', '_error'))
def EnsureChannel(self, request, _success, _error):

    # code goes here

    # return success over D-Bus
    _success(yours, channel._object_path, props)

    # emit a signal
    self.signal_new_channels([channel])

12.2.2. Publishing an Object on the Bus

Publishing a Telepathy object on the bus is just like publishing any other object with dbus-python. Example 12-10 shows publishing our example Observer on the session bus.

Example 12-10Publishing a Client on the Bus
def publish(client_name):
    bus_name = '.'.join ([CLIENT, client_name])
    object_path = '/' + bus_name.replace('.', '/')

    bus_name = dbus.service.BusName(bus_name, bus=dbus.SessionBus())

    ExampleObserver(bus_name, object_path)

Complete Source Code

12.2.3. D-Bus Properties

D-Bus properties are handled via the telepathy.server.DBusProperties base class, which your class should inherit from.

Call the method _implement_property_get to provide a dictionary of the properties for a given interface. Properties are provided as Python callables, so static properties can be defined using lambda. See Example 12-8 for an example.