Coder Social home page Coder Social logo

adbus's Introduction

python-adbus

D-Bus Binding for Python utilizing the Python's asyncio module.

Dependencies

  1. Python >= 3.7
  2. libsystemd >= 232 (don’t need systemd, just libsystemd which is a separate package)
  3. Cython >= 0.25.2

Building / Installing

  • To build in place for development python ./setup.py build_ext --inplace
  • The html documents are stored in gh-pages branch, so that GitHub will serve them as a GitHub Pages. To build them:
    1. check out the gh-pages branch into ../python-adbus/html
    2. cd into docs
    3. sphinx-apidoc -o source/ ../adbus
    4. make html

Unit-Tests

NOTE: Some test-cases require the busctl tool from systemd.

  • To run a specific unit-test from the root directory (eg.):
python -m unittest tests.test\_sdbus\_method.Test.test\_method\_single\_str
  • To run a specific unit-test module from the root directory (eg.):
python -m unittest tests.test\_sdbus\_method
  • To run all unit-tests from the root directory:
tox

Server Examples

Object Example

This is an example of an object, which can be connected to a service.

import adbus
import typing

class ExampleClass(adbus.server.Object):

    signal1: int = adbus.server.Signal()
    signal2: typing.List[int] = adbus.server.Signal()

    property1: str = adbus.server.Property('none', read_only=True, hidden=True)
    property2: typing.List[int] = adbus.server.Property(['rr', 'ff'], deprecated=True)

    def __init__(self, service):
        super().__init__(service, path='/xxx/yyy', interface='yyy.xxx')

    @adbus.server.method(name='test', hidden=True)
    def test_method(self, r: int, gg: str) -> int:
        return r + 10

    def do_something(self):
        self.signal1.emit(14)

Setting Multiple Properties

It's possible to set multiple properties at the same time, this will defer the property update signal, and send one signal for all property changes. It's good practice to use this when changing multiple properties, it will reduce traffic on the D-Bus.

NOTE: Must be running in a loop.

Client Examples

Accessing Remote Interface via a Proxy

It's possible to map a remote interface to a local instantiated class using a Proxy.

If the even loop isn't running no signals will caught, and properties will not cache (i.e. will read on every access instead of tracking the property changes signals)

The proxy opbject must be saved for as long as you want to activily receive signals. If the proxy object is garbage collected it will no longer receive signals and it won't forward them to a watcher.

service = adbus.Service(bus='session')
proxy = adbus.client.Proxy(service, 'com.example.xxx', '/com/example/Service1',
    interface='com.example.service.unit')

async def proxy_examples():
  await proxy.update() # initialize the proxy

  # == Access Properties
  await proxy.remote_propertyX.set(45)
  print(await proxy.remote_propertyY.get())

  # == or
  await proxy.remote_propertyX(45)
  print(await proxy.remote_propertyY())

  # == Access Methods
  asyncio.ensure_future(proxy.remote_method_foo("some info")) # don't wait for result
  x = await proxy.remote_method_bar(100, 12, -45) # wait for result

  # == Add a Coroutine to a Signal
  async def local_method(signal_data: int):
    print(signal_data)
  proxy.remote_signal.add(local_method)

  # == or
  proxy.remote_signal(local_method)

  # == Remove a Coroutine to a Signal
  proxy.remote_signal.remove(local_method)

  # == or (if already added)
  proxy.remote_signal(local_method)

  # == Access a method using a different interface name
  proxy['com.example.service.serve'].remote_method_800(b"data")

  # == Create a new proxy from a node in the proxy
  proxy_new = await proxy('Test')

  # == Loop through all nodes in a proxy
  sum_cnt = 0
  async for node in proxy:
      try:
          sum_cnt += await node.count
      except AttributeError:
          pass

  # == set multiple properties in one message (if linked to an adbus based server)
  async with proxy as p:
      p.property1 = "some data"
      p.property2 = [1,2,3,4,5]

