Blame doc/tutorial.txt

Packit 130fc8
====================
Packit 130fc8
dbus-python tutorial
Packit 130fc8
====================
Packit 130fc8
Packit 130fc8
:Author: Simon McVittie, `Collabora Ltd.`_
Packit 130fc8
:Date: 2006-06-14
Packit 130fc8
Packit 130fc8
.. _`Collabora Ltd.`: http://www.collabora.co.uk/
Packit 130fc8
Packit 130fc8
This tutorial requires Python 2.4 or up, and ``dbus-python`` 0.80rc4 or up.
Packit 130fc8
Packit 130fc8
.. contents::
Packit 130fc8
Packit 130fc8
.. --------------------------------------------------------------------
Packit 130fc8
Packit 130fc8
.. _Bus object:
Packit 130fc8
.. _Bus objects:
Packit 130fc8
Packit 130fc8
Connecting to the Bus
Packit 130fc8
=====================
Packit 130fc8
Packit 130fc8
Applications that use D-Bus typically connect to a *bus daemon*, which
Packit 130fc8
forwards messages between the applications. To use D-Bus, you need to create a
Packit 130fc8
``Bus`` object representing the connection to the bus daemon.
Packit 130fc8
Packit 130fc8
There are generally two bus daemons you may be interested in. Each user
Packit 130fc8
login session should have a *session bus*, which is local to that
Packit 130fc8
session. It's used to communicate between desktop applications. Connect
Packit 130fc8
to the session bus by creating a ``SessionBus`` object::
Packit 130fc8
Packit 130fc8
    import dbus
Packit 130fc8
Packit 130fc8
    session_bus = dbus.SessionBus()
Packit 130fc8
Packit 130fc8
The *system bus* is global and usually started during boot; it's used to
Packit 130fc8
communicate with system services like udev_, NetworkManager_, and the
Packit 130fc8
`Hardware Abstraction Layer daemon (hald)`_. To connect to the system
Packit 130fc8
bus, create a ``SystemBus`` object::
Packit 130fc8
Packit 130fc8
    import dbus
Packit 130fc8
Packit 130fc8
    system_bus = dbus.SystemBus()
Packit 130fc8
Packit 130fc8
Of course, you can connect to both in the same application.
Packit 130fc8
Packit 130fc8
For special purposes, you might use a non-default Bus, or a connection
Packit 130fc8
which isn't a Bus at all, using some new API added in dbus-python 0.81.0.
Packit 130fc8
This is not described here, and will at some stage be the subject of a separate
Packit 130fc8
tutorial.
Packit 130fc8
Packit 130fc8
.. _udev:
Packit 130fc8
    http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
Packit 130fc8
.. _NetworkManager:
Packit 130fc8
    http://www.gnome.org/projects/NetworkManager/
Packit 130fc8
.. _Hardware Abstraction Layer daemon (hald):
Packit 130fc8
    http://www.freedesktop.org/wiki/Software/hal
Packit 130fc8
Packit 130fc8
.. --------------------------------------------------------------------
Packit 130fc8
Packit 130fc8
Making method calls
Packit 130fc8
===================
Packit 130fc8
Packit 130fc8
D-Bus applications can export objects for other applications' use. To
Packit 130fc8
start working with an object in another application, you need to know:
Packit 130fc8
Packit 130fc8
* The *bus name*. This identifies which application you want to
Packit 130fc8
  communicate with. You'll usually identify applications by a
Packit 130fc8
  *well-known name*, which is a dot-separated string starting with a
Packit 130fc8
  reversed domain name, such as ``org.freedesktop.NetworkManager``
Packit 130fc8
  or ``com.example.WordProcessor``.
Packit 130fc8
Packit 130fc8
* The *object path*. Applications can export many objects - for
Packit 130fc8
  instance, example.com's word processor might provide an object
Packit 130fc8
  representing the word processor application itself and an object for
Packit 130fc8
  each document window opened, or it might also provide an object for
Packit 130fc8
  each paragraph within a document.
Packit 130fc8
  
Packit 130fc8
  To identify which one you want to interact with, you use an object path,
Packit 130fc8
  a slash-separated string resembling a filename. For instance, example.com's
Packit 130fc8
  word processor might provide an object at ``/`` representing the word
Packit 130fc8
  processor itself, and objects at ``/documents/123`` and
Packit 130fc8
  ``/documents/345`` representing opened document windows.
