DBus is great, and so is Python—each for their own reasons. One mismatch is that everything passing over the bus must be a message or signal. You wind up with Python code that looks like

bar = proxyobject.GetThat()

But then you realize the dbus-python binding is very Pythonic, so you can extend it in a Pythonic way. Here's something I banged together in about half an hour:

 import dbus

 class FancyInterface(dbus.Interface):
     """A fancier DBus Interface.

     Derived classes should define a list of strings __dbus_properties__ and a
     _dbus_interface. For every listed property ('foo') the named interface
     should support two methods:
       * GetFoo() -- accepts nothing, returns a single value.
       * SetFoo(..) -- returns nothing, accepts a single value of the same type
         as GetFoo.

     Then may be accessed as if it were a normal variable.

     def __init__(self, object):
         # next four lines from dbus.Interface.__init__()
         if isinstance(object, dbus.Interface):
             self._obj = object.proxy_object
             self._obj = object
         # set up properties
         for a in self.__dbus_properties__:
             fget = lambda self: self._obj.get_dbus_method('Get' +
             fset = lambda self, value: self._obj.get_dbus_method('Set' +
             setattr(self.__class__, a, property(fget, fset))

 class Sample(FancyInterface):
     _dbus_interface = 'com.example.SampleInterface'
     __dbus_properties__ = ('foo', 'bar',)
     def __init__(self, object): FancyInterface.__init__(self, object)
     # this class is 'empty' otherwise…

Using FancyInterface, it becomes even easier to forget you're talking to a proxy of a remote object:

bus = dbus.SessionBus()
o = Sample(bus.get_object('com.example.SampleService',
  '/SomeObject')) = 'Hello, ' = 'world!'

Look for this stuff being used in GTG in the near future! (Also, fixes to my blog CSS…)


comments powered by Disqus