loop = asyncio.get_event_loop()
loop.run_until_complete(proxy_examples())
loop.close()

Style Guide

For a consistent style all code is updated using yapf with the following options:

yapf --recursive --verbose --in-place --no-local-style --style="{dedent_closing_brackets: True, continuation_indent_width: 8, split_complex_comprehension: True}" <filename>

adbus's People

Contributors

ccx-jfront avatar charleseidsness avatar hamid-rostami avatar jameshilliard avatar laped83 avatar sth avatar tamaralyne avatar wuhanck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

adbus's Issues

Add a Set Multiple Property Method

Add D-Bus method to set multiple properties at a time. Similar to the with syntax.

This will limit D-Bus and internal traffic when more than one property is set.

Also add support to the proxy.

Add Proxy Interface

Provides a "virtual class" which access remote methods, properties, and signals.

Example of a usage scenario:

  service = adbus.client.Service('com.example.service', bus='session')
  proxy = adbus.client.Proxy(service, '/com/example/Service1',
  ¦ ¦ interface='com.example.service.unit')

  # == Access Properties
  proxy.remote_propertyX = 45
  print(proxy.remote_propertyY)

  # == Access Methods
  proxy.remote_method_foo("some info")
  x = proxy.remote_method_bar(100, 12, -45)

  # == Add a Call-Back to a Signal
  def local_method(signal_data: int):
  ¦ print(signal_data)

  proxy.remote_signal.connect(local_method)

  # == Remove a Call-Back to a Signal
  proxy.remote_signal.disconnect(local_method)

  # == Access a method using a different interface name
  proxy['com.example.service.serve'].remote_method_800(b"data")

  # == Change a Proxies default interface
  proxy = proxy['com.example.service.serve']

  # == Create a new proxy from a node in the proxy
  proxy_new = proxy('Test')['com.example.test']

  # == Create list of all nodes in the proxy
  proxies = proxy()['com.example.test']

  sum_cnt = 0 
  for proxy in proxies:
     try:
         sum_cnt += proxy.count
     except AttributeError:
         pass

Python 3.5 compatibility?

Hi,

Any chance the required version could be lowered to 3.5? 3.7 is not packaged for Debian Stretch (current stable).

Properties that are Lists of Strings Aren't Working

Single character strings work, but for others we get the error below, it's probably a memory issue:

Traceback (most recent call last):
File "adbus/sdbus/property.pyx", line 16, in adbus.sdbus.property_get_handler
File "adbus/sdbus/message.pyx", line 420, in adbus.sdbus.Message.append
File "adbus/sdbus/message.pyx", line 318, in adbus.sdbus.Message._append_array
File "adbus/sdbus/message.pyx", line 403, in adbus.sdbus.Message.append_multiple
File "adbus/sdbus/message.pyx", line 508, in adbus.sdbus.Message.append
adbus.sdbus.SdbusError: Unsupported signature type for append

Active Listen object is garbage collected

When using a adbus.client.Proxy to listen for a signal, a sdbus.Listen object is created. As long as that object exists the signal is received. When the Proxy goes out of scope the Listen object can be garbage collected, which will stop receiving of the signal.

This can be quite confusing because a because things might seem to work for a while before "randomly" stopping.

For example the following setup function works and watcher will be called when signals arrive, but only until garbage collection:

async def setup(watcher):
    service = adbus.Service(bus='session')
    proxy = adbus.client.Proxy(service, 'org.freedesktop.ScreenSaver', '/ScreenSaver')
    await proxy.update()
    proxy.ActiveChanged.add(watcher)

Some ideas how that could be improved:

  • Emit a warning when a Proxy with active listeners gets destroyed
  • Keep the Listen object alive even after the Proxy gets garbage collected
  • Use a context manager when listening for signals so it's clear when the signal listener goes out of scope

Typing problem in `signal2` in the Readme server example code

I try to run the following code (a shortened version of the server example from the Readme):

import adbus
import typing