Packit 130fc8
Packit 130fc8
As you'd expect, one of the main things you can do with remote objects
Packit 130fc8
is to call their methods. As in Python, methods may have parameters,
Packit 130fc8
and they may return one or more values.
Packit 130fc8
Packit 130fc8
.. _proxy object:
Packit 130fc8
Packit 130fc8
Proxy objects
Packit 130fc8
-------------
Packit 130fc8
Packit 130fc8
To interact with a remote object, you use a *proxy object*. This is a
Packit 130fc8
Python object which acts as a proxy or "stand-in" for the remote object -
Packit 130fc8
when you call a method on a proxy object, this causes dbus-python to make
Packit 130fc8
a method call on the remote object, passing back any return values from
Packit 130fc8
the remote object's method as the return values of the proxy method call.
Packit 130fc8
Packit 130fc8
To obtain a proxy object, call the ``get_object`` method on the ``Bus``.
Packit 130fc8
For example, NetworkManager_ has the well-known name
Packit 130fc8
``org.freedesktop.NetworkManager`` and exports an object whose object
Packit 130fc8
path is ``/org/freedesktop/NetworkManager``, plus an object per network
Packit 130fc8
interface at object paths like
Packit 130fc8
``/org/freedesktop/NetworkManager/Devices/eth0``. You can get a proxy
Packit 130fc8
for the object representing eth0 like this::
Packit 130fc8
Packit 130fc8
    import dbus
Packit 130fc8
    bus = dbus.SystemBus()
Packit 130fc8
    proxy = bus.get_object('org.freedesktop.NetworkManager',
Packit 130fc8
                           '/org/freedesktop/NetworkManager/Devices/eth0')
Packit 130fc8
    # proxy is a dbus.proxies.ProxyObject
Packit 130fc8
Packit 130fc8
Interfaces and methods
Packit 130fc8
----------------------
Packit 130fc8
Packit 130fc8
D-Bus uses *interfaces* to provide a namespacing mechanism for methods.
Packit 130fc8
An interface is a group of related methods and signals (more on signals
Packit 130fc8
later), identified by a name which is a series of dot-separated components
Packit 130fc8
starting with a reversed domain name. For instance, each NetworkManager_
Packit 130fc8
object representing a network interface implements the interface
Packit 130fc8
``org.freedesktop.NetworkManager.Devices``, which has methods like
Packit 130fc8
``getProperties``.
Packit 130fc8
Packit 130fc8
To call a method, call the method of the same name on the proxy object,
Packit 130fc8
passing in the interface name via the ``dbus_interface`` keyword argument::
Packit 130fc8
Packit 130fc8
    import dbus
Packit 130fc8
    bus = dbus.SystemBus()
Packit 130fc8
    eth0 = bus.get_object('org.freedesktop.NetworkManager',
Packit 130fc8
                          '/org/freedesktop/NetworkManager/Devices/eth0')
Packit 130fc8
    props = eth0.getProperties(dbus_interface='org.freedesktop.NetworkManager.Devices')
Packit 130fc8
    # props is a tuple of properties, the first of which is the object path
Packit 130fc8
Packit 130fc8
.. _dbus.Interface:
Packit 130fc8
Packit 130fc8
As a short cut, if you're going to be calling many methods with the same
Packit 130fc8
interface, you can construct a ``dbus.Interface`` object and call
Packit 130fc8
methods on that, without needing to specify the interface again::
Packit 130fc8
Packit 130fc8
    import dbus
Packit 130fc8
    bus = dbus.SystemBus()
Packit 130fc8
    eth0 = bus.get_object('org.freedesktop.NetworkManager',
Packit 130fc8
                          '/org/freedesktop/NetworkManager/Devices/eth0')
Packit 130fc8
    eth0_dev_iface = dbus.Interface(eth0,
Packit 130fc8
        dbus_interface='org.freedesktop.NetworkManager.Devices')
Packit 130fc8
    props = eth0_dev_iface.getProperties()
Packit 130fc8
    # props is the same as before
