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.
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.
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'])
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.
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.
@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])
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.
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.