class ExampleClass(adbus.server.Object):
    signal2: typing.List[int] = adbus.server.Signal()

This results in an exception:

Traceback (most recent call last):
  File "/home/sth/src/screenwatch-1/.venv/lib/python3.7/site-packages/adbus-1.0.1-py3.7-linux-x86_64.egg/adbus/server/signal.py", line 59, in __set_name__
    self.dbus_signature = [sdbus.dbus_signature(s) for s in signature]
  File "/home/sth/src/screenwatch-1/.venv/lib/python3.7/site-packages/adbus-1.0.1-py3.7-linux-x86_64.egg/adbus/server/signal.py", line 59, in <listcomp>
    self.dbus_signature = [sdbus.dbus_signature(s) for s in signature]
  File "/usr/lib/python3.7/typing.py", line 251, in inner
    return func(*args, **kwds)
  File "/usr/lib/python3.7/typing.py", line 626, in __getitem__
    params = tuple(_type_check(p, msg) for p in params)
  File "/usr/lib/python3.7/typing.py", line 626, in <genexpr>
    params = tuple(_type_check(p, msg) for p in params)
  File "/usr/lib/python3.7/typing.py", line 139, in _type_check
    raise TypeError(f"{msg} Got {arg!r:.100}.")
TypeError: Parameters to generic types must be types. Got 0.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "ex1.py", line 4, in <module>
    class ExampleClass(adbus.server.Object):
RuntimeError: Error calling __set_name__ on 'Signal' instance 'signal2' in 'ExampleClass'

systemd dbus activation timeout on first try

Hi. Iam trying to create an dbus service that is activated when needed by systemd like described in section (DBus activation) in the following link.

https://fedoraproject.org/wiki/Packaging:Systemd#DBus_activation

My issue is that the service is started but the first dbus call, that activated it, times out but the following calls afterwards works. I have tried to boil it down to the following code that can reproduce it.

Maybe I have misunderstood how to use adbus and I'm still pretty new in the async world. I appreciate any help and hope you can reproduce this issue with the following wall of text :)

I have tried to implement that the same Foo service as show in (which works in the first try):

https://github.com/stylesuxx/python-dbus-examples/blob/master/receiver.py

dbus service (receiver py)

#!/usr/bin/env python3
import adbus
import asyncio

service_name = 'sub.domain.tld'
object_path = '/tld/domain/sub/Test'
object_interface = 'tld.domain.sub.TestInterface'

class FooService(adbus.server.Object):
    def __init__(self, service):
        super().__init__(service, object_path, object_interface)

    @adbus.server.method()
    def foo(self) -> str:
        return 'Foo'

loop = asyncio.get_event_loop()

service = adbus.Service(service_name, bus='system', replace_existing=True, allow_replacement=True)

obj = FooService(service)

loop.run_forever()

systemd service unit file

cat /usr/lib/systemd/system/dbus-sub.domain.tld.service 
[Unit]
Description=Sub tld service test

[Service]
Type=dbus
BusName=sub.domain.tld
ExecStart=python3 /home/laa/git/cons/octopus/receiver.py
User=username

systemd system-services


cat /usr/share/dbus-1/system-services/sub.domain.tld.service 
[D-BUS Service]
Name=sub.domain.tld
SystemdService=dbus-sub.domain.tld.service

# This service should not be bus activated if systemd isn't running,
# so that activation won't conflict with the init script startup.
Exec=/bin/false

Allow dbus service

cat /etc/dbus-1/system.d/sub.domain.tld.conf 
<!DOCTYPE busconfig PUBLIC
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <policy user="username">
    <allow own="sub.domain.tld"/>
  </policy>
  <policy context="default">
    <allow send_destination="sub.domain.tld"/>
  </policy>
</busconfig>

Environment