Packit 130fc8
Packit 130fc8
See also
Packit 130fc8
~~~~~~~~
Packit 130fc8
Packit 130fc8
See the example in ``examples/example-client.py``. Before running it,
Packit 130fc8
you'll need to run ``examples/example-service.py`` in the background or
Packit 130fc8
in another shell.
Packit 130fc8
Packit 130fc8
Data types
Packit 130fc8
----------
Packit 130fc8
Packit 130fc8
Unlike Python, D-Bus is statically typed - each method has a certain
Packit 130fc8
*signature* representing the types of its arguments, and will not accept
Packit 130fc8
arguments of other types.
Packit 130fc8
Packit 130fc8
D-Bus has an introspection mechanism, which ``dbus-python`` tries to use
Packit 130fc8
to discover the correct argument types. If this succeeds, Python types
Packit 130fc8
are converted into the right D-Bus data types automatically, if possible;
Packit 130fc8
``TypeError`` is raised if the type is inappropriate.
Packit 130fc8
Packit 130fc8
If the introspection mechanism fails (or the argument's type is
Packit 130fc8
variant - see below), you have to provide arguments of
Packit 130fc8
the correct type. ``dbus-python`` provides Python types corresponding to
Packit 130fc8
the D-Bus data types, and a few native Python types are also converted to
Packit 130fc8
D-Bus data types automatically. If you use a type which isn't among these,
Packit 130fc8
a ``TypeError`` will be raised telling you that ``dbus-python`` was
Packit 130fc8
unable to guess the D-Bus signature.
Packit 130fc8
Packit 130fc8
Basic types
Packit 130fc8
~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
The following basic data types are supported.
Packit 130fc8
Packit 130fc8
==========================  =============================  =====
Packit 130fc8
Python type                 converted to D-Bus type        notes
Packit 130fc8
==========================  =============================  =====
Packit 130fc8
D-Bus `proxy object`_       ObjectPath (signature 'o')     `(+)`_
Packit 130fc8
`dbus.Interface`_           ObjectPath (signature 'o')     `(+)`_
Packit 130fc8
`dbus.service.Object`_      ObjectPath (signature 'o')     `(+)`_
Packit 130fc8
``dbus.Boolean``            Boolean (signature 'b')        a subclass of ``int``
Packit 130fc8
``dbus.Byte``               byte (signature 'y')           a subclass of ``int``
Packit 130fc8
``dbus.Int16``              16-bit signed integer ('n')    a subclass of ``int``
Packit 130fc8
``dbus.Int32``              32-bit signed integer ('i')    a subclass of ``int``
Packit 130fc8
``dbus.Int64``              64-bit signed integer ('x')    `(*)`_
Packit 130fc8
``dbus.UInt16``             16-bit unsigned integer ('q')  a subclass of ``int``
Packit 130fc8
``dbus.UInt32``             32-bit unsigned integer ('u')  `(*)_`
Packit 130fc8
``dbus.UInt64``             64-bit unsigned integer ('t')  `(*)_`
Packit 130fc8
``dbus.Double``             double-precision float ('d')   a subclass of ``float``
Packit 130fc8
``dbus.ObjectPath``         object path ('o')              a subclass of ``str``
Packit 130fc8
``dbus.Signature``          signature ('g')                a subclass of ``str``
Packit 130fc8
``dbus.String``             string ('s')                   a subclass of 
Packit 130fc8
                                                           ``unicode``
Packit 130fc8
``dbus.UTF8String``         string ('s')                   a subclass of ``str``
Packit 130fc8
``bool``                    Boolean ('b')
Packit 130fc8
``int`` or subclass         32-bit signed integer ('i')
Packit 130fc8
``long`` or subclass        64-bit signed integer ('x')
Packit 130fc8
``float`` or subclass       double-precision float ('d')
Packit 130fc8
``str`` or subclass         string ('s')                   must be valid UTF-8
Packit 130fc8
``unicode`` or subclass     string ('s')
Packit 130fc8
==========================  =============================  =====
Packit 130fc8
Packit 130fc8
.. _(*):
Packit 130fc8
Packit 130fc8
Types marked (*) may be a subclass of either ``int`` or ``long``, depending
Packit 130fc8
on platform.
Packit 130fc8
Packit 130fc8
.. _(+):
Packit 130fc8
Packit 130fc8
(+): D-Bus proxy objects, exported D-Bus service objects and anything
Packit 130fc8
else with the special attribute ``__dbus_object_path__``, which
Packit 130fc8
must be a string, are converted to their object-path. This might be
Packit 130fc8
useful if you're writing an object-oriented API using dbus-python.
Packit 130fc8
Packit 130fc8
Basic type conversions
Packit 130fc8
~~~~~~~~~~~~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
If introspection succeeded, ``dbus-python`` will also accept:
Packit 130fc8
Packit 130fc8
* for Boolean parameters, any object (converted as if via ``int(bool(...))``)
Packit 130fc8
* for byte parameters, a single-character string (converted as if via ``ord()``)
Packit 130fc8
* for byte and integer parameters, any integer (must be in the correct range)
Packit 130fc8
* for object-path and signature parameters, any ``str`` or ``unicode``
Packit 130fc8
  subclass (the value must follow the appropriate syntax)
