DASBUS(1)
DASBUS(1) β dasbus π
NAME β¨
okay so dasbus β dasbus, periodt. π
Dasbus is a DBus library written in Python 3, based on GLib and inspired by pydbus. The code used to be part of the Anaconda Installer project. It was based on the pydbus library, but we replaced it with our own solution because its upstream development stalled. The dasbus library is a result of this effort.
REQUIREMENTS π¦
- Python 3.6+
- PyGObject 3
You can install PyGObject provided by your operating system or use PyPI. The system package is usually called python3-gi, python3-gobject or pygobject3. See the instructions for your platform (only for PyGObject, you don't need cairo or GTK).
The library is known to work with Python 3.8, PyGObject 3.34 and GLib 2.63, but these are not the required minimal versions.
INSTALLATION π
Install the package from PyPI or install the package provided by your operating system if available.
Install from PyPI π
Follow the instructions above to install the requirements before you install dasbus with pip. The required dependencies has to be installed manually in this case.
pip3 install dasbus
Install on Arch Linux π§
Build and install the community package from the Arch User Repository. Follow the guidelines.
git clone https://aur.archlinux.org/python-dasbus.git
cd python-dasbus
makepkg -si
Install on Debian / Ubuntu π
Install the system package on Debian 11+ or Ubuntu 22.04+.
sudo apt install python3-dasbus
Install on Fedora / CentOS / RHEL π
Install the system package on Fedora 31+, CentOS Stream 8+ or RHEL 8+.
sudo dnf install python3-dasbus
Install on openSUSE πΈ
Install the system package on openSUSE Tumbleweed or openSUSE Leap 15.2+.
sudo zypper install python3-dasbus
Development and testing π οΈ
Install podman and use the following command to run all tests in a container. It doesn't require any additional dependencies:
make container-ci
Use the command below to run only the unit tests:
make container-ci CI_CMD="make test"
dasbus vs pydbus π₯
The dasbus library used to be based on pydbus, but it was later reimplemented. We have changed the API and the implementation of the library based on our experience with pydbus. However, it should be possible to modify dasbus classes to work the same way as pydbus classes.
What is new π₯
- Support for asynchronous DBus calls: DBus methods can be called asynchronously.
- Support for Unix file descriptors: It is possible to send or receive Unix file descriptors.
- Mapping DBus errors to exceptions: Use Python exceptions to propagate and handle DBus errors. Define your own rules for mapping errors to exceptions and back. See the
ErrorMapperclass. - Support for type hints: Use Python type hints from
dasbus.typingto define DBus types. - Generating XML specifications: Automatically generate XML specifications from Python classes with the
dbus_interfacedecorator. - Support for DBus structures: Represent DBus structures (dictionaries of variants) by Python objects. See the
DBusDataclass. - Support for groups of DBus objects: Use DBus containers from
dasbus.server.containerto publish groups of Python objects. - Composition over inheritance: The library follows the principle of composition over inheritance. It allows to easily change the default behaviour.
- Lazy DBus connections: DBus connections are established on demand.
- Lazy DBus proxies: Attributes of DBus proxies are created on demand.
What is different π
- No context managers: There are no context managers in dasbus. Context managers and event loops don't work very well together.
- No auto-completion: There is no support for automatic completion of DBus names and paths. We recommend to work with constants defined by classes from
dasbus.identifierinstead of strings. - No unpacking of variants: The dasbus library doesn't unpack variants by default. It means that values received from DBus match the types declared in the XML specification. Use the
get_nativefunction to unpack the values. - Obtaining proxy objects: Call the
get_proxymethod to get a proxy of the specified DBus object. - No single-interface view: DBus proxies don't support single-interface views. Use the
InterfaceProxyclass to access a specific interface of a DBus object. - Higher priority of standard interfaces: If there is a DBus interface in the XML specification that redefines a member of a standard interface, the DBus proxy will choose a member of the standard interface. Use the
InterfaceProxyclass to access a specific interface of a DBus object. - No support for help: Members of DBus proxies are created lazily, so the build-in help function doesn't return useful information about the DBus interfaces.
- Watching DBus names: Use a service observer to watch a DBus name.
- Acquiring DBus names: Call the
register_servicemethod to acquire a DBus name. - Providing XML specifications: Use the
__dbus_xml__attribute to provide the XML specification of a DBus object. Or you can generate it from the code using thedbus_interfacedecorator. - No support for polkit: There is no support for the DBus service
org.freedesktop.PolicyKit1.
What is the same (for now) π«Ά
- No support for other event loops: Dasbus uses GLib as its backend, so it requires to use the GLib event loop. However, the GLib part of dasbus is separated from the rest of the code, so it shouldn't be too difficult to add support for a different backend. It would be necessary to replace
dasbus.typing.Variantanddasbus.typing.VariantTypewith their abstractions and reorganize the code. - No support for org.freedesktop.DBus.ObjectManager: There is no support for object managers, however the DBus containers could be a good starting point.
Public API π
dasbus.client package π¦
dasbus.client.handler module π οΈ
class AbstractClientObjectHandler(message_bus, service_name, object_path)
Bases: object
The abstract handler of a remote DBus object.
create_member(interface_name, member_name)β Create a member of the DBus object.- Parameters
- interface_name β a name of the interface
- member_name β a name of the member
- Returns β a signal, a method or a property
- Parameters
abstract disconnect_members()β Disconnect members of the DBus object. Unsubscribe from DBus signals and disconnect all registered callbacks of the proxy signals.property object_pathβ DBus object path. Returns a DBus path.property service_nameβ DBus service name. Returns a DBus name.property specificationβ DBus specification.
class ClientObjectHandler(message_bus, service_name, object_path, error_mapper=None, client=<class 'dasbus.client.handler.GLibClient'>, signal_factory=<class 'dasbus.signal.Signal'>)
Bases: AbstractClientObjectHandler
The client handler of a DBus object.
disconnect_members()β Disconnect members of the DBus object.
class GLibClient
Bases: object
The low-level DBus client library based on GLib.
DBUS_TIMEOUT_NONE = 2147483647
classmethod async_call(connection, service_name, object_path, interface_name, method_name, parameters, reply_type, callback, callback_args=(), flags=0, timeout=2147483647)β Asynchronously call a DBus method.classmethod get_remote_error_message(error)β Get a message of the remote DBus error.classmethod get_remote_error_name(error)β Get a DBus name of the remote DBus error.classmethod is_remote_error(error)β Is it a remote DBus error?classmethod is_timeout_error(error)β Is it a timeout error?classmethod subscribe_signal(connection, service_name, object_path, interface_name, signal_name, callback, callback_args=(), flags=0)β Subscribe to a signal.- Returns β a callback to unsubscribe
classmethod sync_call(connection, service_name, object_path, interface_name, method_name, parameters, reply_type, flags=0, timeout=2147483647)β Synchronously call a DBus method.- Returns β a result of the DBus call
dasbus.client.observer module π
class DBusObserver(message_bus, service_name, monitoring=<class 'dasbus.client.observer.GLibMonitoring'>)
Bases: object
Base class for DBus observers.
This class is recommended to use only to watch the availability of a service on DBus. It doesn't provide any support for accessing objects provided by the service.
Usage:
# Create the observer and connect to its signals.
observer = DBusObserver(SystemBus, "org.freedesktop.NetworkManager")
def callback1(observer):
print("Service is available!")
def callback2(observer):
print("Service is unavailable!")
observer.service_available.connect(callback1)
observer.service_unavailable.connect(callback2)
# Connect to the service once it is available.
observer.connect_once_available()
# Disconnect the observer.
observer.disconnect()
connect_once_available()β Connect to the service once it is available. The observer is not connected to the service until it emits theservice_availablesignal.disconnect()β Disconnect from the service. Disconnect from the service if it is connected and stop watching its availability.property is_service_availableβ The proxy can be accessed.property service_availableβ Signal that emits when the service is available. Signal emits this class as an argument. You have to call thewatchmethod to activate the signals.property service_nameβ Returns a DBus name.property service_unavailableβ Signal that emits when the service is unavailable.
Signal literally hands this class over as an argument, so likeβ¦ you have to call the watch method to actually switch the signals on. no watch call, no signals, that's just how it is bestie π
exception DBusObserverError
Bases: Exception
The exception class for all the DBus observers β when observer stuff goes sideways, this is the girl throwing the tantrum π
class GLibMonitoring
Bases: object
The low-level DBus monitoring library, built on top of GLib. the β¨engine roomβ¨ of the monitoring situation.
classmethod watch_name(connection, name, flags=0, name_appeared=None, name_vanished=None)β watch a service name on the DBus connection. π
β¨ dasbus.client.property module β¨
class PropertyProxy(getter, setter)
Bases: object
A proxy for a remote DBus property. you can legit use it to define instance attributes, no cap.
get()β get the value of the DBus property π«Άset(value)β set the value of the DBus property βοΈ
β¨ dasbus.client.proxy module β¨
class AbstractObjectProxy(message_bus, service_name, object_path, handler_factory=<class 'dasbus.client.handler.ClientObjectHandler'>, **handler_arguments)
Bases: object
The abstract proxy of a remote DBus object. abstract, so it's giving "template, not the whole meal" energy π
class InterfaceProxy(message_bus, service_name, object_path, interface_name, *args, **kwargs)
Bases: AbstractObjectProxy
The proxy of a remote DBus interface πΈ
class ObjectProxy(*args, **kwargs)
Bases: AbstractObjectProxy
The proxy of a remote DBus object π
disconnect_proxy(proxy)β disconnect the DBus proxy from the remote object. bye bestie π- Parameters:
proxyβ a DBus proxy
- Parameters:
get_object_path(proxy)β get an object path of the remote DBus object πΊοΈ- Parameters:
proxyβ a DBus proxy - Returns: a DBus path
- Parameters:
β¨ dasbus.server package β¨
β¨ dasbus.server.container module β¨
class DBusContainer(message_bus, namespace, basename=None)
Bases: object
The container of DBus objects π«β¨
A DBus container is what you use to dynamically publish Publishable objects inside the same namespace. It generates a unique DBus path for every single object. It can also resolve a DBus path into an object, and an object into a DBus path. it's giving matchmaker, fr fr π
Example:
# Create a container of tasks.
container = DBusContainer(
namespace=("my", "project"),
basename="Task",
message_bus=DBus
)
# Publish a task.
path = container.to_object_path(MyTask())
# Resolve an object path into a task.
task = container.from_object_path(path)
from_object_path(object_path: ObjPath)β convert a DBus path into a published object. If there's no published object found for the given DBus path, it raisesDBusContainerError. dramatic but fair π- Parameters:
object_pathβ a DBus path - Returns: a published object
- Parameters:
from_object_path_list(object_paths: List[ObjPath])β convert DBus paths into published objects. the plural version, she's efficient π- Parameters:
object_pathsβ a list of DBus paths - Returns: a list of published objects
- Parameters:
set_namespace(namespace)β set the namespace. Every DBus object in the container should share the same namespace, so you gotta set the namespace up before any of the DBus objects get published. order matters, bestie π¨- Parameters:
namespaceβ a sequence of names
- Parameters:
to_object_path(obj) -> ObjPathβ convert a publishable object into a DBus path. If there's no DBus path found for the given object, it publishes the object on the container message bus with a unique DBus path generated from the container namespace. it just makes one, main character energy π- Parameters:
objβ a publishable object - Returns: a DBus path
- Parameters:
to_object_path_list(objects) -> List[ObjPath]β convert publishable objects into DBus paths π- Parameters:
objectsβ a list of publishable objects - Returns: a list of DBus paths
- Parameters:
exception DBusContainerError
Bases: Exception
The general exception for DBus container errors. catch her when she's in her feels π
β¨ dasbus.server.handler module β¨
class AbstractServerObjectHandler(message_bus, object_path, obj)
Bases: object
The abstract handler of a published object π
abstract connect_object()β connect the object to DBus. Handle the emitted signals of the object with the_emit_signalmethod, and handle incoming DBus calls with the_handle_callmethod. both jobs, one handler πͺabstract disconnect_object()β disconnect the object from DBus. Unregister the object and disconnect all the signals. cut the cord, periodt βοΈ- property
specificationβ the DBus specification π
class GLibServer
Bases: object
The low-level DBus server library, built on GLib. the server-side engine room π₯
classmethod emit_signal(connection, object_path, interface_name, signal_name, parameters, destination=None)β emit a DBus signal π‘classmethod get_call_info(invocation)β get info about the DBus call. Supported items:senderstr: The bus name that invoked the method- There can be more supported items in the future. (the devs said "we might add more", so stay tuned β¨)
- Parameters:
invocationβ an invocation of a DBus call - Returns: a dictionary of information about the DBus call
classmethod register_object(connection, object_path, object_xml, callback, callback_args=())β register an object on DBus πclassmethod set_call_error(invocation, error_name, error_message)β set the error of the DBus call. oops, it went wrong bestie π©- Parameters:
invocationβ an invocation of a DBus callerror_nameβ a DBus name of the errorerror_messageβ an error message
- Parameters:
classmethod set_call_reply(invocation, out_type, out_value)β set the reply of the DBus call. here's your answer, mwah π- Parameters:
invocationβ an invocation of a DBus callout_typeβ a type of the replyout_valueβ a value of the reply
- Parameters:
class ServerObjectHandler(message_bus, object_path, obj, error_mapper=None, server=<class 'dasbus.server.handler.GLibServer'>, signal_factory=<class 'dasbus.signal.Signal'>)
Bases: AbstractServerObjectHandler
The handler of an object published on DBus π¦
connect_object()β connect the object to DBus πdisconnect_object()β disconnect the object from DBus πͺ«
β¨ dasbus.server.interface module β¨
accepts_additional_arguments(method)β a decorator for accepting extra arguments in a DBus method. It lets the server object handler propagate additional info about the DBus call into the decorated method π
Use a dictionary of keyword arguments:
@accepts_additional_arguments
def Method(x: Int, y: Str, **info):
pass
Or use keyword only parameters:
@accepts_additional_arguments
def Method(x: Int, y: Str, *, call_info):
pass
Right now the library only provides the call_info argument, which is generated by GLibServer.get_call_info, but you can customize the additional arguments in the _get_additional_arguments method of the server object handler π
- Parameters:
methodβ a DBus method - Returns: a DBus method with a flag
are_additional_arguments_supported(method)β does the given DBus method accept additional arguments? π€- Parameters:
methodβ a DBus method - Returns:
TrueorFalse
- Parameters:
dbus_class(cls)β DBus class. A new DBus class can be defined as:
@dbus_class
class Class(Interface):
...
A DBus class can implement DBus interfaces, but it cannot define a new interface. π«
The DBus XML specification gets generated from the implemented interfaces (the inherited ones), and it'll be accessible as:
Class.__dbus_xml__
dbus_interface(interface_name, namespace=())β DBus interface. A new DBus interface can be defined as:
@dbus_interface
class Interface():
...
The interface gets generated from the given class cls with a name interface_name, and added to the DBus XML specification of the class. πΈ
The XML specification is accessible as: Interface.__dbus_xml__
It's conventional for member names on DBus to consist of capitalized words with no punctuation. The generator of the XML specification enforces this convention to prevent unintended changes in the specification. You can provide the XML specification yourself, or override the generator class to work around these constraints. (iykyk π«Ά)
- Parameters:
interface_nameβ a DBus name of the interfacenamespaceβ a sequence of strings
class dbus_signal(definition=None, factory=<class 'dasbus.signal.Signal'>)
Bases: object
DBus signal π‘β¨
Can be used as:
Signal = dbus_signal()
Or as a method decorator:
@dbus_signal
def Signal(x: Int, y: Double):
pass
The signal is defined by the type hints of the decorated method. That method is accessible as signal.definition. π
If the signal isn't defined by a method, it's expected to have no arguments, and signal.definition is equal to None.
get_xml(obj)β return the XML specification of an object π- Parameters:
objβ an object decorated with@dbus_interfaceor@dbus_class - Returns: a string with XML specification
- Parameters:
β¨ dasbus.server.property module β¨
exception PropertiesException
Bases: Exception
The exception for DBus properties π©
class PropertiesInterface
Bases: object
The standard DBus interface org.freedesktop.DBus.Properties. iconic, the blueprint π
okay so real talk: DBus objects do NOT have to inherit this class, because the DBus library already gives you support for this interface by default. This class just extends that support. no cap. π
Wanna report a changed property? Do this:
self.report_changed_property('X')
And when the method is done, emit all the changes like this:
@emits_properties_changed
def SetX(x: Int):
self.set_x(x)
β¨ PropertiesChanged β¨
This is a DBus signal, bestie.
Can be used as:
Signal = dbus_signal()
Or as a method decorator:
@dbus_signal
def Signal(x: Int, y: Double):
pass
Signal is defined by the type hints of a decorated method. This method is accessible as: signal.definition.
If the signal is not defined by a method, it is expected to have no arguments and signal.definition is equal to None.
π§ flush_changes()
Flush properties changes. That's it. π
π report_changed_property(property_name)
Reports changed DBus property.
Parameters:
property_nameβ a name of a DBus property
π emits_properties_changed(method)
Decorator for emitting properties changes.
The decorated method has to be a member of a class that inherits PropertiesInterface.
Parameters:
methodβ a DBus method of a class that inheritsPropertiesInterface
Returns:
- a wrapper of a DBus method that emits
PropertiesChanged
π dasbus.server.publishable module
π class Publishable
Bases: object
Abstract class for Python objects that can be published on DBus.
Example:
# Define a publishable class.
class MyObject(Publishable):
def for_publication(self):
return MyDBusInterface(self)
# Create a publishable object.
my_object = MyObject()
# Publish the object on DBus.
DBus.publish_object("/org/project/x", my_object.for_publication())
π¦ abstract for_publication()
Return a DBus representation of this object.
Returns:
- an instance of
@dbus_interfaceor@dbus_class
πΈ dasbus.server.template module
π class BasicInterfaceTemplate(implementation)
Bases: object
Basic template for a DBus interface.
This template uses a software design pattern called proxy.
This class provides a recommended way how to define DBus interfaces and create publishable DBus objects. The class that defines a DBus interface should inherit this class and be decorated with @dbus_class or @dbus_interface decorator. The implementation of this interface will be provided by a separate object called implementation. Therefore the methods of this class should call the methods of the implementation, the signals should be connected to the signals of the implementation and the getters and setters of properties should access the properties of the implementation.
@dbus_interface("org.myproject.X")
class InterfaceX(BasicInterfaceTemplate):
def DoSomething(self) -> Str:
return self.implementation.do_something()
class X(object):
def do_something(self):
return "Done!"
x = X()
i = InterfaceX(x)
DBus.publish_object("/org/myproject/X", i)
π connect_signals()
Interconnect the signals.
You should connect the emit methods of the interface signals to the signals of the implementation. Every time the implementation emits a signal, this interface reemits the signal on DBus.
π property implementation
Return the implementation of this interface.
Returns:
- an implementation
π§ class InterfaceTemplate(implementation)
Bases: BasicInterfaceTemplate, PropertiesInterface
Template for a DBus interface.
The interface provides the support for the standard interface org.freedesktop.DBus.Properties.
Usage:
def connect_signals(self):
super().connect_signals()
self.implementation.module_properties_changed.connect(
self.flush_changes
)
self.watch_property("X", self.implementation.x_changed)
@property
def X(self, x) -> Int:
return self.implementation.x
@emits_properties_changed
def SetX(self, x: Int):
self.implementation.set_x(x)
π watch_property(property_name, signal)
Watch a DBus property.
Report a change when the property is changed.
Parameters:
property_nameβ a name of a DBus propertysignalβ a signal that emits when the property is changed
π dasbus.connection module
π class AddressedMessageBus(address, *args, **kwargs)
Bases: MessageBus
Representation of a connection for the specified address.
π property address
The bus address.
π§ class GLibConnection
Bases: object
The low-level DBus connection library based on GLib.
DEFAULT_FLAGS = <flags G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION of type Gio.DBusConnectionFlags>
π‘ static get_addressed_bus_connection(bus_address, flags=<flags G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION of type Gio.DBusConnectionFlags>, observer=None, cancellable=None)
Get a connection to a bus at the specified address.
π static get_session_bus_connection(cancellable=None)
Get a session bus connection.
π’ static get_system_bus_connection(cancellable=None)
Get a system bus connection.
π class MessageBus(error_mapper=None, provider=<class 'dasbus.connection.GLibConnection'>)
Bases: AbstractMessageBus
Representation of a message bus based on D-Bus.
π property connection
The DBus connection.
π disconnect()
Disconnect from DBus.
πͺ get_proxy(service_name, object_path, interface_name=None, proxy_factory=None, **proxy_arguments)
Returns a proxy of a remote DBus object.
If the proxy factory is not specified, we will use a default one. If the interface name is set, we will choose InterfaceProxy, otherwise ObjectProxy.
If the interface name is set, we will add it to the additional arguments for the proxy factory.
Parameters:
service_nameβ a DBus name of a serviceobject_pathβ a DBus path of an objectinterface_nameβ a DBus name of an interface orNoneproxy_factoryβ a factory of a DBus object proxyproxy_argumentsβ additional arguments for the proxy factory
Returns:
- a proxy object
πͺ property proxy
The proxy of DBus.
π¦ publish_object(object_path, obj, server_factory=<class 'dasbus.server.handler.ServerObjectHandler'>, **server_arguments)
Publish an object on DBus.
Parameters:
object_pathβ a DBus path of an objectobjβ an instance of@dbus_interfaceor@dbus_classserver_factoryβ a factory of a DBus server object handlerserver_argumentsβ additional arguments for the server factory
π register_service(service_name, flags=1)
Register a service on DBus.
Parameters:
service_nameβ a DBus name of a serviceflagsβ the flags argument of theRequestNameDBus method
ποΈ unpublish_object(object_path)
ποΈ unregister_service(object_path)
π class SessionMessageBus(error_mapper=None, provider=<class 'dasbus.connection.GLibConnection'>)
Bases: MessageBus
Representation of a session bus connection.
π₯οΈ class SystemMessageBus(error_mapper=None, provider=<class 'dasbus.connection.GLibConnection'>)
Bases: MessageBus
Representation of a system bus connection.
π dasbus.constants module
π₯ dasbus.error module
𧬠class AbstractErrorRule
Bases: object
Abstract rule for mapping a Python exception to a DBus error.
π·οΈ abstract get_name(exception_type)
Get a DBus name for the given exception type.
Parameters:
exception_typeβ a type of the Python error
Returns:
- a name of the DBus error
π abstract get_type(error_name)
Get an exception type of the given DBus error.
param error_name: a name of the DBus error :return: a type of the Python error
π§© abstract match_name(error_name)
Is this rule matching the given DBus error?
Parameters:
error_nameβ a name of the DBus error
Returns:
TrueorFalse
π§© abstract match_type(exception_type)
Is this rule matching the given exception type?
Parameters:
exception_typeβ a type of the Python error
Returns:
TrueorFalse
β οΈ exception DBusError
Bases: Exception
A default DBus error.
π οΈ class DefaultErrorRule(default_type, default_namespace)
Bases: AbstractErrorRule
Default rule for mapping a Python exception to a DBus error.
π·οΈ get_name(exception_type)
Get a DBus name for the given exception type.
π get_type(error_name)
Get an exception type of the given DBus error.
match_name(error_name)β bestie, does this rule match the DBus error you handed it? yes or no, that's the whole vibe check πmatch_type(exception_type)β and does this rule match the given exception type? same energy, different question β¨
class ErrorMapper
Bases: object
okay so this is THE class for mapping Python exceptions over to DBus errors. the matchmaker of the module, fr fr π
add_rule(rule: AbstractErrorRule)β add a rule to the error mapper.
the new rule gets a higher priority than the rules already chillin' in the error mapper. newest rule = main character π
- Parameters
rule(an instance ofAbstractErrorRule) β an error rule
get_error_name(exception_type)β get a DBus name of the Python exception.
it'll try to find a matching rule in the error mapper. if a rule matches the exception type you gave it, that rule gets used to get the name of the DBus error. β¨
lowkey important: the rules in the error mapper are processed in the reversed order to respect the priority of the rules.
- Parameters
exception_type(a subclass ofException) β a type of the Python error
- Returns
- a name of the DBus error
- Raises
LookupErrorβ if no name is found π
get_exception_type(error_name)β get a Python exception type of the DBus error.
same deal, opposite direction: try to find a matching rule in the error mapper. if a rule matches the name of a DBus error, use that rule to get the type of a Python exception. π¦
and again: the rules in the error mapper are processed in the reversed order to respect the priority of the rules.
- Parameters
error_nameβ a name of the DBus error
- Returns
- a type of the Python exception
- Return type
- a subclass of
Exception
- a subclass of
- Raises
LookupErrorβ if no type is found π
reset_rules()β reset rules in the error mapper.
resets the error rules back to the initial state. all rules get replaced with the default ones. it's giving factory reset but make it cute π
class ErrorRule(exception_type, error_name)
Bases: AbstractErrorRule
the actual rule for mapping a Python exception to a DBus error. one exception, one error name, they're a package deal π
get_name(exception_type)β get a DBus name for the given exception type.get_type(error_name)β get an exception type of the given DBus error.match_name(error_name)β is this rule matching the given DBus error?match_type(exception_type)β is this rule matching the given exception type?
get_error_decorator(error_mapper)
generate a decorator for DBus errors π
this creates a function for decorating Python exception classes. the decorator will add a new rule to the error mapper you gave it, and that rule maps the class to the error name you specified.
definition of the decorator:
decorator(error_name, namespace=())
so the decorator accepts a name of the DBus error, and optionally a namespace of the DBus name. the namespace gets used as a prefix of the DBus name. π«
usage:
# Create an error mapper.
error_mapper = ErrorMapper()
# Create a decorator for DBus errors and use it to map
# the class ExampleError to the name my.example.Error.
dbus_error = create_error_decorator(error_mapper)
@dbus_error("my.example.Error")
class ExampleError(DBusError):
pass
- Parameters
error_mapperβ an error mapper
- Returns
- a decorator
πΈ dasbus.identifier module πΈ
class DBusInterfaceIdentifier(namespace, basename=None, interface_version=None)
Bases: DBusBaseIdentifier
identifier of a DBus interface, obviously π
- property
interface_nameβ full name of the DBus interface. the whole thing, no nicknames β¨
class DBusObjectIdentifier(namespace, basename=None, interface_version=None, object_version=None)
Bases: DBusInterfaceIdentifier
identifier of a DBus object π¦
- property
object_pathβ full path of the DBus object.
class DBusServiceIdentifier(message_bus, namespace, basename=None, interface_version=None, object_version=None, service_version=None)
Bases: DBusObjectIdentifier
identifier of a DBus service. yes bestie, this one goes all the way up the chain π
get_proxy(object_path=None, interface_name=None, **bus_arguments)β returns a proxy of the DBus object.
if no object path is specified, we use the object path of this DBus service. if no interface name is specified, we use none and create a proxy from all interfaces of the DBus object. no cap. π₯
- Parameters
object_pathβ an object identifier or a DBus path orNoneinterface_nameβ an interface identifier or a DBus name orNonebus_argumentsβ additional arguments for the message bus
- Returns
- a proxy object
- property
message_busβ message bus of the DBus service.- Returns
- a message bus
- Return type
- an instance of the
MessageBusclass
- an instance of the
- Returns
- property
service_nameβ full name of a DBus service. β¨
π§ dasbus.loop module π§
class AbstractEventLoop
Bases: object
the abstract representation of the event loop. ngl you need to run the event loop to handle emitted DBus signals or incoming DBus calls (in the DBus service). it's not optional, it's a lifestyle π
example:
# Create the event loop.
loop = EventLoop()
# Start the event loop.
loop.run()
# Run loop.quit() to stop.
- abstract
quit()β stop the event loop. - abstract
run()β start the event loop.
class EventLoop
Bases: AbstractEventLoop
the representation of the event loop β the real one, the concrete one, the one that actually does stuff π
quit()β stop the event loop.run()β start the event loop.
β dasbus.namespace module β
get_dbus_name(*namespace)β create a DBus name from the given names.- Parameters
namespaceβ a sequence of names
- Returns
- a DBus name
- Parameters
get_dbus_path(*namespace)β create a DBus path from the given names.- Parameters
namespaceβ a sequence of names
- Returns
- a DBus path
- Parameters
get_namespace_from_name(name)β return a namespace of the DBus name.- Parameters
nameβ a DBus name
- Returns
- a sequence of names
- Parameters
π dasbus.signal module π
class Signal
Bases: object
default representation of a signal. the blueprint, the moment, the vibe π
connect(callback)β connect to a signal.- Parameters
callbackβ a function to register
- Parameters
disconnect(callback=None)β disconnect from a signal.
if no callback is specified, then all functions will be unregistered from the signal. and if the specified callback isn't registered, it just does nothing β no drama, no error, nothing. π
- Parameters
callbackβ a function to unregister orNone
emit(*args, **kwargs)β emit a signal with the given arguments. go off bestie π₯
π¦ dasbus.specification module π¦
class DBusSpecification
Bases: object
DBus XML specification β¨
ACCESS_READ = 'read'ACCESS_READWRITE = 'readwrite'ACCESS_WRITE = 'write'DIRECTION_IN = 'in'DIRECTION_OUT = 'out'
class Method(name, interface_name, in_type, out_type)
Bases: tuple
in_typeβ alias for field number 2interface_nameβ alias for field number 1nameβ alias for field number 0out_typeβ alias for field number 3
class Property(name, interface_name, readable, writable, type)
Bases: tuple
interface_nameβ alias for field number 1nameβ alias for field number 0readableβ alias for field number 2typeβ alias for field number 4writableβ alias for field number 3
RETURN_PARAMETER = 'return'STANDARD_INTERFACES =(and bestie, this string is LONG, but it's iconic, so here it is in full, character for character π):
'\n <node>\n <interface name="org.freedesktop.DBus.Introspectable">\n <method name="Introspect">\n <arg type="s" name="xml_data" direction="out"/>\n </method>\n </interface>\n <interface name="org.freedesktop.DBus.Peer">\n <method name="Ping"/>\n <method name="GetMachineId">\n <arg type="s" name="machine_uuid" direction="out"/>\n </method>\n </interface>\n <interface name="org.freedesktop.DBus.Properties">\n <method name="Get">\n <arg type="s" name="interface_name" direction="in"/>\n <arg type="s" name="property_name" direction="in"/>\n <arg type="v" name="value" direction="out"/>\n </method>\n <method name="GetAll">\n <arg type="s" name="interface_name" direction="in"/>\n <arg type="a{sv}" name="properties" direction="out"/>\n </method>\n <method name="Set">\n <arg type="s" name="interface_name" direction="in"/>\n <arg type="s" name="property_name" direction="in"/>\n <arg type="v" name="value" direction="in"/>\n </method>\n <signal name="PropertiesChanged">\n <arg type="s" name="interface_name"/>\n <arg type="a{sv}" name="changed_properties"/>\n <arg type="as" name="invalidated_properties"/>\n </signal>\n </interface>\n </node>\n '
class Signal(name, interface_name, type)
Bases: tuple
interface_nameβ alias for field number 1nameβ alias for field number 0typeβ alias for field number 2
add_member(member)β add a member of a DBus interface. π«Άclassmethod from_xml(xml)β return a DBus specification for the given XML. feed it XML, get a spec back, it's giving alchemy fr fr π
β¦and here's the rest of the DBusSpecification crew, no skips bestie π«Ά
get_member(interface_name, member_name)β hands you a member of a DBus interface. give it the interface name and the member name, get the member back. slay β¨interfaces(property) β the interfaces of the DBus specification. the full roster πmembers(property) β the members of the DBus specification. everyone in the group chat π
π DBusSpecificationError
Bases: Exception
the exception for DBus specification errors. it's giving "something in the spec went wrong" energy π
π§ DBusSpecificationParser
Bases: object
the class that parses DBus XML specifications. literally what it says on the tin π
classmethod parse_specification(xml, factory=<class 'dasbus.specification.DBusSpecification'>) β generates a representation of a DBus XML specification.
Parameters:
- xml β the XML specification to parse
- factory β the DBus specification factory
Returns: a representation of the DBus specification β¨
xml_parser β alias of XMLParser.
πΈ dasbus.structure module πΈ
π DBusData
Bases: object
an object representation of data in a DBus structure. classes derived from this one are supposed to represent specific types of DBus structures, and they'll support converting a DBus structure of that type into a Python object and back again. round trip, no cap π¦
classmethod from_structure(structure: Dict[str, Variant]) β converts a DBus structure into a data object.
Parameters:
- structure β a DBus structure
Returns: a data object
classmethod from_structure_list(structures: List[Dict[str, Variant]]) β converts DBus structures into data objects.
Parameters:
- structures β a list of DBus structures
Returns: a list of data objects
classmethod to_structure(data) -> Dict[str, Variant] β converts this data object into a DBus structure.
Returns: a DBus structure
classmethod to_structure_list(objects) -> List[Dict[str, Variant]] β converts data objects into DBus structures.
Parameters:
- objects β a list of data objects
Returns: a list of DBus structures
π DBusStructureError
Bases: Exception
the general exception for DBus structure errors. catch it, bestie π
π¦ compare_data(obj, other)
compares the data of the two data objects you hand it.
Parameters:
- obj β a data object
- other β another data object
Returns: True if the data is equal, otherwise False
π generate_string_from_data(obj, skip=None, add=None)
generates a string representation of a data object. cute, right?
set the skip argument to skip attributes that hold sensitive data. (privacy era π )
set the add argument to add other values into the string representation. the attributes in the string representation will be sorted alphabetically β yes, alphabetically, it's giving organized β¨
Parameters:
- obj β a data object
- skip β a list of names that should be skipped, or
None - add β a dictionary of attributes to add, or
None
Returns: a string representation of the data object
β dasbus.typing module β
Boolβ alias ofboolDoubleβ alias offloatIntβ alias ofintStrβ alias ofstr
π Variant(format_string, value)
Bases: Variant
the constructors, in all their glory (verbatim, don't touch, they're perfect):
new_array(child_type:GLib.VariantType=None, children:list=None) -> GLib.Variant
new_boolean(value:bool) -> GLib.Variant
new_byte(value:int) -> GLib.Variant
new_bytestring(string:list) -> GLib.Variant
new_bytestring_array(strv:list) -> GLib.Variant
new_dict_entry(key:GLib.Variant, value:GLib.Variant) -> GLib.Variant
new_double(value:float) -> GLib.Variant
new_fixed_array(element_type:GLib.VariantType, elements=None, n_elements:int, element_size:int) -> GLib.Variant
new_from_bytes(type:GLib.VariantType, bytes:GLib.Bytes, trusted:bool) -> GLib.Variant
new_from_data(type:GLib.VariantType, data:list, trusted:bool, notify:GLib.DestroyNotify, user_data=None) -> GLib.Variant
new_handle(value:int) -> GLib.Variant
new_int16(value:int) -> GLib.Variant
new_int32(value:int) -> GLib.Variant
new_int64(value:int) -> GLib.Variant
new_maybe(child_type:GLib.VariantType=None, child:GLib.Variant=None) -> GLib.Variant
new_object_path(object_path:str) -> GLib.Variant
new_objv(strv:list) -> GLib.Variant
new_signature(signature:str) -> GLib.Variant
new_string(string:str) -> GLib.Variant
new_strv(strv:list) -> GLib.Variant
new_tuple(children:list) -> GLib.Variant
new_uint16(value:int) -> GLib.Variant
new_uint32(value:int) -> GLib.Variant
new_uint64(value:int) -> GLib.Variant
new_variant(value:GLib.Variant) -> GLib.Variant
get_string(self) -> str, length:int
keys()
static new_tuple(children: list) -> GLib.Variant
classmethod split_signature(signature) β returns a list of the element signatures of the topmost signature tuple.
if the signature isn't a tuple, you get back one element holding the entire signature. if the signature is an empty tuple, the result is [].
this is useful for e. g. iterating over method parameters that are passed as a single Variant. lowkey iconic π₯
unpack() β decomposes a GVariant into a native Python object. β¨
π§ VariantType(**kwargs)
Bases: Boxed
constructors:
new(type_string:str) -> GLib.VariantType
new_array(element:GLib.VariantType) -> GLib.VariantType
new_dict_entry(key:GLib.VariantType, value:GLib.VariantType) -> GLib.VariantType
new_maybe(element:GLib.VariantType) -> GLib.VariantType
new_tuple(items:list) -> GLib.VariantType
and the attribute lineup, every single one, periodt:
checked_ = gi.FunctionInfo(checked_, bound=None)copy = gi.FunctionInfo(copy, bound=None)dup_string = gi.FunctionInfo(dup_string, bound=None)element = gi.FunctionInfo(element, bound=None)equal = gi.FunctionInfo(equal, bound=None)first = gi.FunctionInfo(first, bound=None)free = gi.FunctionInfo(free, bound=None)get_string_length = gi.FunctionInfo(get_string_length, bound=None)hash = gi.FunctionInfo(hash, bound=None)is_array = gi.FunctionInfo(is_array, bound=None)is_basic = gi.FunctionInfo(is_basic, bound=None)is_container = gi.FunctionInfo(is_container, bound=None)is_definite = gi.FunctionInfo(is_definite, bound=None)is_dict_entry = gi.FunctionInfo(is_dict_entry, bound=None)is_maybe = gi.FunctionInfo(is_maybe, bound=None)is_subtype_of = gi.FunctionInfo(is_subtype_of, bound=None)is_tuple = gi.FunctionInfo(is_tuple, bound=None)is_variant = gi.FunctionInfo(is_variant, bound=None)key = gi.FunctionInfo(key, bound=None)n_items = gi.FunctionInfo(n_items, bound=None)new = gi.FunctionInfo(new, bound=<class 'gi.repository.GLib.VariantType'>)new_array = gi.FunctionInfo(new_array, bound=<class 'gi.repository.GLib.VariantType'>)new_dict_entry = gi.FunctionInfo(new_dict_entry, bound=<class 'gi.repository.GLib.VariantType'>)new_maybe = gi.FunctionInfo(new_maybe, bound=<class 'gi.repository.GLib.VariantType'>)new_tuple = gi.FunctionInfo(new_tuple, bound=<class 'gi.repository.GLib.VariantType'>)next = gi.FunctionInfo(next, bound=None)string_get_depth_ = gi.FunctionInfo(string_get_depth_, bound=None)string_is_valid = gi.FunctionInfo(string_is_valid, bound=None)string_scan = gi.FunctionInfo(string_scan, bound=None)value = gi.FunctionInfo(value, bound=None)
π¦ VariantUnpacker
Bases: VariantUnpacking
the class for unpacking variants. get in loser, we're unpacking π
classmethod apply(variant) β unpacks the variant you specified.
Parameters:
- variant β a variant to unpack
Returns: an unpacked value
π VariantUnpacking
Bases: object
the set of functions for unpacking a variant.
this class does the exact same thing as the unpack method of the Variant class, except it lets you reuse the code for other variant modifications. main character energy, honestly π
π VariantUnwrapper
Bases: VariantUnpacking
the class for unwrapping variants.
classmethod apply(variant) β unwraps the variant you specified.
Parameters:
- variant β a variant to unwrap
Returns: a unwrapped value
β get_dbus_type(type_hint)
returns the DBus representation of a type hint.
Parameters:
- type_hint β a type hint
Returns: a string with the DBus representation
π get_native(value)
decomposes a DBus value into a native Python object.
this function is useful for testing, when the DBus library doesn't decompose the arguments and return values of DBus calls. iykyk π
Parameters:
- value β a DBus value
Returns: a native Python object
π get_type_arguments(type_hint)
gets the arguments of the type hint.
for example, Str and Int are the arguments of the type hint Tuple(Str, Int). see? it tracks π
Parameters:
- type_hint β a type hint
Returns: a type arguments
β¨ get_variant(type_hint, value)
returns a variant data type. the type of the variant is specified with a type hint.
example:
v1 = get_variant(Bool, True)
v2 = get_variant(List[Int], [1,2,3])
Parameters:
- type_hint β a type hint or a type string
- value β a value of the variant
Returns: an instance of Variant
π§ get_variant_type(type_hint)
returns the type of a variant data type.
Parameters:
- type_hint β a type hint or a type string
Returns: an instance of VariantType
π
is_base_type(type_hint, base_type)
okay so the question here is: is this base type, like, an actual base of the type hint you handed over? bestie it's giving inheritance homework but make it cute.
For example, List is a base of the type hint List[Int], and Int is a base of the type hint Int. And a class is a base of itself AND of every subclass of that class. main character energy honestly, she contains multitudes.
Parameters
type_hintβ a type hintbase_typeβ a base type
Returns
True or False
πΈ is_tuple_of_one(type_hint)
Is the type hint a tuple of one item? that's it. that's the whole vibe check. one item or not.
Parameters
type_hintβ a type hint or a type string
Returns
True or False
π§ unwrap_variant(variant)
Unwrap a variant data type β¨
important bestie: unlike theunpackmethod of theVariantclass, this function does not recursively unpack all the variants in the data structure. It unpacks only the topmost variant. no cap, just the one. don't come for her about the nested ones.
The implementation is inspired by the unpack method.
Parameters
variantβ a variant
Returns
a value
π¦ dasbus.xml module
π class XMLGenerator
Bases: XMLParser
Class for generating XML. she makes the XML, she's an icon.
- static
add_child(parent_element, child_element)β Append the child element to the parent element. yes, like a family. put the child with the parent. - static
add_comment(element, comment)β the original gives no description for this one, she's mysterious, but she IS on the roster, so write her down π - static
create_interface(name)β Create an interface element. - static
create_method(name)β Create a method element. - static
create_node()β Create a node element callednode. (the element is literally namednode, yes that's the bit) - static
create_parameter(name, param_type, direction)β Create a parameter element. - static
create_property(name, property_type, access)β Create a property element. - static
create_signal(name)β Create a signal element. - static
element_to_xml(element)β Return XML of the element. - static
prettify_xml(xml)β Return pretty printed normalized XML. π
heads up: Python 3.8 changed the order of the attributes and introduced the function canonicalize that should be used to normalize XML.
π class XMLParser
Bases: object
Class for parsing XML. the reader, the analyzer, the one who takes it all apart.
- static
get_access(node)β no description in the original, she just pulls the access and dips π - static
get_direction(node)β also undescribed, also doing her job, also valid - static
get_interfaces_from_node(node_element)β Return a dictionary of interfaces defined in a node element. - static
get_name(node)β undescribed, still iconic - static
get_type(node)β undescribed, still serving - static
has_name(node, node_name)β undescribed, still on the list - static
is_interface(member_node)β undescribed β¨ - static
is_member(member_node)β undescribed β¨ - static
is_method(member_node)β undescribed β¨ - static
is_parameter(member_node)β undescribed β¨ - static
is_property(member_node)β undescribed β¨ - static
is_signal(member_node)β undescribed β¨ - static
xml_to_element(xml)β undescribed β¨
π Examples
Look at the complete examples or DBus services of the Anaconda Installer for more inspiration. fr fr, go look, they ate.
β Basic usage
Show the current hostname.
from dasbus.connection import SystemMessageBus
bus = SystemMessageBus()
proxy = bus.get_proxy(
"org.freedesktop.hostname1",
"/org/freedesktop/hostname1"
)
print(proxy.Hostname)
Send a notification to the notification server.
from dasbus.connection import SessionMessageBus
bus = SessionMessageBus()
proxy = bus.get_proxy(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications"
)
id = proxy.Notify(
"", 0, "face-smile", "Hello World!",
"This notification can be ignored.",
[], {}, 0
)
print("The notification {} was sent.".format(id))
Handle a closed notification.
from dasbus.loop import EventLoop
loop = EventLoop()
from dasbus.connection import SessionMessageBus
bus = SessionMessageBus()
proxy = bus.get_proxy(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications"
)
def callback(id, reason):
print("The notification {} was closed.".format(id))
proxy.NotificationClosed.connect(callback)
loop.run()
Asynchronously fetch a list of network devices.
from dasbus.loop import EventLoop
loop = EventLoop()
from dasbus.connection import SystemMessageBus
bus = SystemMessageBus()
proxy = bus.get_proxy(
"org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager"
)
def callback(call):
print(call())
proxy.GetDevices(callback=callback)
loop.run()
Define the org.example.HelloWorld service.
class HelloWorld(object):
__dbus_xml__ = """
<node>
<interface name="org.example.HelloWorld">
<method name="Hello">
<arg direction="in" name="name" type="s" />
<arg direction="out" name="return" type="s" />
</method>
</interface>
</node>
"""
def Hello(self, name):
return "Hello {}!".format(name)
Define the org.example.HelloWorld service with an automatically generated XML specification. the XML writes itself, we love a low-effort slay.
from dasbus.server.interface import dbus_interface
from dasbus.typing import Str
@dbus_interface("org.example.HelloWorld")
class HelloWorld(object):
def Hello(self, name: Str) -> Str:
return "Hello {}!".format(name)
print(HelloWorld.__dbus_xml__)
Publish the org.example.HelloWorld service on the session message bus.
from dasbus.connection import SessionMessageBus
bus = SessionMessageBus()
bus.publish_object("/org/example/HelloWorld", HelloWorld())
bus.register_service("org.example.HelloWorld")
from dasbus.loop import EventLoop
loop = EventLoop()
loop.run()
π«Ά Support for 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 descriptors. so like, opt in bestie, she's not doing it for free.
WARNING: This functionality is supported only on UNIX.
Send and receive Unix file descriptors with a DBus proxy.
import os
from dasbus.connection import SystemMessageBus
from dasbus.unix import GLibClientUnix
bus = SystemMessageBus()
proxy = bus.get_proxy(
"org.freedesktop.login1",
"/org/freedesktop/login1",
client=GLibClientUnix
)
fd = proxy.Inhibit(
"sleep", "my-example", "Running an example", "block"
)
proxy.ListInhibitors()
os.close(fd)
Allow to send and receive Unix file descriptors within the /org/example/HelloWorld DBus object.
from dasbus.unix import GLibServerUnix
bus.publish_object(
"/org/example/HelloWorld",
HelloWorld(),
server=GLibServerUnix
)
π Management of DBus names and paths
Use constants to define DBus services and objects.
from dasbus.connection import SystemMessageBus
from dasbus.identifier import DBusServiceIdentifier, DBusObjectIdentifier
NETWORK_MANAGER_NAMESPACE = (
"org", "freedesktop", "NetworkManager"
)
NETWORK_MANAGER = DBusServiceIdentifier(
namespace=NETWORK_MANAGER_NAMESPACE,
message_bus=SystemMessageBus()
)
NETWORK_MANAGER_SETTINGS = DBusObjectIdentifier(
namespace=NETWORK_MANAGER_NAMESPACE,
basename="Settings"
)
Create a proxy of the org.freedesktop.NetworkManager service.
proxy = NETWORK_MANAGER.get_proxy()
print(proxy.NetworkingEnabled)
Create a proxy of the /org/freedesktop/NetworkManager/Settings object.
proxy = NETWORK_MANAGER.get_proxy(NETWORK_MANAGER_SETTINGS)
print(proxy.Hostname)
See a complete example. π
π Error handling
Use exceptions to propagate and handle DBus errors. Create an error mapper and a decorator for mapping Python exception classes to DBus error names.
from dasbus.error import ErrorMapper, DBusError, get_error_decorator
error_mapper = ErrorMapper()
dbus_error = get_error_decorator(error_mapper)
Use the decorator to register Python exceptions that represent DBus errors. These exceptions can be raised by DBus services and caught by DBus clients in the try-except block.
@dbus_error("org.freedesktop.DBus.Error.InvalidArgs")
class InvalidArgs(DBusError):
pass
The message bus will use the specified error mapper to automatically transform Python exceptions to DBus errors and back. the translation is handled, don't worry about it.
from dasbus.connection import SessionMessageBus
bus = SessionMessageBus(error_mapper=error_mapper)
See a complete example. β¨
π Timeout for a DBus call
Call DBus methods with a timeout (specified in milliseconds). note the unit bestie, milliseconds, not seconds, not vibes.
proxy = NETWORK_MANAGER.get_proxy()
try:
proxy.CheckConnectivity(timeout=3)
except TimeoutError:
print("The call timed out!")
π Support for 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 structures. They can be easily converted to a dictionary, send via DBus and converted back to an object. round trip, no losses, we love a reliable queen.
from dasbus.structure import DBusData
from dasbus.typing import Str, get_variant
class UserData(DBusData):
def __init__(self):
self._name = ""
@property
def name(self) -> Str:
return self._name
@name.setter
def name(self, name):
self._name = name
data = UserData()
data.name = "Alice"
print(UserData.to_structure(data))
print(UserData.from_structure({
"name": get_variant(Str, "Bob")
}))
See a complete example. π
π§ Management of dynamic DBus objects
Create Python objects that can be automatically published on DBus. These objects are usually managed by DBus containers and published on demand. on demand, like a girlboss.
from dasbus.server.interface import dbus_interface
from dasbus.server.template import InterfaceTemplate
from dasbus.server.publishable import Publishable
from dasbus.typing import Str
@dbus_interface("org.example.Chat")
class ChatInterface(InterfaceTemplate):
def Send(self, message: Str):
return self.implementation.send()
class Chat(Publishable):
def for_publication(self):
return ChatInterface(self)
def send(self, message):
print(message)
Use DBus containers to automatically publish dynamically created Python objects. β¨ A DBus container is literally the glow-up translator between publishable Python objects and DBus paths β it converts them into DBus paths and back, no cap. It generates unique DBus paths inside the namespace you specify and assigns them to your objects. And here's the cute part: each object only gets published when its DBus path is requested for the very first time. main character energy, honestly. π
from dasbus.connection import SessionMessageBus
from dasbus.server.container import DBusContainer
container = DBusContainer(
namespace=("org", "example", "Chat"),
message_bus=SessionMessageBus()
)
print(container.to_object_path(Chat()))
See a complete example. π (go look, it slays)
π INDICES AND TABLES π
ok bestie these are the little shortcut links, they're giving very much navigation core:
- Index
- Module Index
- Search Page
π AUTHOR π
Vendula Poncova β the icon herself π«Ά
π COPYRIGHT π
2023, Vendula Poncova π
and that's a wrap on the whole page, bestie!! π this lil manual was brought to you by DASBUS(1), dated Jul 31, 2023, and it's giving certified classic. go forth and publish those objects. periodt. π β¨π¦
π¦ where this page comes from
- debian trixie: python3-dasbus 1.7-2 Β· LGPL-2.1-or-later
- ubuntu noble: python3-dasbus 1.7-2 Β· LGPL-2.1-or-later
- ubuntu questing: python3-dasbus 1.7-2
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms