xibus

experimental pure python async D-Bus library
git clone https://git.ce9e.org/xibus.git

commit
d1b1b6d0956f81cadd0c323ead6e81e4dcd24eb6
parent
013aad6105305fe072b549256676351822aa4830
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2026-02-16 08:41
add acquire name

Diffstat

M xibus/client.py 25 +++++++++++++++++++++++++
M xibus/connection.py 15 ++++++++++++++-

2 files changed, 39 insertions, 1 deletions


diff --git a/xibus/client.py b/xibus/client.py

@@ -1,10 +1,24 @@
    1     1 import contextlib
   -1     2 import enum
    2     3 import random
    3     4 
    4     5 from .connection import DBusError
    5     6 from .schema import Schema
    6     7 
    7     8 
   -1     9 class NameFlag(enum.IntEnum):
   -1    10     ALLOW_REPLACEMENT = 0x1
   -1    11     REPLACE_EXISTING = 0x2
   -1    12     DO_NOT_QUEUE = 0x4
   -1    13 
   -1    14 
   -1    15 class RequestNameReply(enum.IntEnum):
   -1    16     PRIMARY_OWNER = 1
   -1    17     IN_QUEUE = 2
   -1    18     EXISTS = 3
   -1    19     ALREADY_OWNER = 4
   -1    20 
   -1    21 
    8    22 class SignalQueue:
    9    23     def __init__(self, queue, sender, path, iface, signal):
   10    24         self.queue = queue
@@ -111,6 +125,17 @@ class Client:
  111   125             finally:
  112   126                 await self.bus.call('RemoveMatch', [sq.rule], 's')
  113   127 
   -1   128     @contextlib.asynccontextmanager
   -1   129     async def acquire_name(self, name):
   -1   130         with self.con.call_queue(name) as queue:
   -1   131             reply = await self.bus.call('RequestName', (name, NameFlag.DO_NOT_QUEUE))
   -1   132             if reply != RequestNameReply.PRIMARY_OWNER:
   -1   133                 raise DBusError('Failed to acquire name', name, reply)
   -1   134             try:
   -1   135                 yield queue
   -1   136             finally:
   -1   137                 await self.bus.call('ReleaseName', (name,))
   -1   138 
  114   139     async def get_property(self, name, path, iface, prop):
  115   140         iprop = 'org.freedesktop.DBus.Properties'
  116   141         result = await self.call(name, path, iprop, 'Get', (iface, prop), 'ss')

diff --git a/xibus/connection.py b/xibus/connection.py

@@ -35,6 +35,7 @@ class Connection:
   35    35         self.serial = 0
   36    36         self.send_queue = []
   37    37         self.replies = {}
   -1    38         self.call_queues = {}
   38    39         self.signal_queues = set()
   39    40 
   40    41         if not self.loop:
@@ -57,7 +58,7 @@ class Connection:
   57    58                     future = self.replies.pop(msg.reply_serial)
   58    59                     future.set_result(msg)
   59    60             elif msg.type == MsgType.METHOD_CALL:
   60    -1                 raise NotImplementedError
   -1    61                 self.call_queues[msg.destination].put_nowait(msg)
   61    62             elif msg.type == MsgType.SIGNAL:
   62    63                 for queue in self.signal_queues:
   63    64                     queue.put_nowait(msg)
@@ -133,6 +134,18 @@ class Connection:
  133   134             self.signal_queues.remove(queue)
  134   135             queue.shutdown()
  135   136 
   -1   137     @contextmanager
   -1   138     def call_queue(self, name):
   -1   139         if name in self.call_queues:
   -1   140             raise ValueError(name)
   -1   141         queue = asyncio.Queue()
   -1   142         self.call_queues[name] = queue
   -1   143         try:
   -1   144             yield iter_queue(queue)
   -1   145         finally:
   -1   146             self.call_queues.pop(name)
   -1   147             queue.shutdown()
   -1   148 
  136   149     async def call(self, dest, path, iface, method, body, sig, flags=MsgFlag.NONE):
  137   150         if not RE_PATH.match(path):
  138   151             raise InvalidPathError(path)