Packit 130fc8
Packit 130fc8
Container types
Packit 130fc8
~~~~~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
D-Bus supports four container types: array (a variable-length sequence of the
Packit 130fc8
same type), struct (a fixed-length sequence whose members may have
Packit 130fc8
different types), dictionary (a mapping from values of the same basic type to
Packit 130fc8
values of the same type), and variant (a container which may hold any
Packit 130fc8
D-Bus type, including another variant).
Packit 130fc8
Packit 130fc8
Arrays are represented by Python lists, or by ``dbus.Array``, a subclass
Packit 130fc8
of ``list``. When sending an array, if an introspected signature is
Packit 130fc8
available, that will be used; otherwise, if the ``signature`` keyword
Packit 130fc8
parameter was passed to the ``Array`` constructor, that will be used to
Packit 130fc8
determine the contents' signature; otherwise, ``dbus-python`` will guess
Packit 130fc8
from the array's first item.
Packit 130fc8
Packit 130fc8
The signature of an array is 'ax' where 'x' represents the signature of
Packit 130fc8
one item. For instance, you could also have 'as' (array of strings) or
Packit 130fc8
'a(ii)' (array of structs each containing two 32-bit integers).
Packit 130fc8
Packit 130fc8
There's also a type ``dbus.ByteArray`` which is a subclass of ``str``,
Packit 130fc8
used as a more efficient representation of a D-Bus array of bytes
Packit 130fc8
(signature 'ay').
Packit 130fc8
Packit 130fc8
Structs are represented by Python tuples, or by ``dbus.Struct``, a
Packit 130fc8
subclass of ``tuple``. When sending a struct, if an introspected signature is
Packit 130fc8
available, that will be used; otherwise, if the ``signature`` keyword
Packit 130fc8
parameter was passed to the ``Array`` constructor, that will be used to
Packit 130fc8
determine the contents' signature; otherwise, ``dbus-python`` will guess
Packit 130fc8
from the array's first item.
Packit 130fc8
Packit 130fc8
The signature of a struct consists of the signatures of the contents,
Packit 130fc8
in parentheses - for instance '(is)' is the signature of a struct
Packit 130fc8
containing a 32-bit integer and a string.
Packit 130fc8
Packit 130fc8
Dictionaries are represented by Python dictionaries, or by
Packit 130fc8
``dbus.Dictionary``, a subclass of ``dict``. When sending a dictionary,
Packit 130fc8
if an introspected signature is available, that will be used; otherwise,
Packit 130fc8
if the ``signature`` keyword parameter was passed to the ``Dictionary``
Packit 130fc8
constructor, that will be used to determine the contents' key and value
Packit 130fc8
signatures; otherwise, ``dbus-python`` will guess from an arbitrary item
Packit 130fc8
of the ``dict``.
Packit 130fc8
Packit 130fc8
The signature of a dictionary is 'a{xy}' where 'x' represents the
Packit 130fc8
signature of the keys (which may not be a container type) and 'y'
Packit 130fc8
represents the signature of the values. For instance,
Packit 130fc8
'a{s(ii)}' is a dictionary where the keys are strings and the values are
Packit 130fc8
structs containing two 32-bit integers.
Packit 130fc8
Packit 130fc8
Variants are represented by setting the ``variant_level`` keyword
Packit 130fc8
argument in the constructor of any D-Bus data type to a value greater
Packit 130fc8
than 0 (``variant_level`` 1 means a variant containing some other data type,
Packit 130fc8
``variant_level`` 2 means a variant containing a variant containing some
Packit 130fc8
other data type, and so on). If a non-variant is passed as an argument
Packit 130fc8
but introspection indicates that a variant is expected, it'll
Packit 130fc8
automatically be wrapped in a variant.
Packit 130fc8
Packit 130fc8
The signature of a variant is 'v'.
Packit 130fc8
Packit 130fc8
.. _byte_arrays and utf8_strings:
Packit 130fc8
Packit 130fc8
Return values, and the ``byte_arrays`` and ``utf8_strings`` options
Packit 130fc8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
If a D-Bus method returns no value, the Python proxy method will return
Packit 130fc8
``None``.
Packit 130fc8
Packit 130fc8
If a D-Bus method returns one value, the Python proxy method will return
Packit 130fc8
that value as one of the ``dbus.`` types - by default, strings are
Packit 130fc8
returned as ``dbus.String`` (a subclass of Unicode) and byte arrays are
Packit 130fc8
returned as a ``dbus.Array`` of ``dbus.Byte``.
Packit 130fc8
Packit 130fc8
If a D-Bus method returns multiple values, the Python proxy method
Packit 130fc8
will return a tuple containing those values.
Packit 130fc8
Packit 130fc8
If you want strings returned as ``dbus.UTF8String`` (a subclass of
Packit 130fc8
``str``) pass the keyword parameter ``utf8_strings=True`` to the proxy
Packit 130fc8
method.
Packit 130fc8
Packit 130fc8
If you want byte arrays returned as ``dbus.ByteArray`` (also a
Packit 130fc8
subclass of ``str`` - in practice, this is often what you want) pass
Packit 130fc8
the keyword parameter ``byte_arrays=True`` to the proxy method.
Packit 130fc8
Packit 130fc8
.. --------------------------------------------------------------------
Packit 130fc8
Packit 130fc8
Making asynchronous method calls
Packit 130fc8
================================
Packit 130fc8
Packit 130fc8
Asynchronous (non-blocking) method calls allow multiple method calls to
Packit 130fc8
be in progress simultaneously, and allow your application to do other
Packit 130fc8
work while it's waiting for the results. To make asynchronous calls,
Packit 130fc8
you first need an event loop or "main loop".
Packit 130fc8
Packit 130fc8
Setting up an event loop
Packit 130fc8
------------------------
Packit 130fc8
Packit 130fc8
Currently, the only main loop supported by ``dbus-python`` is GLib.
Packit 130fc8
Packit 130fc8
``dbus-python`` has a global default main loop, which is the easiest way
Packit 130fc8
to use this functionality. To arrange for the GLib main loop to be the
Packit 130fc8
default, use::
Packit 130fc8
Packit 130fc8
    from dbus.mainloop.glib import DBusGMainLoop