cat /etc/redhat-release 
Fedora release 32 (Thirty Two

systemctl --version
systemd 245 (v245.4-1.fc32)

Python 3.8.2 (default, Feb 28 2020, 00:00:00) 
[GCC 10.0.1 20200216 (Red Hat 10.0.1-0.8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import adbus
>>> adbus.__version__
'1.1.1'

Output

time busctl call sub.domain.tld /tld/domain/sub/Test tld.domain.sub.TestInterface Foo 
Call failed: Connection timed out
real	0m25.017s
user	0m0.006s
sys	0m0.006s
 time busctl call sub.domain.tld /tld/domain/sub/Test tld.domain.sub.TestInterface Foo 
s "Foo"

real	0m0.013s
user	0m0.003s
sys	0m0.008s

new release

Could you do a new release so we can get the latest bugfixes :)

NoReply: Method call timed out

i think, you have to give timeout support on await proxy.update(). cuz why we wait 120 sec when we dont have proxy obj
like this

service = adbus.Service(bus='session')
proxy = await adbus.client.Proxy(service, bus_name, '/com/example/Service1',
                                   interface='com.example.service.unit').update(timeout_ms=5000)

Segfault in __pyx_f_5adbus_5sdbus_call_callback

Under some environments(such as ubuntu) I seem to get this segfault. Any idea why that would be happening?
backtrace:

(gdb) bt
#0  0x00007ffff340f2e6 in sd_bus_slot_unref () from /lib/x86_64-linux-gnu/libsystemd.so.0
#1  0x00007ffff34d1728 in __pyx_f_5adbus_5sdbus_call_callback (__pyx_v_m=0x1034330, 
    __pyx_v_userdata=0x7ffff2b77c78, __pyx_v_err=<optimized out>) at adbus/sdbus.c:21986
#2  0x00007ffff3409064 in ?? () from /lib/x86_64-linux-gnu/libsystemd.so.0
#3  0x00007ffff34d400e in __pyx_pf_5adbus_5sdbus_7Service_8process (__pyx_v_self=<optimized out>, 
    __pyx_v_self=<optimized out>) at adbus/sdbus.c:14618
#4  __pyx_pw_5adbus_5sdbus_7Service_9process (__pyx_v_self=0x7ffff3e0e830, unused=<optimized out>)
    at adbus/sdbus.c:14517
#5  0x00000000005d5a41 in _PyMethodDef_RawFastCallKeywords ()
#6  0x00000000005d7980 in _PyObject_FastCallKeywords ()
#7  0x000000000062ea6f in ?? ()
#8  0x00000000005d5ef7 in _PyMethodDef_RawFastCallDict ()
#9  0x00000000005d62da in PyCFunction_Call ()
#10 0x0000000000551e0c in _PyEval_EvalFrameDefault ()
#11 0x00000000005d68ec in _PyFunction_FastCallKeywords ()
#12 0x000000000054d21c in _PyEval_EvalFrameDefault ()
#13 0x00000000005d68ec in _PyFunction_FastCallKeywords ()
#14 0x000000000054d21c in _PyEval_EvalFrameDefault ()
#15 0x00000000005d68ec in _PyFunction_FastCallKeywords ()
#16 0x000000000054d21c in _PyEval_EvalFrameDefault ()
#17 0x00000000005d68ec in _PyFunction_FastCallKeywords ()
#18 0x000000000054d088 in _PyEval_EvalFrameDefault ()
#19 0x000000000054a8c1 in _PyEval_EvalCodeWithName ()
#20 0x000000000054cb83 in PyEval_EvalCode ()
#21 0x000000000062d012 in ?? ()
#22 0x000000000062d0ca in PyRun_FileExFlags ()
#23 0x000000000062ddd8 in PyRun_SimpleFileExFlags ()
#24 0x0000000000650ad5 in ?? ()
#25 0x0000000000650bfe in _Py_UnixMain ()
#26 0x00007ffff7bbc09b in __libc_start_main (main=0x4ba4a0 <main>, argc=2, argv=0x7fffffffd878, 
    init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd868)
    at ../csu/libc-start.c:308
