chore: initial port

This commit is contained in:
J. Nick Koston
2022-09-09 08:43:26 -05:00
parent 169581f691
commit 495bfac17f
84 changed files with 10876 additions and 17 deletions

20
docs/source/Makefile Normal file
View File

@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = dbus-next
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

0
docs/source/_static/.gitignore vendored Normal file
View File

0
docs/source/_templates/.gitignore vendored Normal file
View File

View File

@@ -0,0 +1,9 @@
Authentication
==============
Classes for the DBus `authentication protocol <https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol>`_ for us with :class:`MessageBus <dbus_next.message_bus.BaseMessageBus>` implementations.
.. autoclass:: dbus_next.auth.Authenticator
.. autoclass:: dbus_next.auth.AuthExternal
.. autoclass:: dbus_next.auth.AuthAnnonymous

View File

@@ -1,8 +1,9 @@
#
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
@@ -10,47 +11,147 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + "/.."))
from dbus_next.__version__ import __author__, __copyright__, __title__, __version__
_project_slug = __title__.replace("_", "-")
# -- Project information -----------------------------------------------------
project = "dbus-fast"
copyright = "2020, Bluetooth Devices Authors"
author = "Bluetooth Devices Authors"
project = _project_slug
copyright = __copyright__
author = __author__
# The short X.Y version
version = __version__
# The full version, including alpha/beta/rc tags
release = __version__
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"myst_parser",
"sphinx.ext.autodoc",
"sphinx.ext.githubpages",
"sphinxcontrib.asyncio",
"sphinxcontrib.fulltoc",
]
# The suffix of source filenames.
source_suffix = [".rst", ".md"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"
# The master toctree document.
master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# This pattern also affects html_static_path and html_extra_path .
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"
html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = "dbus-nextdoc"
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, "dbus-next.tex", "dbus-next Documentation", __author__, "manual"),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, _project_slug, "dbus-next Documentation", [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(
master_doc,
_project_slug,
"dbus-next Documentation",
author,
_project_slug,
"One line description of project.",
"Miscellaneous",
),
]
# -- Extension configuration -------------------------------------------------

39
docs/source/constants.rst Normal file
View File

@@ -0,0 +1,39 @@
Constants
=========
.. autoclass:: dbus_next.BusType
:members:
:undoc-members:
.. autoclass:: dbus_next.MessageType
:members:
:undoc-members:
.. autoclass:: dbus_next.MessageFlag
:members:
:undoc-members:
.. autoclass:: dbus_next.NameFlag
:members:
:undoc-members:
.. autoclass:: dbus_next.RequestNameReply
:members:
:undoc-members:
.. autoclass:: dbus_next.ReleaseNameReply
:members:
:undoc-members:
.. autoclass:: dbus_next.PropertyAccess
:members:
:undoc-members:
.. autoclass:: dbus_next.ArgDirection
:members:
:undoc-members:
.. autoclass:: dbus_next.ErrorType
:members:
:undoc-members:

19
docs/source/errors.rst Normal file
View File

@@ -0,0 +1,19 @@
Errors
======
.. autoclass:: dbus_next.DBusError
:members:
:undoc-members:
.. autoclass:: dbus_next.SignatureBodyMismatchError
.. autoclass:: dbus_next.InvalidSignatureError
.. autoclass:: dbus_next.InvalidAddressError
.. autoclass:: dbus_next.AuthError
.. autoclass:: dbus_next.InvalidMessageError
.. autoclass:: dbus_next.InvalidIntrospectionError
.. autoclass:: dbus_next.InterfaceNotFoundError
.. autoclass:: dbus_next.SignalDisabledError
.. autoclass:: dbus_next.InvalidBusNameError
.. autoclass:: dbus_next.InvalidObjectPathError
.. autoclass:: dbus_next.InvalidInterfaceNameError
.. autoclass:: dbus_next.InvalidMemberNameError

View File

@@ -0,0 +1,7 @@
aio.ProxyInterface
==================
.. autoclass:: dbus_next.aio.ProxyInterface
:members:
:undoc-members:
:show-inheritance:

View File

@@ -0,0 +1,7 @@
aio.ProxyObject
===============
.. autoclass:: dbus_next.aio.ProxyObject
:members:
:undoc-members:
:show-inheritance:

View File

@@ -0,0 +1,6 @@
BaseProxyInterface
==================
.. autoclass:: dbus_next.proxy_object.BaseProxyInterface
:members:
:undoc-members:

View File

@@ -0,0 +1,6 @@
BaseProxyObject
===============
.. autoclass:: dbus_next.proxy_object.BaseProxyObject
:members:
:undoc-members:

View File

@@ -0,0 +1,7 @@
glib.ProxyInterface
===================
.. autoclass:: dbus_next.glib.ProxyInterface
:members:
:undoc-members:
:show-inheritance:

View File

@@ -0,0 +1,7 @@
glib.ProxyObject
================
.. autoclass:: dbus_next.glib.ProxyObject
:members:
:undoc-members:
:show-inheritance:

View File

@@ -0,0 +1,100 @@
The High Level Client
=====================
.. toctree::
:maxdepth: 2
base-proxy-object
base-proxy-interface
aio-proxy-object
aio-proxy-interface
glib-proxy-object
glib-proxy-interface
DBus interfaces are defined with an XML-based `introspection data format <https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format>`_ which is exposed over the standard `org.freedesktop.DBus.Introspectable <https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable>`_ interface. Calling the ``Introspect`` at a particular object path may return XML data similar to this:
.. code-block:: xml
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/com/example/sample_object0">
<interface name="com.example.SampleInterface0">
<method name="Frobate">
<arg name="foo" type="i" direction="in"/>
<arg name="bar" type="s" direction="out"/>
<arg name="baz" type="a{us}" direction="out"/>
</method>
<method name="Bazify">
<arg name="bar" type="(iiu)" direction="in"/>
<arg name="bar" type="v" direction="out"/>
</method>
<method name="Mogrify">
<arg name="bar" type="(iiav)" direction="in"/>
</method>
<signal name="Changed">
<arg name="new_value" type="b"/>
</signal>
<property name="Bar" type="y" access="readwrite"/>
</interface>
<node name="child_of_sample_object"/>
<node name="another_child_of_sample_object"/>
</node>
The object at this path (a ``node``) may contain interfaces and child nodes. Nodes like this are represented in the library by a :class:`ProxyObject <dbus_next.proxy_object.BaseProxyObject>`. The interfaces contained in the nodes are represented by a :class:`ProxyInterface <dbus_next.proxy_object.BaseProxyInterface>`. The proxy interface exposes the methods, signals, and properties specified by the interface definition.
The proxy object is obtained by the :class:`MessageBus <dbus_next.message_bus.BaseMessageBus>` through the :func:`get_proxy_object() <dbus_next.message_bus.BaseMessageBus.get_proxy_object>` method. This method takes the name of the client to send messages to, the path exported by that client that is expected to export the node, and the XML introspection data. If you can, it is recommended to include the XML in your project and pass it to that method as a string. But you may also use the :func:`introspect() <dbus_next.message_bus.BaseMessageBus.introspect>` method of the message bus to get this data dynamically at runtime.
Once you have a proxy object, use the :func:`get_proxy_interface() <dbus_next.proxy_object.BaseProxyObject.get_interface>` method to create an interface passing the name of the interface to get. Each message bus has its own implementation of the proxy interface which behaves slightly differently. This is an example of how to use a proxy interface for the asyncio :class:`MessageBus <dbus_next.aio.MessageBus>`.
If any file descriptors are sent or received (DBus type ``h``), the variable refers to the file descriptor itself. You are responsible for closing any file descriptors sent or received by the bus. You must set the ``negotiate_unix_fd`` flag to ``True`` in the ``MessageBus`` constructor to use unix file descriptors.
:example:
.. code-block:: python3
from dbus_next.aio import MessageBus
from dbus_next import Variant
bus = await MessageBus().connect()
with open('introspection.xml', 'r') as f:
introspection = f.read()
# alternatively, get the data dynamically:
# introspection = await bus.introspect('com.example.name',
# '/com/example/sample_object0')
proxy_object = bus.get_proxy_object('com.example.name',
'/com/example/sample_object0',
introspection)
interface = proxy_object.get_interface('com.example.SampleInterface0')
# Use call_[METHOD] in snake case to call methods, passing the
# in args and receiving the out args. The `baz` returned will
# be type 'a{us}' which translates to a Python dict with `int`
# keys and `str` values.
baz = await interface.call_frobate(5, 'hello')
# `bar` will be a Variant.
bar = await interface.call_bazify([-5, 5, 5])
await interface.call_mogrify([5, 5, [ Variant('s', 'foo') ])
# Listen to signals by defining a callback that takes the args
# specified by the signal definition and registering it on the
# interface with on_[SIGNAL] in snake case.
def changed_notify(new_value):
print(f'The new value is: {new_value}')
interface.on_changed(changed_notify)
# Use get_[PROPERTY] and set_[PROPERTY] with the property in
# snake case to get and set the property.
bar_value = await interface.get_bar()
await interface.set_bar(105)
await bus.wait_for_disconnect()

View File

@@ -0,0 +1,93 @@
The High Level Service
======================
.. toctree::
:maxdepth: 2
service-interface
The high level service interface provides everything you need to export interfaces on the bus. When you export an interface on your :class:`MessageBus <dbus_next.message_bus.BaseMessageBus>`, clients can send you messages to call methods, get and set properties, and listen to your signals.
If you're exposing a service for general use, you can request a well-known name for your connection with :func:`MessageBus.request_name() <dbus_next.message_bus.BaseMessageBus.request_name>` so users have a predictable name to use to send messages your client.
Services are defined by subclassing :class:`ServiceInterface <dbus_next.service.ServiceInterface>` and definining members as methods on the class with the decorator methods :func:`@method() <dbus_next.service.method>`, :func:`@dbus_property() <dbus_next.service.dbus_property>`, and :func:`@signal() <dbus_next.service.signal>`. The parameters of the decorated class methods must be annotated with DBus type strings to indicate the types of values they expect. See the documentation on `the type system </type-system/index.html>`_ for more information on how DBus types are mapped to Python values with signature strings. The decorator methods themselves take arguments that affect how the member is exported on the bus, such as the name of the member or the access permissions of a property.
A class method decorated with ``@method()`` will be called when a client calls the method over DBus. The parameters given to the class method will be provided by the calling client and will conform to the parameter type annotations. The value returned by the class method will be returned to the client and must conform to the return type annotation specified by the user. If the return annotation specifies more than one type, the values must be returned in a ``list``. When :class:`aio.MessageBus` is used, methods can be coroutines.
A class method decorated with ``@dbus_property()`` will be exposed as a DBus property getter. This decoration works the same as a standard Python ``@property``. The getter will be called when a client gets the property through the standard properties interface with ``org.freedesktop.DBus.Properties.Get``. Define a property setter with ``@method_name.setter`` taking the new value as a parameter. The setter will be called when the client sets the property through ``org.freedesktop.DBus.Properties.Set``. When :class:`aio.MessageBus` is used, property getters and setters can be coroutines, although this will cause some functionality of the Python ``@property`` annotation to be lost.
A class method decorated with ``@signal()`` will be exposed as a DBus signal. The value returned by the class method will be emitted as a signal and broadcast to clients who are listening to the signal. The returned value must conform to the return annotation of the class method as a DBus signature string. If the signal has more than one argument, they must be returned within a ``list``.
A class method decorated with ``@method()`` or ``@dbus_property()`` may throw a :class:`DBusError <dbus_next.DBusError>` to return a detailed error to the client if something goes wrong.
After the service interface is defined, call :func:`MessageBus.export() <dbus_next.message_bus.BaseMessageBus.export>` on a connected message bus and the service will be made available on the given object path.
If any file descriptors are sent or received (DBus type ``h``), the variable refers to the file descriptor itself. You are responsible for closing any file descriptors sent or received by the bus. You must set the ``negotiate_unix_fd`` flag to ``True`` in the ``MessageBus`` constructor to use unix file descriptors.
:example:
.. code-block:: python3
from dbus_next.aio import MessageBus
from dbus_next.service import (ServiceInterface,
method, dbus_property, signal)
from dbus_next import Variant, DBusError
import asyncio
class ExampleInterface(ServiceInterface):
def __init__(self):
super().__init__('com.example.SampleInterface0')
self._bar = 105
@method()
def Frobate(self, foo: 'i', bar: 's') -> 'a{us}':
print(f'called Frobate with foo={foo} and bar={bar}')
return {
1: 'one',
2: 'two'
}
@method()
async def Bazify(self, bar: '(iiu)') -> 'vv':
print(f'called Bazify with bar={bar}')
return [Variant('s', 'example'), Variant('s', 'bazify')]
@method()
def Mogrify(self, bar: '(iiav)'):
raise DBusError('com.example.error.CannotMogrify',
'it is not possible to mogrify')
@signal()
def Changed(self) -> 'b':
return True
@dbus_property()
def Bar(self) -> 'y':
return self._bar
@Bar.setter
def Bar(self, val: 'y'):
if self._bar == val:
return
self._bar = val
self.emit_properties_changed({'Bar': self._bar})
async def main():
bus = await MessageBus().connect()
interface = ExampleInterface()
bus.export('/com/example/sample0', interface)
await bus.request_name('com.example.name')
# emit the changed signal after two seconds.
await asyncio.sleep(2)
interface.changed()
await bus.wait_for_disconnect()
asyncio.get_event_loop().run_until_complete(main())

View File

@@ -0,0 +1,12 @@
ServiceInterface
================
.. autoclass:: dbus_next.service.ServiceInterface
:members:
:undoc-members:
.. autodecorator:: dbus_next.service.dbus_property
.. autodecorator:: dbus_next.service.method
.. autodecorator:: dbus_next.service.signal

72
docs/source/index.rst Normal file
View File

@@ -0,0 +1,72 @@
Python DBus-Next Documentation
==============================
.. module:: dbus_next
.. toctree::
:maxdepth: 3
:caption: Reference:
type-system/index.rst
high-level-client/index.rst
high-level-service/index.rst
low-level-interface/index.rst
message-bus/index.rst
introspection
validators
constants
errors
authentication
Overview
++++++++
Python DBus-Next is a library for the `DBus message bus system <https://www.freedesktop.org/wiki/Software/dbus/>`_ for interprocess communcation in a Linux desktop or mobile environment.
Desktop application developers can use this library for integrating their applications into desktop environments by implementing common DBus standard interfaces or creating custom plugin interfaces.
Desktop users can use this library to create their own scripts and utilities to interact with those interfaces for customization of their desktop environment.
While other libraries for DBus exist for Python, this library offers the following improvements:
- Zero dependencies and pure Python 3.
- Support for multiple main loop 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.
The library offers three core interfaces:
- `The High Level Client <high-level-client/index.html>`_ - Communicate with an existing interface exported on the bus by another client through a proxy object.
- `The High Level Service <high-level-service/index.html>`_ - Export a service interface for your application other clients can connect to for interaction with your application at runtime.
- `The Low Level Interface <low-level-interface/index.html>`_ - Work with DBus messages directly for applications that work with the DBus daemon directly or to build your own high level abstractions.
Installation
++++++++++++
This library is available on PyPi as `dbus-next <https://pypi.org/project/dbus-next/>`_.
.. code-block:: bash
pip3 install dbus-next
Contributing
++++++++++++
Development for this library happens on `Github <https://github.com/altdesktop/python-dbus-next>`_. Report bugs or request features there. Contributions are welcome.
License
++++++++
This library is available under an `MIT License <https://github.com/altdesktop/python-dbus-next/blob/master/LICENSE>`_.
© 2019, Tony Crisci
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -0,0 +1,26 @@
Introspection
=============
.. autoclass:: dbus_next.introspection.Node
:members:
:undoc-members:
.. autoclass:: dbus_next.introspection.Interface
:members:
:undoc-members:
.. autoclass:: dbus_next.introspection.Property
:members:
:undoc-members:
.. autoclass:: dbus_next.introspection.Method
:members:
:undoc-members:
.. autoclass:: dbus_next.introspection.Signal
:members:
:undoc-members:
.. autoclass:: dbus_next.introspection.Arg
:members:
:undoc-members:

View File

@@ -0,0 +1,100 @@
The Low Level Interface
=======================
.. toctree::
:maxdepth: 2
message
The low-level interface allows you to work with messages directly through the :class:`MessageBus <dbus_next.message_bus.BaseMessageBus>` with the :class:`Message <dbus_next.Message>` class. This might be useful in the following cases:
- Implementing an application that works with DBus directly like ``dbus-send(1)`` or ``dbus-monitor(1)``.
- Creating a new implementation of the :class:`BaseMessageBus <dbus_next.message_bus.BaseMessageBus>`.
- Creating clients or services that use an alternative to the standard DBus interfaces.
The primary methods and classes of the low-level interface are:
- :class:`Message <dbus_next.Message>`
- :func:`MessageBus.send() <dbus_next.message_bus.BaseMessageBus.send>`
- :func:`MessageBus.add_message_handler() <dbus_next.message_bus.BaseMessageBus.add_message_handler>`
- :func:`MessageBus.remove_message_handler() <dbus_next.message_bus.BaseMessageBus.remove_message_handler>`
- :func:`MessageBus.next_serial() <dbus_next.message_bus.BaseMessageBus.next_serial>`
- :func:`aio.MessageBus.call() <dbus_next.aio.MessageBus.call>`
- :func:`glib.MessageBus.call() <dbus_next.glib.MessageBus.call>`
- :func:`glib.MessageBus.call_sync() <dbus_next.glib.MessageBus.call_sync>`
Mixed use of the low and high level interfaces on the same bus connection is not recommended.
:example: Call a standard interface
.. code-block:: python3
bus = await MessageBus().connect()
msg = Message(destination='org.freedesktop.DBus',
path='/org/freedesktop/DBus',
interface='org.freedesktop.DBus',
member='ListNames',
serial=bus.next_serial())
reply = await bus.call(msg)
assert reply.message_type == MessageType.METHOD_RETURN
print(reply.body[0])
:example: A custom method handler. Note that to receive these messages, you must `add a match rule <https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-routing-match-rules>`_ for the types of messages you want to receive.
.. code-block:: python3
bus = await MessageBus().connect()
reply = await bus.call(
Message(destination='org.freedesktop.DBus',
path='/org/freedesktop/DBus',
member='AddMatch',
signature='s',
body=["member='MyMember', interface='com.test.interface'"]))
assert reply.message_type == MessageType.METHOD_RETURN
def message_handler(msg):
if msg.interface == 'com.test.interface' and msg.member == 'MyMember':
return Message.new_method_return(msg, 's', ['got it'])
bus.add_message_handler(message_handler)
await bus.wait_for_disconnect()
:example: Emit a signal
.. code-block:: python3
bus = await MessageBus().connect()
await bus.send(Message.new_signal('/com/test/path',
'com.test.interface',
'SomeSignal',
's', ['a signal']))
:example: Send a file descriptor. The message format will be the same when
received on the client side. You are responsible for closing any file
descriptor that is sent or received by the bus. You must set the
``negotiate_unix_fd`` flag to ``True`` in the ``MessageBus``
constructor to use unix file descriptors.
.. code-block:: python3
bus = await MessageBus().connect(negotiate_unix_fd=True)
fd = os.open('/dev/null', os.O_RDONLY)
msg = Message(destination='org.test.destination',
path='/org/test/destination',
interface='org.test.interface',
member='TestMember',
signature='h',
body=[0],
unix_fds=[fd])
await bus.send(msg)

View File

@@ -0,0 +1,6 @@
Message
=======
.. autoclass:: dbus_next.Message
:members:
:undoc-members:

View File

@@ -0,0 +1,7 @@
aio.MessageBus
==============
.. autoclass:: dbus_next.aio.MessageBus
:members:
:inherited-members:
:show-inheritance:

View File

@@ -0,0 +1,5 @@
BaseMessageBus
==============
.. autoclass:: dbus_next.message_bus.BaseMessageBus
:members:

View File

@@ -0,0 +1,7 @@
glib.MessageBus
===============
.. autoclass:: dbus_next.glib.MessageBus
:members:
:inherited-members:
:show-inheritance:

View File

@@ -0,0 +1,17 @@
The Message Bus
===============
.. toctree::
:maxdepth: 2
base-message-bus.rst
aio-message-bus.rst
glib-message-bus.rst
The message bus manages a connection to the DBus daemon. It's capable of sending and receiving messages and wiring up the classes of the high level interfaces.
There are currently two implementations of the message bus depending on what main loop implementation you want to use. Use :class:`aio.MessageBus <dbus_next.aio.MessageBus>` if you are using an asyncio main loop. Use :class:`glib.MessageBus <dbus_next.glib.MessageBus>` if you are using a GLib main loop.
For standalone applications, the asyncio message bus is preferable because it has a nice async/await api in place of the callback/synchronous interface of the GLib message bus. If your application is using other libraries that use the GLib main loop, such as a GTK application, the GLib implementation will be needed. However neither library is a requirement.
For more information on how to use the message bus, see the documentation for the specific interfaces you plan to use.

View File

@@ -0,0 +1,102 @@
The Type System
===============
.. toctree::
:maxdepth: 2
variant
signature-tree
signature-type
Values that are sent or received over the message bus always have an
associated signature that specifies the types of those values. For the
high-level client and service, these signatures are specified in XML
data which is advertised in a `standard DBus
interface <https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format>`__.
The high-level client dynamically creates classes based on this
introspection data with methods and signals with arguments based on the
type signature. The high-level service does the inverse by introspecting
the class to create the introspection XML data which is advertised on
the bus for clients.
Each token in the signature is mapped to a Python type as shown in the table
below.
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| Name | Token | Python | Notes |
| | | Type | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| BYTE | y | int | An integer 0-255. In an array, it has type ``bytes``. |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| BOOLEAN | b | bool | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| INT16 | n | int | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| UINT16 | q | int | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| INT32 | i | int | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| UINT32 | u | int | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| INT64 | x | int | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| UINT64 | t | int | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| DOUBLE | d | float | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| STRING | s | str | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| OBJECT_PATH | o | str | Must be a valid object path. |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| SIGNATURE | g | str | Must be a valid signature. |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| UNIX_FD | h | int | In the low-level interface, an index pointing to a file descriptor |
| | | | in the ``unix_fds`` member of the :class:`Message <dbus_next.Message>`. |
| | | | In the high-level interface, it is the file descriptor itself. |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| ARRAY | a | list | Must be followed by a complete type which specifies the child type. |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| STRUCT | ( | list | Types in the Python ``list`` must match the types between the parens. |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| VARIANT | v | :class:`Variant <dbus_next.Variant>` | This class is provided by the library. |
| | | | |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
| DICT_ENTRY | { | dict | Must be included in an array to be a ``dict``. |
+-------------+-------+--------------------------------------+-------------------------------------------------------------------------+
The types ``a``, ``(``, ``v``, and ``{`` are container types that hold
other values. Examples of container types and Python examples are in the
table below.
+-----------+--------------------------------------+-------------------------------------------------------+
| Signature | Example | Notes |
+===========+======================================+=======================================================+
| ``(su)`` | ``[ 'foo', 5 ]`` | Each element in the array must match the |
| | | corresponding type of the struct member. |
+-----------+--------------------------------------+-------------------------------------------------------+
| ``as`` | ``[ 'foo', 'bar' ]`` | The child type comes immediately after the ``a``. |
| | | The array can have any number of elements, but |
| | | they all must match the child type. |
+-----------+--------------------------------------+-------------------------------------------------------+
| ``a{su}`` | ``{ 'foo': 5 }`` | An "array of dict entries" is represented by a |
| | | ``dict``. The type after ``{`` is the key type and |
| | | the type before the ``}`` is the value type. |
+-----------+--------------------------------------+-------------------------------------------------------+
| ``ay`` | ``b'\0x62\0x75\0x66'`` | Special case: an array of bytes is represented by |
| | | Python ``bytes``. |
| | | |
| | | |
| | | |
| | | |
+-----------+--------------------------------------+-------------------------------------------------------+
| ``v`` | ``Variant('as', ['hello'])`` | Signature must be a single type. A variant may hold a |
| | | container type. |
| | | |
| | | |
| | | |
+-----------+--------------------------------------+-------------------------------------------------------+
| ``(asv)`` | ``[ ['foo'], Variant('s', 'bar') ]`` | Containers may be nested. |
+-----------+--------------------------------------+-------------------------------------------------------+
For more information on the DBus type system, see `the
specification <https://dbus.freedesktop.org/doc/dbus-specification.html#type-system>`__.

View File

@@ -0,0 +1,6 @@
SignatureTree
=============
.. autoclass:: dbus_next.SignatureTree
:members:
:undoc-members:

View File

@@ -0,0 +1,7 @@
SignatureType
==============
.. autoclass:: dbus_next.SignatureType
:members:
:undoc-members:
:exclude-members: signature

View File

@@ -0,0 +1,6 @@
Variant
=======
.. autoclass:: dbus_next.Variant
:members:
:undoc-members:

View File

@@ -0,0 +1,11 @@
Validators
==========
.. autofunction:: dbus_next.is_bus_name_valid
.. autofunction:: dbus_next.is_member_name_valid
.. autofunction:: dbus_next.is_object_path_valid
.. autofunction:: dbus_next.is_interface_name_valid
.. autofunction:: dbus_next.assert_bus_name_valid
.. autofunction:: dbus_next.assert_member_name_valid
.. autofunction:: dbus_next.assert_object_path_valid
.. autofunction:: dbus_next.assert_interface_name_valid