Packit 130fc8
Packit 130fc8
    DBusGMainLoop(set_as_default=True)
Packit 130fc8
Packit 130fc8
You must do this before `connecting to the bus`_.
Packit 130fc8
Packit 130fc8
Actually starting the main loop is as usual for ``pygi``::
Packit 130fc8
Packit 130fc8
    from gi.repository import GLib
Packit 130fc8
Packit 130fc8
    loop = GLib.MainLoop()
Packit 130fc8
    loop.run()
Packit 130fc8
Packit 130fc8
While ``loop.run()`` is executing, GLib will run your callbacks when
Packit 130fc8
appropriate. To stop, call ``loop.quit()``.
Packit 130fc8
Packit 130fc8
You can also set a main loop on a per-connection basis, by passing a
Packit 130fc8
main loop to the Bus constructor::
Packit 130fc8
Packit 130fc8
    import dbus
Packit 130fc8
    from dbus.mainloop.glib import DBusGMainLoop
Packit 130fc8
Packit 130fc8
    dbus_loop = DBusGMainLoop()
Packit 130fc8
Packit 130fc8
    bus = dbus.SessionBus(mainloop=dbus_loop)
Packit 130fc8
Packit 130fc8
This isn't very useful until we support more than one main loop, though.
Packit 130fc8
Packit 130fc8
Backwards compatibility: ``dbus.glib``
Packit 130fc8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
In versions of ``dbus-python`` prior to 0.80, the way to set GLib as the
Packit 130fc8
default main loop was::
Packit 130fc8
Packit 130fc8
    import dbus.glib
Packit 130fc8
Packit 130fc8
Executing that import statement would automatically load the GLib main
Packit 130fc8
loop and make this the default. This is now deprecated, since it's
Packit 130fc8
highly non-obvious, but may be useful if you want to write or understand
Packit 130fc8
backwards-compatible code.
Packit 130fc8
Packit 130fc8
The Qt main loop
Packit 130fc8
~~~~~~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
PyQt v4.2 and later includes support for integrating dbus-python with
Packit 130fc8
the Qt event loop. To connect D-Bus to this main loop, call
Packit 130fc8
``dbus.mainloop.qt.DBusQtMainLoop`` instead of
Packit 130fc8
``dbus.mainloop.glib.DBusGMainLoop``. Otherwise the Qt loop is used in
Packit 130fc8
exactly the same way as the GLib loop.
Packit 130fc8
Packit 130fc8
Making asynchronous calls
Packit 130fc8
-------------------------
Packit 130fc8
Packit 130fc8
To make a call asynchronous, pass two callables as keyword arguments
Packit 130fc8
``reply_handler`` and ``error_handler`` to the proxy method. The proxy
Packit 130fc8
method will immediately return `None`. At some later time, when the event
Packit 130fc8
loop is running, one of these will happen: either
Packit 130fc8
Packit 130fc8
* the ``reply_handler`` will be called with the method's return values
Packit 130fc8
  as arguments; or
Packit 130fc8
Packit 130fc8
* the ``error_handler`` will be called with one argument, an instance of
Packit 130fc8
  ``DBusException`` representing a remote exception.
Packit 130fc8
Packit 130fc8
See also
Packit 130fc8
~~~~~~~~
Packit 130fc8
Packit 130fc8
``examples/example-async-client.py`` makes asynchronous method calls to
Packit 130fc8
the service provided by ``examples/example-service.py`` which return
Packit 130fc8
either a value or an exception. As for ``examples/example-client.py``,
Packit 130fc8
you need to run ``examples/example-service.py`` in the background or
Packit 130fc8
in another shell first.
Packit 130fc8
Packit 130fc8
.. --------------------------------------------------------------------
Packit 130fc8
Packit 130fc8
Receiving signals
Packit 130fc8
=================
Packit 130fc8
Packit 130fc8
To receive signals, the Bus needs to be connected to an event loop - see
Packit 130fc8
section `Setting up an event loop`_. Signals will only be received while
Packit 130fc8
the event loop is running.
Packit 130fc8
Packit 130fc8
Signal matching
Packit 130fc8
---------------
Packit 130fc8
Packit 130fc8
To respond to signals, you can use the ``add_signal_receiver`` method on
Packit 130fc8
`Bus objects`_. This arranges for a callback to be called when a
Packit 130fc8
matching signal is received, and has the following arguments:
Packit 130fc8
Packit 130fc8
* a callable (the ``handler_function``) which will be called by the event loop
Packit 130fc8
  when the signal is received - its parameters will be the arguments of
