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
proxyobject.SetThis('foo')
bar = proxyobject.GetThat()
proxyobject.DoSomeOtherStuff()
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 DerivedClass.foo 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
else:
self._obj = object
# set up properties
for a in self.__dbus_properties__:
fget = lambda self: self._obj.get_dbus_method('Get' +
a.capitalize())()
fset = lambda self, value: self._obj.get_dbus_method('Set' +
a.capitalize())(value)
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'))
o.foo = 'Hello, '
o.bar = 'world!'
print o.foo, o.bar
Look for this stuff being used in GTG in the near future! (Also, fixes to my blog CSS…)
Comments
comments powered by Disqus