#27 0x00000000005dee4a in _start ()

Rare Signature Decode Memory Error

Every once in a while I see this when trying to add a listen to a proxy:

  File "/usr/lib/python3.6/site-packages/adbus/client/proxy.py", line 468, in update
    self._update_interfaces()
  File "/usr/lib/python3.6/site-packages/adbus/client/proxy.py", line 481, in _update_interfaces
    self._changed_coroutines.get(name, None)
  File "/usr/lib/python3.6/site-packages/adbus/client/proxy.py", line 247, in __init__
    args=(interface, ),
  File "/usr/lib/python3.6/site-packages/adbus/client/listen.py", line 46, in __init__
    self.signature += sdbus.dbus_signature(param.annotation)
  File "adbus/sdbus/signature.pyx", line 125, in adbus.sdbus.dbus_signature
  File "adbus/sdbus/signature.pyx", line 118, in adbus.sdbus.dbus_signature
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe4 in position 0: invalid continuation byte

I added an extra debug message and got this:

==> typing.Dict[str, typing.Any] === b'\xe4{sv}'

That \xe4 should have been an 'a' (0x61). This maybe a memory issue?

adbus.sdbus.SdbusError: Failed to enter array b'y'

import asyncio
import adbus

async def create_service_proxy():
    name = 'cron'
    proxy = adbus.client.Proxy(
        adbus.Service(bus='session'),
        'org.freedesktop.systemd1',
        '/org/freedesktop/systemd1/unit/%s_2eservice' % name,
        interface='org.freedesktop.systemd1.Unit',
    )
    await proxy.update()
    return proxy

def main():
    loop = asyncio.get_event_loop()
    loop.run_until_complete(create_service_proxy())
    loop.close()

if __name__ == '__main__':
    main()

This program fails with error:

File "adbus/sdbus/call.pyx", line 13, in adbus.sdbus.call_callback
  File "adbus/sdbus/message.pyx", line 219, in adbus.sdbus.Message.read
  File "adbus/sdbus/message.pyx", line 133, in adbus.sdbus.Message._read_array
  File "adbus/sdbus/message.pyx", line 228, in adbus.sdbus.Message.read
  File "adbus/sdbus/message.pyx", line 198, in adbus.sdbus.Message._read_dict
  File "adbus/sdbus/message.pyx", line 222, in adbus.sdbus.Message.read
  File "adbus/sdbus/message.pyx", line 160, in adbus.sdbus.Message._read_variant
  File "adbus/sdbus/message.pyx", line 219, in adbus.sdbus.Message.read
  File "adbus/sdbus/message.pyx", line 133, in adbus.sdbus.Message._read_array
  File "adbus/sdbus/message.pyx", line 219, in adbus.sdbus.Message.read
  File "adbus/sdbus/message.pyx", line 129, in adbus.sdbus.Message._read_array
adbus.sdbus.SdbusError: Failed to enter array b'y'
sys:1: RuntimeWarning: coroutine 'get_all' was never awaited

Systemd: 237
libsystemd: 237-3ubuntu10.13
adbus: 0.2.0 from pypi
python: 3.6.7

Invalid read of size 1 in message.pyx

This is probably not the cause of the crash in #42 but when running in valgrind I got this warning.