Packit 130fc8
  the signal
Packit 130fc8
Packit 130fc8
* the signal name, ``signal_name``: here None (the default) matches all names
Packit 130fc8
Packit 130fc8
* the D-Bus interface, ``dbus_interface``: again None is the default,
Packit 130fc8
  and matches all interfaces
Packit 130fc8
Packit 130fc8
* a sender bus name (well-known or unique), ``bus_name``: None is again
Packit 130fc8
  the default, and matches all senders. Well-known names match signals
Packit 130fc8
  from whatever application is currently the primary owner of that
Packit 130fc8
  well-known name.
Packit 130fc8
Packit 130fc8
* a sender object path, ``path``: once again None is the default and
Packit 130fc8
  matches all object paths
Packit 130fc8
Packit 130fc8
``add_signal_receiver`` also has keyword arguments ``utf8_strings`` and
Packit 130fc8
``byte_arrays`` which influence the types used when calling the
Packit 130fc8
handler function, in the same way as the `byte_arrays and utf8_strings`_
Packit 130fc8
options on proxy methods.
Packit 130fc8
Packit 130fc8
``add_signal_receiver`` returns a ``SignalMatch`` object. Its only
Packit 130fc8
useful public API at the moment is a ``remove`` method with no
Packit 130fc8
arguments, which removes the signal match from the connection.
Packit 130fc8
Packit 130fc8
Getting more information from a signal
Packit 130fc8
--------------------------------------
Packit 130fc8
Packit 130fc8
You can also arrange for more information to be passed to the handler
Packit 130fc8
function. If you pass the keyword arguments ``sender_keyword``,
Packit 130fc8
``destination_keyword``, ``interface_keyword``, ``member_keyword`` or
Packit 130fc8
``path_keyword`` to the ``connect_to_signal`` method, the appropriate
Packit 130fc8
part of the signal message will be passed to the handler function as a
Packit 130fc8
keyword argument: for instance if you use ::
Packit 130fc8
Packit 130fc8
    def handler(sender=None):
Packit 130fc8
        print "got signal from %r" % sender
Packit 130fc8
Packit 130fc8
    iface.connect_to_signal("Hello", handler, sender_keyword='sender')
Packit 130fc8
Packit 130fc8
and a signal ``Hello`` with no arguments is received from
Packit 130fc8
``com.example.Foo``, the ``handler`` function will be called with
Packit 130fc8
``sender='com.example.Foo'``.
Packit 130fc8
Packit 130fc8
String argument matching
Packit 130fc8
------------------------
Packit 130fc8
Packit 130fc8
If there are keyword parameters for the form ``arg``\ *n* where n is a
Packit 130fc8
small non-negative number, their values must be ``unicode`` objects
Packit 130fc8
or UTF-8 strings. The handler will only be called if that argument
Packit 130fc8
of the signal (numbered from zero) is a D-Bus string (in particular,
Packit 130fc8
not an object-path or a signature) with that value.
Packit 130fc8
Packit 130fc8
.. *this comment is to stop the above breaking vim syntax highlighting*
Packit 130fc8
Packit 130fc8
Receiving signals from a proxy object
Packit 130fc8
-------------------------------------
Packit 130fc8
Packit 130fc8
`Proxy objects`_ have a special method ``connect_to_signal`` which
Packit 130fc8
arranges for a callback to be called when a signal is received
Packit 130fc8
from the corresponding remote object. The parameters are:
Packit 130fc8
Packit 130fc8
* the name of the signal
Packit 130fc8
Packit 130fc8
* a callable (the handler function) which will be called by the event loop
Packit 130fc8
  when the signal is received - its parameters will be the arguments of
Packit 130fc8
  the signal
Packit 130fc8
Packit 130fc8
* the handler function, a callable: the same as for ``add_signal_receiver``
Packit 130fc8
Packit 130fc8
* the keyword argument ``dbus_interface`` qualifies the name with its
Packit 130fc8
  interface
