Introducing python-dbus-next: The Next Generation DBus Library for Python
Are you a developer looking for a powerful and comprehensive library to integrate your applications into Linux desktop and mobile environments? Look no further! Allow us to introduce python-dbus-next, the next great DBus library for Python. In this article, we will explore its key features, installation process, and demonstrate how to use it for both client and service interfaces.
What is python-dbus-next?
python-dbus-next is a Python library that aims to be a fully featured high-level DBus library primarily geared towards integration of applications into Linux desktop and mobile environments. It allows developers to integrate their applications into desktop environments by implementing common DBus standard interfaces or creating custom plugin interfaces. Moreover, desktop users can leverage this library to create their own scripts and utilities for customization of their desktop environment.
Key Features
python-dbus-next plans to improve over other DBus libraries for Python in the following ways:
- Zero dependencies and pure Python 3.
- Support for multiple IO backends including asyncio and the GLib main loop.
- Nonblocking IO suitable for GUI development.
- Target the latest language features of Python for beautiful services and clients.
- Complete implementation of the DBus type system without ever guessing types.
- Integration tests for all features of the library.
- Completely documented public API.
Installation
Getting started with python-dbus-next is quick and easy. Simply follow these steps:
- Install the library from PyPi using pip3:
bash
pip3 install dbus-next
That’s it! You are now ready to explore the power of python-dbus-next in your projects.
The Client Interface
The client interface of python-dbus-next allows you to interact with services on the bus by constructing proxy objects. These proxy objects enable you to call methods, get and set properties, and listen to signals. Let’s take a look at an example that demonstrates how to control a media player using the MPRIS DBus interface:
“`python
Import the required modules
from dbus_next.aio import MessageBus
import asyncio
Initialize the event loop
loop = asyncio.get_event_loop()
Define the main function
async def main():
# Connect to the MessageBus
bus = await MessageBus().connect()
# Introspect the media player interface
introspection = await bus.introspect('org.mpris.MediaPlayer2.vlc', '/org/mpris/MediaPlayer2')
# Get the proxy object for the media player interface
obj = bus.get_proxy_object('org.mpris.MediaPlayer2.vlc', '/org/mpris/MediaPlayer2', introspection)
player = obj.get_interface('org.mpris.MediaPlayer2.Player')
properties = obj.get_interface('org.freedesktop.DBus.Properties')
# Call methods on the interface (this causes the media player to play)
await player.call_play()
# Get and set properties
volume = await player.get_volume()
print(f'current volume: {volume}, setting to 0.5')
await player.set_volume(0.5)
# Listen to signals
def on_properties_changed(interface_name, changed_properties, invalidated_properties):
for changed, variant in changed_properties.items():
print(f'property changed: {changed} - {variant.value}')
properties.on_properties_changed(on_properties_changed)
await loop.create_future()
Run the main function
loop.run_until_complete(main())
“`
The above example demonstrates how python-dbus-next simplifies the process of interacting with DBus services. It enables you to control a media player by calling methods, getting and setting properties, and listening to signals.
The Service Interface
If you’re looking to define a service on the bus, python-dbus-next provides the ServiceInterface
class. By using this class and decorating class methods, you can specify DBus methods, properties, and signals with their type signatures. Here’s an example that shows how to define and export a service interface:
“`python
Import the required modules
from dbus_next.service import ServiceInterface, method, dbus_property, signal, Variant
from dbus_next.aio import MessageBus
import asyncio
Define the ExampleInterface class
class ExampleInterface(ServiceInterface):
def init(self, name):
super().init(name)
self._string_prop = ‘kevin’
@method()
def Echo(self, what: 's') -> 's':
return what
@method()
def GetVariantDict() -> 'a{sv}':
return {
'foo': Variant('s', 'bar'),
'bat': Variant('x', -55),
'a_list': Variant('as', ['hello', 'world'])
}
@dbus_property()
def string_prop(self) -> 's':
return self._string_prop
@string_prop.setter
def string_prop_setter(self, val: 's'):
self._string_prop = val
@signal()
def signal_simple(self) -> 's':
return 'hello'
Define the main function
async def main():
# Connect to the MessageBus
bus = await MessageBus().connect()
interface = ExampleInterface(‘test.interface’)
# Export the service on the bus
bus.export('/test/path', interface)
# Request a name from D-Bus
await bus.request_name('test.name')
# Wait indefinitely
await asyncio.get_event_loop().create_future()
Run the main function
asyncio.get_event_loop().run_until_complete(main())
“`
The above example demonstrates how to define a service interface using python-dbus-next. It showcases how to define methods, properties, and signals, and how to export the service on the bus.
The Low-Level Interface
If you prefer working with DBus messages directly, python-dbus-next provides a low-level interface that allows you to interact with DBus messages at a lower level of abstraction. Here’s an example that demonstrates how to use the low-level interface:
“`python
Import the required modules
from dbus_next.message import Message, MessageType
from dbus_next.aio import MessageBus
import asyncio
import json
Initialize the event loop
loop = asyncio.get_event_loop()
Define the main function
async def main():
# Connect to the MessageBus
bus = await MessageBus().connect()
# Call a method on the D-Bus interface
reply = await bus.call(
Message(destination='org.freedesktop.DBus',
path='/org/freedesktop/DBus',
interface='org.freedesktop.DBus',
member='ListNames'))
if reply.message_type == MessageType.ERROR:
raise Exception(reply.body[0])
print(json.dumps(reply.body[0], indent=2))
Run the main function
loop.run_until_complete(main())
“`
The above example demonstrates how to use the low-level interface of python-dbus-next. It showcases how to call a method on a D-Bus interface and retrieve the response.
Projects that use python-dbus-next
python-dbus-next is already being used by various projects. Some notable examples include:
- The Playerctl test suite
- i3-dstatus
Conclusion
In this article, we introduced python-dbus-next, the next generation DBus library for Python. We explored its key features, installation process, and demonstrated how to use it for both client and service interfaces. Whether you are a desktop application developer or a desktop user looking to customize your environment, python-dbus-next is the perfect tool for integrating your applications into Linux desktop and mobile environments. So why wait? Start using python-dbus-next in your projects today and unlock the full potential of DBus integration.
Contributing
Contributions are welcome! If you’d like to contribute to python-dbus-next, visit the Github repository for more information. Before committing your changes, make sure to run the provided make
command to run the linter, code formatter, and the test suite.
Copyright
You can use python-dbus-next under the MIT license. For more information, see the LICENSE file in the Github repository.
Leave a Reply