==3908== Invalid read of size 1
==3908==    at 0x878C056: __pyx_f_5adbus_5sdbus_7Message_read (sdbus.c:8925)
==3908==    by 0x878F2AC: __pyx_f_5adbus_5sdbus_7Message__read_variant (sdbus.c:8274)
==3908==    by 0x878C296: __pyx_f_5adbus_5sdbus_7Message_read (sdbus.c:8994)
==3908==    by 0x8768590: __pyx_f_5adbus_5sdbus_7Message__read_dict (sdbus.c:8747)
==3908==    by 0x878C488: __pyx_f_5adbus_5sdbus_7Message_read (sdbus.c:9038)
==3908==    by 0x8771AE9: __pyx_f_5adbus_5sdbus_7Message__read_array (sdbus.c:7995)
==3908==    by 0x878C1A5: __pyx_f_5adbus_5sdbus_7Message_read (sdbus.c:8972)
==3908==    by 0x877FF0B: __pyx_f_5adbus_5sdbus_call_callback (sdbus.c:21941)
==3908==    by 0x87EA815: process_reply (sd-bus.c:2504)
==3908==    by 0x87F03C4: process_message (sd-bus.c:2683)
==3908==    by 0x87F0580: process_running (sd-bus.c:2745)
==3908==    by 0x87F088E: bus_process_internal (sd-bus.c:2963)
==3908==  Address 0x6575695 is 0 bytes after a block of size 5 alloc'd
==3908==    at 0x4835790: malloc (vg_replace_malloc.c:299)
==3908==    by 0x4D29439: strdup (strdup.c:42)
==3908==    by 0x87D7569: sd_bus_message_enter_container (bus-message.c:4034)
==3908==    by 0x878F27A: __pyx_f_5adbus_5sdbus_7Message__read_variant (sdbus.c:8223)
==3908==    by 0x878C296: __pyx_f_5adbus_5sdbus_7Message_read (sdbus.c:8994)
==3908==    by 0x8768590: __pyx_f_5adbus_5sdbus_7Message__read_dict (sdbus.c:8747)
==3908==    by 0x878C488: __pyx_f_5adbus_5sdbus_7Message_read (sdbus.c:9038)
==3908==    by 0x8771AE9: __pyx_f_5adbus_5sdbus_7Message__read_array (sdbus.c:7995)
==3908==    by 0x878C1A5: __pyx_f_5adbus_5sdbus_7Message_read (sdbus.c:8972)
==3908==    by 0x877FF0B: __pyx_f_5adbus_5sdbus_call_callback (sdbus.c:21941)
==3908==    by 0x87EA815: process_reply (sd-bus.c:2504)
==3908==    by 0x87F03C4: process_message (sd-bus.c:2683)
==3908== 

This(sdbus.c:8925) seems to be specific line doing the invalid read. For reference this is my generated sdbus.c.

Failed to read value with signature s

I have a dbus server with specific method with name New. Its Output signature is "is".
When I call it using busctl, there is no error. But when I using adbus, my client program can't grab string part of output and below exception occurs. So I can't using proxy for client and have to use adbus.client by assign "i" to response_signature to drop "s" part.

adbus.sdbus.SdbusError: Failed to read value with signature s: ENXIO

Here is my test client with adbus:

import adbus
import asyncio

name2 = "ir.elecplus.iot"
path2 = "/ir/elecplus/iot/Daemon1/Tasks"
iface2 = "ir.elecplus.iot.Daemon1.Tasks"


async def main():
    service = adbus.Service(bus='session')
    proxy = adbus.client.Proxy(service, name2, path2,
        interface=iface2)
    await proxy.update()
    ret = await proxy.New("body")
    print(ret)

asyncio.run(main())