Packit 130fc8
Packit 130fc8
`dbus.Interface` objects have a similar ``connect_to_signal`` method,
Packit 130fc8
but in this case you don't need the ``dbus_interface`` keyword argument
Packit 130fc8
since the interface to use is already known.
Packit 130fc8
Packit 130fc8
The same extra keyword arguments as for ``add_signal_receiver`` are also
Packit 130fc8
available, and just like ``add_signal_receiver``, it returns a
Packit 130fc8
SignalMatch.
Packit 130fc8
Packit 130fc8
You shouldn't use proxy objects just to listen to signals, since they
Packit 130fc8
might activate the relevant service when created, but if you already have a
Packit 130fc8
proxy object in order to call methods, it's often convenient to use it to add
Packit 130fc8
signal matches too.
Packit 130fc8
Packit 130fc8
See also
Packit 130fc8
--------
Packit 130fc8
Packit 130fc8
``examples/signal-recipient.py`` receives signals - it demonstrates
Packit 130fc8
general signal matching as well as ``connect_to_signal``. Before running it,
Packit 130fc8
you'll need to run ``examples/signal-emitter.py`` in the background or
Packit 130fc8
in another shell.
Packit 130fc8
Packit 130fc8
.. _BusName:
Packit 130fc8
Packit 130fc8
.. --------------------------------------------------------------------
Packit 130fc8
Packit 130fc8
Claiming a bus name
Packit 130fc8
===================
Packit 130fc8
Packit 130fc8
FIXME describe `BusName`_ - perhaps fix its API first?
Packit 130fc8
Packit 130fc8
The unique-instance idiom
Packit 130fc8
-------------------------
Packit 130fc8
Packit 130fc8
FIXME provide exemplary code, put it in examples
Packit 130fc8
Packit 130fc8
.. _exported object:
Packit 130fc8
.. _exported objects:
Packit 130fc8
Packit 130fc8
.. --------------------------------------------------------------------
Packit 130fc8
Packit 130fc8
Exporting objects
Packit 130fc8
=================
Packit 130fc8
Packit 130fc8
Objects made available to other applications over D-Bus are said to be
Packit 130fc8
*exported*. All subclasses of ``dbus.service.Object`` are automatically
Packit 130fc8
exported.
Packit 130fc8
Packit 130fc8
To export objects, the Bus needs to be connected to an event loop - see
Packit 130fc8
section `Setting up an event loop`_. Exported methods will only be called,
Packit 130fc8
and queued signals will only be sent, while the event loop is running.
Packit 130fc8
Packit 130fc8
.. _dbus.service.Object:
Packit 130fc8
Packit 130fc8
Inheriting from ``dbus.service.Object``
Packit 130fc8
---------------------------------------
Packit 130fc8
Packit 130fc8
To export an object onto the Bus, just subclass
Packit 130fc8
``dbus.service.Object``. Object expects either a `BusName`_ or a `Bus
Packit 130fc8
object`_, and an object-path, to be passed to its constructor: arrange
Packit 130fc8
for this information to be available. For example::
Packit 130fc8
Packit 130fc8
    class Example(dbus.service.Object):
Packit 130fc8
        def __init__(self, object_path):
Packit 130fc8
            dbus.service.Object.__init__(self, dbus.SessionBus(), path)
Packit 130fc8
Packit 130fc8
This object will automatically support introspection, but won't do
Packit 130fc8
anything particularly interesting. To fix that, you'll need to export some
Packit 130fc8
methods and signals too.
Packit 130fc8
Packit 130fc8
FIXME also mention dbus.gobject.ExportedGObject once I've written it
Packit 130fc8
Packit 130fc8
Exporting methods with ``dbus.service.method``
Packit 130fc8
----------------------------------------------
Packit 130fc8
Packit 130fc8
To export a method, use the decorator ``dbus.service.method``. For
Packit 130fc8
example::
Packit 130fc8
Packit 130fc8
    class Example(dbus.service.Object):
Packit 130fc8
        def __init__(self, object_path):
Packit 130fc8
            dbus.service.Object.__init__(self, dbus.SessionBus(), path)
Packit 130fc8
Packit 130fc8
        @dbus.service.method(dbus_interface='com.example.Sample',
Packit 130fc8
                             in_signature='v', out_signature='s')
Packit 130fc8
        def StringifyVariant(self, variant):
Packit 130fc8
            return str(variant)
Packit 130fc8
Packit 130fc8
The ``in_signature`` and ``out_signature`` are D-Bus signature strings
Packit 130fc8
as described in `Data Types`_.
Packit 130fc8
Packit 130fc8
As well as the keywords shown, you can pass ``utf8_strings`` and
Packit 130fc8
``byte_arrays`` keyword arguments, which influence the types which will
Packit 130fc8
be passed to the decorated method when it's called via D-Bus, in the
Packit 130fc8
same way that the `byte_arrays and utf8_strings`_ options affect the
Packit 130fc8
return value of a proxy method.
Packit 130fc8
Packit 130fc8
You can find a simple example in ``examples/example-service.py``, which
Packit 130fc8
we used earlier to demonstrate ``examples/example-client.py``.
Packit 130fc8
Packit 130fc8
Finding out the caller's bus name
Packit 130fc8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
The ``method`` decorator accepts a ``sender_keyword`` keyword argument.
Packit 130fc8
If you set that to a string, the unique bus name of the sender will be
Packit 130fc8
passed to the decorated method as a keyword argument of that name::
Packit 130fc8
Packit 130fc8
    class Example(dbus.service.Object):
