chore: initial port
This commit is contained in:
20
docs/source/Makefile
Normal file
20
docs/source/Makefile
Normal 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
0
docs/source/_static/.gitignore
vendored
Normal file
0
docs/source/_templates/.gitignore
vendored
Normal file
0
docs/source/_templates/.gitignore
vendored
Normal file
9
docs/source/authentication.rst
Normal file
9
docs/source/authentication.rst
Normal 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
|
||||
@@ -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
39
docs/source/constants.rst
Normal 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
19
docs/source/errors.rst
Normal 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
|
||||
7
docs/source/high-level-client/aio-proxy-interface.rst
Normal file
7
docs/source/high-level-client/aio-proxy-interface.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
aio.ProxyInterface
|
||||
==================
|
||||
|
||||
.. autoclass:: dbus_next.aio.ProxyInterface
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
docs/source/high-level-client/aio-proxy-object.rst
Normal file
7
docs/source/high-level-client/aio-proxy-object.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
aio.ProxyObject
|
||||
===============
|
||||
|
||||
.. autoclass:: dbus_next.aio.ProxyObject
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
6
docs/source/high-level-client/base-proxy-interface.rst
Normal file
6
docs/source/high-level-client/base-proxy-interface.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
BaseProxyInterface
|
||||
==================
|
||||
|
||||
.. autoclass:: dbus_next.proxy_object.BaseProxyInterface
|
||||
:members:
|
||||
:undoc-members:
|
||||
6
docs/source/high-level-client/base-proxy-object.rst
Normal file
6
docs/source/high-level-client/base-proxy-object.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
BaseProxyObject
|
||||
===============
|
||||
|
||||
.. autoclass:: dbus_next.proxy_object.BaseProxyObject
|
||||
:members:
|
||||
:undoc-members:
|
||||
7
docs/source/high-level-client/glib-proxy-interface.rst
Normal file
7
docs/source/high-level-client/glib-proxy-interface.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
glib.ProxyInterface
|
||||
===================
|
||||
|
||||
.. autoclass:: dbus_next.glib.ProxyInterface
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
docs/source/high-level-client/glib-proxy-object.rst
Normal file
7
docs/source/high-level-client/glib-proxy-object.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
glib.ProxyObject
|
||||
================
|
||||
|
||||
.. autoclass:: dbus_next.glib.ProxyObject
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
100
docs/source/high-level-client/index.rst
Normal file
100
docs/source/high-level-client/index.rst
Normal 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()
|
||||
93
docs/source/high-level-service/index.rst
Normal file
93
docs/source/high-level-service/index.rst
Normal 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())
|
||||
12
docs/source/high-level-service/service-interface.rst
Normal file
12
docs/source/high-level-service/service-interface.rst
Normal 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
72
docs/source/index.rst
Normal 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`
|
||||
26
docs/source/introspection.rst
Normal file
26
docs/source/introspection.rst
Normal 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:
|
||||
100
docs/source/low-level-interface/index.rst
Normal file
100
docs/source/low-level-interface/index.rst
Normal 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)
|
||||
6
docs/source/low-level-interface/message.rst
Normal file
6
docs/source/low-level-interface/message.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
Message
|
||||
=======
|
||||
|
||||
.. autoclass:: dbus_next.Message
|
||||
:members:
|
||||
:undoc-members:
|
||||
7
docs/source/message-bus/aio-message-bus.rst
Normal file
7
docs/source/message-bus/aio-message-bus.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
aio.MessageBus
|
||||
==============
|
||||
|
||||
.. autoclass:: dbus_next.aio.MessageBus
|
||||
:members:
|
||||
:inherited-members:
|
||||
:show-inheritance:
|
||||
5
docs/source/message-bus/base-message-bus.rst
Normal file
5
docs/source/message-bus/base-message-bus.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
BaseMessageBus
|
||||
==============
|
||||
|
||||
.. autoclass:: dbus_next.message_bus.BaseMessageBus
|
||||
:members:
|
||||
7
docs/source/message-bus/glib-message-bus.rst
Normal file
7
docs/source/message-bus/glib-message-bus.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
glib.MessageBus
|
||||
===============
|
||||
|
||||
.. autoclass:: dbus_next.glib.MessageBus
|
||||
:members:
|
||||
:inherited-members:
|
||||
:show-inheritance:
|
||||
17
docs/source/message-bus/index.rst
Normal file
17
docs/source/message-bus/index.rst
Normal 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.
|
||||
102
docs/source/type-system/index.rst
Normal file
102
docs/source/type-system/index.rst
Normal 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>`__.
|
||||
6
docs/source/type-system/signature-tree.rst
Normal file
6
docs/source/type-system/signature-tree.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
SignatureTree
|
||||
=============
|
||||
|
||||
.. autoclass:: dbus_next.SignatureTree
|
||||
:members:
|
||||
:undoc-members:
|
||||
7
docs/source/type-system/signature-type.rst
Normal file
7
docs/source/type-system/signature-type.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
SignatureType
|
||||
==============
|
||||
|
||||
.. autoclass:: dbus_next.SignatureType
|
||||
:members:
|
||||
:undoc-members:
|
||||
:exclude-members: signature
|
||||
6
docs/source/type-system/variant.rst
Normal file
6
docs/source/type-system/variant.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
Variant
|
||||
=======
|
||||
|
||||
.. autoclass:: dbus_next.Variant
|
||||
:members:
|
||||
:undoc-members:
|
||||
11
docs/source/validators.rst
Normal file
11
docs/source/validators.rst
Normal 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
|
||||
Reference in New Issue
Block a user