Output of busctl in monitor mode:

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=2
  Sender=org.freedesktop.DBus  Destination=:1.146  Path=/org/freedesktop/DBus  Interface=org.freedesktop.DBus  Member=NameAcquired
  MESSAGE "s" {
          STRING ":1.146";
  };

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=4
  Sender=org.freedesktop.DBus  Destination=:1.146  Path=/org/freedesktop/DBus  Interface=org.freedesktop.DBus  Member=NameLost
  MESSAGE "s" {
          STRING ":1.146";
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1  Priority=0 Cookie=2
  Sender=:1.147  Destination=ir.elecplus.iot  Path=/ir/elecplus/iot/Daemon1/Tasks  Interface=org.freedesktop.DBus.Introspectable  Member=Introspect
  UniqueName=:1.147
  MESSAGE "" {
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1  Priority=0 Cookie=46  ReplyCookie=2
  Sender=:1.111  Destination=:1.147
  UniqueName=:1.111
  MESSAGE "s" {
          STRING "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
 <interface name="org.freedesktop.DBus.Peer">
  <method name="Ping"/>
  <method name="GetMachineId">
   <arg type="s" name="machine_uuid" direction="out"/>
  </method>
 </interface>
 <interface name="org.freedesktop.DBus.Introspectable">
  <method name="Introspect">
   <arg name="data" type="s" direction="out"/>
  </method>
 </interface>
 <interface name="org.freedesktop.DBus.Properties">
  <method name="Get">
   <arg name="interface" direction="in" type="s"/>
   <arg name="property" direction="in" type="s"/>
   <arg name="value" direction="out" type="v"/>
  </method>
  <method name="GetAll">
   <arg name="interface" direction="in" type="s"/>
   <arg name="properties" direction="out" type="a{sv}"/>
  </method>
  <method name="Set">
   <arg name="interface" direction="in" type="s"/>
   <arg name="property" direction="in" type="s"/>
   <arg name="value" direction="in" type="v"/>
  </method>
  <signal name="PropertiesChanged">
   <arg type="s" name="interface"/>
   <arg type="a{sv}" name="changed_properties"/>
   <arg type="as" name="invalidated_properties"/>
  </signal>
 </interface>
 <interface name="ir.elecplus.iot.Daemon1.Tasks">
  <method name="New">
   <arg type="s" direction="in"/>
   <arg type="i" direction="out"/>
   <arg type="s" direction="out"/>
  </method>
  <method name="Tasks">
   <arg type="ai" direction="out"/>
  </method>
  <method name="Body">
   <arg type="ai" direction="in"/>
   <arg type="as" direction="out"/>
  </method>
  <method name="Cancel">
   <arg type="ai" direction="in"/>
   <arg type="ab" direction="out"/>
  </method>
  <method name="Status">
   <arg type="ai" direction="in"/>
   <arg type="as" direction="out"/>
  </method>
 </interface>
</node>
";
  };

‣ Type=method_call  Endian=l  Flags=0  Version=1  Priority=0 Cookie=3
  Sender=:1.147  Destination=ir.elecplus.iot  Path=/ir/elecplus/iot/Daemon1/Tasks  Interface=ir.elecplus.iot.Daemon1.Tasks  Member=New
  UniqueName=:1.147
  MESSAGE "s" {
          STRING "body";
  };

‣ Type=method_return  Endian=l  Flags=1  Version=1  Priority=0 Cookie=47  ReplyCookie=3
  Sender=:1.111  Destination=:1.147
  UniqueName=:1.111
  MESSAGE "is" {
          INT32 6;
          STRING "";
  };

Another point is, I implemented a mock-up server using adbus with same input/output signature, the client (written using adbus) runs successfully and no exception occurs. (My main server written in C using sd-bus library)

This is my mock-up server program:

import adbus
import asyncio

name2 = "ir.elecplus.iot"
path2 = "/ir/elecplus/iot/Daemon1/Tasks"
iface2 = "ir.elecplus.iot.Daemon1.Tasks"



async def main():
    service = adbus.Service(bus='session')
    proxy = adbus.client.Proxy(service, name2, path2,
        interface=iface2)
    await proxy.update()
    ret = await proxy.New("body")
    print(ret)

asyncio.run(main())

`depreciated` and `deprectiated` parameters/properties should be spelled `deprecated`

Several classes have a depreciated or deprectiated constructor parameter and property. It should be spelled deprecated, like the underlying DBus property SD_BUS_VTABLE_DEPRECATED.

The easiest fix would be to just rename the parameters/properties.

If you want to stay backwards compatible with people using the old names you could also add keyword-only parameters with the old spellings, like for example in adbus/server/signal.py:

def __init__(
    self, name=None, deprecated=False, hidden=False, camel_convert=True,
    *, deprectiated=False
):
    self.deprecated = self.deprectiated = deprecated or deprectiated
    ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.