Packit 130fc8
        def __init__(self, object_path):
Packit 130fc8
            dbus.service.Object.__init__(self, dbus.SessionBus(), path)
Packit 130fc8
Packit 130fc8
        @dbus.service.method(dbus_interface='com.example.Sample',
Packit 130fc8
                             in_signature='', out_signature='s',
Packit 130fc8
                             sender_keyword='sender')
Packit 130fc8
        def SayHello(self, sender=None):
Packit 130fc8
            return 'Hello, %s!' % sender
Packit 130fc8
            # -> something like 'Hello, :1.1!'
Packit 130fc8
Packit 130fc8
Asynchronous method implementations
Packit 130fc8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packit 130fc8
Packit 130fc8
FIXME and also add an example, perhaps examples/example-async-service.py
Packit 130fc8
Packit 130fc8
Emitting signals with ``dbus.service.signal``
Packit 130fc8
---------------------------------------------
Packit 130fc8
Packit 130fc8
To export a signal, use the decorator ``dbus.service.signal``; to emit
Packit 130fc8
that signal, call the decorated method. The decorated method can also
Packit 130fc8
contain code which will be run when called, as usual. For example::
Packit 130fc8
Packit 130fc8
    class Example(dbus.service.Object):
Packit 130fc8
        def __init__(self, object_path):
Packit 130fc8
            dbus.service.Object.__init__(self, dbus.SessionBus(), path)
Packit 130fc8
Packit 130fc8
        @dbus.service.signal(dbus_interface='com.example.Sample',
Packit 130fc8
                             signature='us')
Packit 130fc8
        def NumberOfBottlesChanged(self, number, contents):
Packit 130fc8
            print "%d bottles of %s on the wall" % (number, contents)
Packit 130fc8
Packit 130fc8
    e = Example('/bottle-counter')
Packit 130fc8
    e.NumberOfBottlesChanged(100, 'beer')
Packit 130fc8
    # -> emits com.example.Sample.NumberOfBottlesChanged(100, 'beer')
Packit 130fc8
    #    and prints "100 bottles of beer on the wall"
Packit 130fc8
Packit 130fc8
The signal will be queued for sending when the decorated method returns -
Packit 130fc8
you can prevent the signal from being sent by raising an exception
Packit 130fc8
from the decorated method (for instance, if the parameters are
Packit 130fc8
inappropriate). The signal will only actually be sent when the event loop
Packit 130fc8
next runs.
Packit 130fc8
Packit 130fc8
Example
Packit 130fc8
~~~~~~~
Packit 130fc8
Packit 130fc8
``examples/example-signal-emitter.py`` emits some signals on demand when
Packit 130fc8
one of its methods is called. (In reality, you'd emit a signal when some
Packit 130fc8
sort of internal state changed, which may or may not be triggered by a
Packit 130fc8
D-Bus method call.)
Packit 130fc8
Packit 130fc8
.. --------------------------------------------------------------------
Packit 130fc8
Packit 130fc8
License for this document
Packit 130fc8
=========================
Packit 130fc8
Packit 130fc8
Copyright 2006-2007 `Collabora Ltd.`_
Packit 130fc8
Packit 130fc8
Permission is hereby granted, free of charge, to any person
Packit 130fc8
obtaining a copy of this software and associated documentation
Packit 130fc8
files (the "Software"), to deal in the Software without
Packit 130fc8
restriction, including without limitation the rights to use, copy,
Packit 130fc8
modify, merge, publish, distribute, sublicense, and/or sell copies
Packit 130fc8
of the Software, and to permit persons to whom the Software is
Packit 130fc8
furnished to do so, subject to the following conditions:
Packit 130fc8
Packit 130fc8
The above copyright notice and this permission notice shall be
Packit 130fc8
included in all copies or substantial portions of the Software.
Packit 130fc8
Packit 130fc8
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 130fc8
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 130fc8
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 130fc8
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
Packit 130fc8
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
Packit 130fc8
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Packit 130fc8
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Packit 130fc8
DEALINGS IN THE SOFTWARE.
Packit 130fc8
Packit 130fc8
..
Packit 130fc8
  vim:set ft=rst sw=4 sts=4 et tw=72: