装饰DBUS方法

时间:2011-02-20 10:14:47

标签: python twisted dbus

我正在尝试将DBUS的异步方法调用与Twisted的Deferreds结合起来,但我在修改通常的DBUS服务方法装饰器时遇到了麻烦。

要使用DBUS异步回调方法,您可以:

class Service(dbus.service.Object):

    @dbus.service.method(INTERFACE, async_callbacks=('callback', 'errback'))
    def Resources(self, callback, errback):
        callback({'Magic' : 42})

有几个地方我只是简单地将这两个方法包装在Deferred中,所以我想我会创建一个装饰器来为我做这个:

def twisted_dbus(*args, **kargs):
    def decorator(real_func):

        @dbus.service.method(*args, async_callbacks=('callback', 'errback'), **kargs)
        def wrapped_func(callback, errback, *inner_args, **inner_kargs):
            d = defer.Deferred()
            d.addCallbacks(callback, errback)
            return real_func(d, *inner_args, **inner_kargs)

        return wrapped_func

    return decorator

class Service(dbus.service.Object):

    @twisted_dbus(INTERFACE)
    def Resources(self, deferred):
        deferred.callback({'Magic' : 42})

然而,这不起作用,因为该方法被绑定并接受第一个参数,从而导致此回溯:

$ python service.py 
Traceback (most recent call last):
  File "service.py", line 25, in <module>
    class StatusCache(dbus.service.Object):
  File "service.py", line 32, in StatusCache
    @twisted_dbus(INTERFACE)
  File "service.py", line 15, in decorator
    @dbus.service.method(*args, async_callbacks=('callback', 'errback'), **kargs)
  File "/usr/lib/pymodules/python2.6/dbus/decorators.py", line 165, in decorator
    args.remove(async_callbacks[0])
ValueError: list.remove(x): x not in list

可以在内部函数中添加一个额外的参数,如下所示:

def twisted_dbus(*args, **kargs):
    def decorator(real_func):

        @dbus.service.method(*args, async_callbacks=('callback', 'errback'), **kargs)
        def wrapped_func(possibly_self, callback, errback, *inner_args, **inner_kargs):
            d = defer.Deferred()
            d.addCallbacks(callback, errback)
            return real_func(possibly_self, d, *inner_args, **inner_kargs)

        return wrapped_func

    return decorator

但这似乎......嗯,愚蠢。特别是如果出于某种原因,我想导出一个非约束方法。

那么可以让这个装饰工作吗?

1 个答案:

答案 0 :(得分:0)

为什么愚蠢?你已经假定你知道第一个位置参数(在self之后)是Deferred。假设你知道真正的第一个立场论证是自我,为什么更愚蠢?

如果你也想支持免费函数,那么写另一个装饰器,当你知道没有自我论证时就使用它。