装饰 DBUS 方法

发布于 2024-10-18 09:22:24 字数 2130 浏览 1 评论 0原文

我正在尝试将 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

但这似乎......好吧,愚蠢。特别是如果由于某种原因我想导出非绑定方法。

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

I'm trying to combine DBUS' asynchronous method calls with Twisted's Deferreds, but I'm encountering trouble in tweaking the usual DBUS service method decorator to do this.

To use the DBUS async callbacks approach, you'd do:

class Service(dbus.service.Object):

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

There's a few places where I simply wrap those two methods in a Deferred, so I thought I'd create a decorator to do that for me:

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})

This, however, doesn't work since the method is bound and takes the first argument, resulting in this traceback:

$ 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

I could add an extra argument to the inner function there, like so:

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

But that seems... well, dumb. Especially if, for some reason, I want to export a non-bound method.

So is it possible to make this decorator work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

神也荒唐 2024-10-25 09:22:24

为什么它是愚蠢的?您已经假设您知道第一个位置参数(在 self 之后)是 Deferred。为什么假设您知道真正的第一位置参数是 self 更愚蠢?

如果您还想支持自由函数,那么编写另一个装饰器,并在您知道没有 self 参数出现时使用它。

Why is it dumb? You're already assuming you know that the first positional argument (after self) is a Deferred. Why is it more dumb to assume that you know that the real first position argument is self?

If you also want to support free functions, then write another decorator and use that when you know there is no self argument coming.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文