Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support async methods #58

Open
pespin opened this issue May 31, 2017 · 5 comments
Open

Support async methods #58

pespin opened this issue May 31, 2017 · 5 comments

Comments

@pespin
Copy link

pespin commented May 31, 2017

I could not find any API which exports or uses async methods from Gio. I was able to workaround the issue by implementing the following snippet in my code:

def __async_result_handler(obj, result, user_data):
    '''Generic callback dispatcher called from glib loop when an async method
    call has returned. This callback is set up by method dbus_async_call.'''
    (result_callback, error_callback, real_user_data) = user_data
    try:
        ret = obj.call_finish(result)
    except Exception:
        etype, e = sys.exc_info()[:2]
        # return exception as value
        if error_callback:
            error_callback(obj, e, real_user_data)
        else:
            result_callback(obj, e, real_user_data)
        return

    ret = ret.unpack()
    # to be compatible with standard Python behaviour, unbox
    # single-element tuples and return None for empty result tuples
    if len(ret) == 1:
        ret = ret[0]
    elif len(ret) == 0:
        ret = None
    result_callback(obj, ret, real_user_data)

def dbus_async_call(proxymethod, instance, *args, **kwargs):
    '''pydbus doesn't support asynchronous methods. This method adds support for
    it until pydbus implements it'''
    argdiff = len(args) - len(proxymethod._inargs)
    if argdiff < 0:
        raise TypeError(proxymethod.__qualname__ + " missing {} required positional argument(s)".format(-argdiff))
    elif argdiff > 0:
        raise TypeError(proxymethod.__qualname__ + " takes {} positional argument(s) but {} was/were given".format(len(proxymethod._inargs), len(args)))

    timeout = kwargs.get("timeout", 30) * 1000
    user_data = (kwargs['result_handler'], kwargs.get('error_handler'), kwargs.get('user_data'))

    ret = instance._bus.con.call(
        instance._bus_name, instance._path,
        proxymethod._iface_name, proxymethod.__name__,
        GLib.Variant(proxymethod._sinargs, args), GLib.VariantType.new(proxymethod._soutargs),
        0, timeout, None,
        __async_result_handler, user_data)

Then call it with something like this:

        dbus_async_call(nr.Scan, nr, timeout=30, result_handler=self.scan_result_cb,
                        error_handler=self.raise_exn_cb, user_data=None)

    def raise_exn_cb(self, obj, e, user_data):
        pass

    def scan_result_cb(self, obj, result, user_data):
        self.register(result)

It would be nice that pydbus could support this out of the box, by using something like dbus_object.foo_method(param0, ..., param N, timeout=XYZ, reply_handler=myfunction, error_handler=myotherfunction)

@hcoin
Copy link

hcoin commented May 31, 2017 via email

@pespin
Copy link
Author

pespin commented Jun 8, 2017

Hi, what's your current status and your target? Do you plan to merge those changes back in this repo?

Timeout being set at registration time means it's set once for the entire proxy object? imho it would be nice being able to set the timeout at least for each method, and possibly also each time we call the method.

@hcoin
Copy link

hcoin commented Jun 8, 2017

Thanks for this interest. Your answers (I hope) are here: https://github.com/hcoin/pydbus/blob/master/status.txt

@hcoin
Copy link

hcoin commented Jul 25, 2017

Much work done, only one major commit left. Plus install instructions known good for all major distros including publishing on pre 2.46 glibs. https://github.com/hcoin/pydbus
I'm planning to have it be 'alpha release ready' 8/1/17.
I will be looking for a few people with known pydbus experience to be committers along with me.

@hcoin
Copy link

hcoin commented Jul 25, 2017

Hopefully Linus too!

poncovka added a commit to poncovka/pydbus that referenced this issue Jul 27, 2017
Added support for asynchronous calls of methods. A method is called
synchronously unless its callback parameter is specified. A callback
is a function f(*args, returned=None, error=None), where args is
callback_args specified in the method call, returned is a return
value of the method and error is an exception raised by the method.

Example of an asynchronous call:

def func(x, y, returned=None, error=None):
  pass

proxy.Method(a, b, callback=func, callback_args=(x, y))
poncovka added a commit to poncovka/pydbus that referenced this issue Jul 28, 2017
Added support for asynchronous calls of methods. A method is called
synchronously unless its callback parameter is specified. A callback
is a function f(*args, returned=None, error=None), where args is
callback_args specified in the method call, returned is a return
value of the method and error is an exception raised by the method.

Example of an asynchronous call:

def func(x, y, returned=None, error=None):
  pass

proxy.Method(a, b, callback=func, callback_args=(x, y))
poncovka added a commit to poncovka/pydbus that referenced this issue Jul 28, 2017
Added support for asynchronous calls of methods. A method is called
synchronously unless its callback parameter is specified. A callback
is a function f(*args, returned=None, error=None), where args is
callback_args specified in the method call, returned is a return
value of the method and error is an exception raised by the method.

Example of an asynchronous call:

def func(x, y, returned=None, error=None):
  pass

proxy.Method(a, b, callback=func, callback_args=(x, y))
poncovka added a commit to poncovka/pydbus that referenced this issue Jul 28, 2017
Added support for asynchronous calls of methods. A method is called
synchronously unless its callback parameter is specified. A callback
is a function f(*args, returned=None, error=None), where args is
callback_args specified in the method call, returned is a return
value of the method and error is an exception raised by the method.

Example of an asynchronous call:

def func(x, y, returned=None, error=None):
  pass

proxy.Method(a, b, callback=func, callback_args=(x, y))
poncovka added a commit to poncovka/pydbus that referenced this issue Jul 28, 2017
Added support for asynchronous calls of methods. A method is called
synchronously unless its callback parameter is specified. A callback
is a function f(*args, returned=None, error=None), where args is
callback_args specified in the method call, returned is a return
value of the method and error is an exception raised by the method.

Example of an asynchronous call:

def func(x, y, returned=None, error=None):
  pass

proxy.Method(a, b, callback=func, callback_args=(x, y))
molobrakos added a commit to molobrakos/pydbus that referenced this issue Mar 10, 2019
Sdrkun pushed a commit to openEuler-BaseService/pydbus that referenced this issue Dec 9, 2020
Added support for asynchronous calls of methods. A method is called
synchronously unless its callback parameter is specified. A callback
is a function f(*args, returned=None, error=None), where args is
callback_args specified in the method call, returned is a return
value of the method and error is an exception raised by the method.

Example of an asynchronous call:

def func(x, y, returned=None, error=None):
  pass

proxy.Method(a, b, callback=func, callback_args=(x, y))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants