From f0f9ccfbd3b8de22e0b8d6904f51c41b5e606a9c Mon Sep 17 00:00:00 2001 From: Vendula Poncova Date: Fri, 3 Feb 2023 12:33:44 +0100 Subject: [PATCH] Use the message bus as a context manager Use `with message_bus:` instead of `message_bus.disconnect()` to automatically unregister DBus services and objects and disconnect from the established DBus connection. --- docs/examples.rst | 43 ++++++++++++++++++++------------ examples/03_helloworld/server.py | 8 +++--- examples/04_register/server.py | 8 +++--- examples/05_chat/server.py | 8 +++--- src/dasbus/connection.py | 8 ++++++ 5 files changed, 47 insertions(+), 28 deletions(-) diff --git a/docs/examples.rst b/docs/examples.rst index da4c534..bd53804 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -84,6 +84,10 @@ Asynchronously fetch a list of network devices. proxy.GetDevices(callback=callback) loop.run() + +Run a DBus service +------------------ + Define the org.example.HelloWorld service. .. code-block:: python @@ -118,21 +122,28 @@ Define the org.example.HelloWorld service with an automatically generated XML sp print(HelloWorld.__dbus_xml__) -Publish the org.example.HelloWorld service on the session message bus. +Publish the org.example.HelloWorld service on the session message bus. The service will +be unregistered automatically via the bus context manager. .. code-block:: python from dasbus.connection import SessionMessageBus - bus = SessionMessageBus() - bus.publish_object("/org/example/HelloWorld", HelloWorld()) - bus.register_service("org.example.HelloWorld") + with SessionMessageBus() as bus: + + bus.publish_object("/org/example/HelloWorld", HelloWorld()) + bus.register_service("org.example.HelloWorld") + +Start the event loop to process incoming D-Bus calls. + +.. code-block:: python from dasbus.loop import EventLoop loop = EventLoop() loop.run() -Support for Unix file descriptors ---------------------------------- + +Use Unix file descriptors +------------------------- The support for Unix file descriptors is disabled by default. It needs to be explicitly enabled when you create a DBus proxy or publish a DBus object that could send or receive Unix file @@ -175,8 +186,8 @@ Allow to send and receive Unix file descriptors within the /org/example/HelloWor server=GLibServerUnix ) -Management of DBus names and paths ----------------------------------- +Manage DBus names +----------------- Use constants to define DBus services and objects. @@ -215,8 +226,8 @@ Create a proxy of the /org/freedesktop/NetworkManager/Settings object. See `a complete example `__. -Error handling --------------- +Handle DBus errors +------------------ Use exceptions to propagate and handle DBus errors. Create an error mapper and a decorator for mapping Python exception classes to DBus error names. @@ -246,8 +257,8 @@ to DBus errors and back. See `a complete example `__. -Timeout for a DBus call ------------------------ +Call methods with timeout +------------------------- Call DBus methods with a timeout (specified in milliseconds). @@ -261,8 +272,8 @@ Call DBus methods with a timeout (specified in milliseconds). print("The call timed out!") -Support for DBus structures ---------------------------- +Handle DBus structures +---------------------- Represent DBus structures by Python objects. A DBus structure is a dictionary of attributes that maps attribute names to variants with attribute values. Use Python objects to define such @@ -296,8 +307,8 @@ an object. See `a complete example `__. -Management of dynamic DBus objects ----------------------------------- +Manage groups of DBus objects +----------------------------- Create Python objects that can be automatically published on DBus. These objects are usually managed by DBus containers and published on demand. diff --git a/examples/03_helloworld/server.py b/examples/03_helloworld/server.py index 781d330..23d5f5c 100644 --- a/examples/03_helloworld/server.py +++ b/examples/03_helloworld/server.py @@ -25,7 +25,10 @@ def Hello(self, name: Str) -> Str: # Print the generated XML specification. print(XMLGenerator.prettify_xml(HelloWorld.__dbus_xml__)) - try: + # Use the message bus as context manager to automatically + # unregister the DBus service and objects at the end. + with SESSION_BUS: + # Create an instance of the class HelloWorld. hello_world = HelloWorld() @@ -38,6 +41,3 @@ def Hello(self, name: Str) -> Str: # Start the event loop. loop = EventLoop() loop.run() - finally: - # Unregister the DBus service and objects. - SESSION_BUS.disconnect() diff --git a/examples/04_register/server.py b/examples/04_register/server.py index b30676f..1e03a2a 100644 --- a/examples/04_register/server.py +++ b/examples/04_register/server.py @@ -60,7 +60,10 @@ def register_user(self, user: User): # Print the generated XML specification. print(XMLGenerator.prettify_xml(RegisterInterface.__dbus_xml__)) - try: + # Use the message bus as context manager to automatically + # unregister the DBus service and objects at the end. + with SESSION_BUS: + # Create the register. register = Register() @@ -78,6 +81,3 @@ def register_user(self, user: User): # Start the event loop. loop = EventLoop() loop.run() - finally: - # Unregister the DBus service and objects. - SESSION_BUS.disconnect() diff --git a/examples/05_chat/server.py b/examples/05_chat/server.py index 24c5c8e..83aa83f 100644 --- a/examples/05_chat/server.py +++ b/examples/05_chat/server.py @@ -85,7 +85,10 @@ def find_room(self, name): print(XMLGenerator.prettify_xml(ChatInterface.__dbus_xml__)) print(XMLGenerator.prettify_xml(RoomInterface.__dbus_xml__)) - try: + # Use the message bus as context manager to automatically + # unregister the DBus service and objects at the end. + with SESSION_BUS: + # Create the chat. chat = Chat() @@ -98,6 +101,3 @@ def find_room(self, name): # Start the event loop. loop = EventLoop() loop.run() - finally: - # Unregister the DBus service and objects. - SESSION_BUS.disconnect() diff --git a/src/dasbus/connection.py b/src/dasbus/connection.py index bc653e3..704a3eb 100644 --- a/src/dasbus/connection.py +++ b/src/dasbus/connection.py @@ -144,6 +144,14 @@ def disconnect(self): """Disconnect from DBus.""" pass + def __enter__(self): + """Connect to DBus as a context manager.""" + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Disconnect from DBus as a context manager.""" + self.disconnect() + class MessageBus(AbstractMessageBus): """Representation of a message bus based on D-Bus."""