dbus.bus: In watch_name_owner, only watch the desired name!
[dbus-python-phuang.git] / doc / tutorial.txt
blobc0b73cbfac7bdadc0175d8e57f9cbf3172eb241c
1 ====================
2 dbus-python tutorial
3 ====================
5 :Author: Simon McVittie, `Collabora Ltd.`_
6 :Date: 2006-01-16
8 .. _`Collabora Ltd.`: http://www.collabora.co.uk/
10 This tutorial requires Python 2.4 or up, and ``dbus-python`` 0.80rc4 or up.
12 .. contents::
14 .. --------------------------------------------------------------------
16 .. _Bus object:
17 .. _Bus objects:
19 Connecting to the Bus
20 =====================
22 Applications that use D-Bus typically connect to a *bus daemon*, which
23 forwards messages between the applications. To use D-Bus, you need to create a
24 ``Bus`` object representing the connection to the bus daemon.
26 There are generally two bus daemons you may be interested in. Each user
27 login session should have a *session bus*, which is local to that
28 session. It's used to communicate between desktop applications. Connect
29 to the session bus by creating a ``SessionBus`` object::
31     import dbus
33     session_bus = dbus.SessionBus()
35 The *system bus* is global and usually started during boot; it's used to
36 communicate with system services like udev_, NetworkManager_, and the
37 `Hardware Abstraction Layer daemon (hald)`_. To connect to the system
38 bus, create a ``SystemBus`` object::
40     import dbus
42     system_bus = dbus.SystemBus()
44 Of course, you can connect to both in the same application.
46 For special purposes, you might use a non-default Bus, or a connection
47 which isn't a Bus at all, using some new API added in dbus-python 0.81.0.
48 This is not described here, and will at some stage be the subject of a separate
49 tutorial.
51 .. _udev:
52     http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
53 .. _NetworkManager:
54     http://www.gnome.org/projects/NetworkManager/
55 .. _Hardware Abstraction Layer daemon (hald):
56     http://www.freedesktop.org/wiki/Software/hal
58 .. --------------------------------------------------------------------
60 Making method calls
61 ===================
63 D-Bus applications can export objects for other applications' use. To
64 start working with an object in another application, you need to know:
66 * The *bus name*. This identifies which application you want to
67   communicate with. You'll usually identify applications by a
68   *well-known name*, which is a dot-separated string starting with a
69   reversed domain name, such as ``org.freedesktop.NetworkManager``
70   or ``com.example.WordProcessor``.
72 * The *object path*. Applications can export many objects - for
73   instance, example.com's word processor might provide an object
74   representing the word processor application itself and an object for
75   each document window opened, or it might also provide an object for
76   each paragraph within a document.
77   
78   To identify which one you want to interact with, you use an object path,
79   a slash-separated string resembling a filename. For instance, example.com's
80   word processor might provide an object at ``/`` representing the word
81   processor itself, and objects at ``/documents/123`` and
82   ``/documents/345`` representing opened document windows.
84 As you'd expect, one of the main things you can do with remote objects
85 is to call their methods. As in Python, methods may have parameters,
86 and they may return one or more values.
88 .. _proxy object:
90 Proxy objects
91 -------------
93 To interact with a remote object, you use a *proxy object*. This is a
94 Python object which acts as a proxy or "stand-in" for the remote object -
95 when you call a method on a proxy object, this causes dbus-python to make
96 a method call on the remote object, passing back any return values from
97 the remote object's method as the return values of the proxy method call.
99 To obtain a proxy object, call the ``get_object`` method on the ``Bus``.
100 For example, NetworkManager_ has the well-known name
101 ``org.freedesktop.NetworkManager`` and exports an object whose object
102 path is ``/org/freedesktop/NetworkManager``, plus an object per network
103 interface at object paths like
104 ``/org/freedesktop/NetworkManager/Devices/eth0``. You can get a proxy
105 for the object representing eth0 like this::
107     >>> import dbus
108     >>> bus = dbus.SystemBus()
109     >>> bus.get_object('org.freedesktop.NetworkManager',
110     ...                '/org/freedesktop/NetworkManager/Devices/eth0')
111     <ProxyObject wrapping <dbus.Bus on SYSTEM at 0x3007e150>
112     org.freedesktop.NetworkManager
113     /org/freedesktop/NetworkManager/Devices/eth0 at 0x301f0ad0>
114     >>>
116 Interfaces and methods
117 ----------------------
119 D-Bus uses *interfaces* to provide a namespacing mechanism for methods.
120 An interface is a group of related methods and signals (more on signals
121 later), identified by a name which is a series of dot-separated components
122 starting with a reversed domain name. For instance, each NetworkManager_
123 object representing a network interface implements the interface
124 ``org.freedesktop.NetworkManager.Devices``, which has methods like
125 ``getProperties``.
127 To call a method, call the method of the same name on the proxy object,
128 passing in the interface name via the ``dbus_interface`` keyword argument::
130     >>> import dbus
131     >>> bus = dbus.SystemBus()
132     >>> eth0 = bus.get_object('org.freedesktop.NetworkManager',
133     ...                       '/org/freedesktop/NetworkManager/Devices/eth0')
134     >>> eth0.getProperties(dbus_interface='org.freedesktop.NetworkManager.Devices')
135     (dbus.ObjectPath('/org/freedesktop/NetworkManager/Devices/eth0'), [...])
136     >>>
138 (I've truncated the list of properties here.)
140 .. _dbus.Interface:
142 As a short cut, if you're going to be calling many methods with the same
143 interface, you can construct a ``dbus.Interface`` object and call
144 methods on that, without needing to specify the interface again::
146     >>> import dbus
147     >>> bus = dbus.SystemBus()
148     >>> eth0 = bus.get_object('org.freedesktop.NetworkManager',
149     ...                       '/org/freedesktop/NetworkManager/Devices/eth0')
150     >>> eth0_dev_iface = dbus.Interface(eth0,
151     ...     dbus_interface='org.freedesktop.NetworkManager.Devices')
152     >>> eth0_dev_iface.getProperties()
153     (dbus.ObjectPath('/org/freedesktop/NetworkManager/Devices/eth0'), [...])
154     >>>
156 See also
157 ~~~~~~~~
159 See the example in ``examples/example-client.py``. Before running it,
160 you'll need to run ``examples/example-service.py`` in the background or
161 in another shell.
163 Data types
164 ----------
166 Unlike Python, D-Bus is statically typed - each method has a certain
167 *signature* representing the types of its arguments, and will not accept
168 arguments of other types.
170 D-Bus has an introspection mechanism, which ``dbus-python`` tries to use
171 to discover the correct argument types. If this succeeds, Python types
172 are converted into the right D-Bus data types automatically, if possible;
173 ``TypeError`` is raised if the type is inappropriate.
175 If the introspection mechanism fails (or the argument's type is
176 variant - see below), you have to provide arguments of
177 the correct type. ``dbus-python`` provides Python types corresponding to
178 the D-Bus data types, and a few native Python types are also converted to
179 D-Bus data types automatically. If you use a type which isn't among these,
180 a ``TypeError`` will be raised telling you that ``dbus-python`` was
181 unable to guess the D-Bus signature.
183 Basic types
184 ~~~~~~~~~~~
186 The following basic data types are supported.
188 ==========================  =============================  =====
189 Python type                 converted to D-Bus type        notes
190 ==========================  =============================  =====
191 D-Bus `proxy object`_       ObjectPath (signature 'o')     `(+)`_
192 `dbus.Interface`_           ObjectPath (signature 'o')     `(+)`_
193 `dbus.service.Object`_      ObjectPath (signature 'o')     `(+)`_
194 ``dbus.Boolean``            Boolean (signature 'b')        a subclass of ``int``
195 ``dbus.Byte``               byte (signature 'y')           a subclass of ``int``
196 ``dbus.Int16``              16-bit signed integer ('n')    a subclass of ``int``
197 ``dbus.Int32``              32-bit signed integer ('i')    a subclass of ``int``
198 ``dbus.Int64``              64-bit signed integer ('x')    `(*)`_
199 ``dbus.UInt16``             16-bit unsigned integer ('q')  a subclass of ``int``
200 ``dbus.UInt32``             32-bit unsigned integer ('u')  `(*)_`
201 ``dbus.UInt64``             64-bit unsigned integer ('t')  `(*)_`
202 ``dbus.Double``             double-precision float ('d')   a subclass of ``float``
203 ``dbus.ObjectPath``         object path ('o')              a subclass of ``str``
204 ``dbus.Signature``          signature ('g')                a subclass of ``str``
205 ``dbus.String``             string ('s')                   a subclass of 
206                                                            ``unicode``
207 ``dbus.UTF8String``         string ('s')                   a subclass of ``str``
208 ``bool``                    Boolean ('b')
209 ``int`` or subclass         32-bit signed integer ('i')
210 ``long`` or subclass        64-bit signed integer ('x')
211 ``float`` or subclass       double-precision float ('d')
212 ``str`` or subclass         string ('s')                   must be valid UTF-8
213 ``unicode`` or subclass     string ('s')
214 ==========================  =============================  =====
216 .. _(*):
218 Types marked (*) may be a subclass of either ``int`` or ``long``, depending
219 on platform.
221 .. _(+):
223 (+): D-Bus proxy objects, exported D-Bus service objects and anything
224 else with the special attribute ``__dbus_object_path__``, which
225 must be a string, are converted to their object-path. This might be
226 useful if you're writing an object-oriented API using dbus-python.
228 Basic type conversions
229 ~~~~~~~~~~~~~~~~~~~~~~
231 If introspection succeeded, ``dbus-python`` will also accept:
233 * for Boolean parameters, any object (converted as if via ``int(bool(...))``)
234 * for byte parameters, a single-character string (converted as if via ``ord()``)
235 * for byte and integer parameters, any integer (must be in the correct range)
236 * for object-path and signature parameters, any ``str`` or ``unicode``
237   subclass (the value must follow the appropriate syntax)
239 Container types
240 ~~~~~~~~~~~~~~~
242 D-Bus supports four container types: array (a variable-length sequence of the
243 same type), struct (a fixed-length sequence whose members may have
244 different types), dictionary (a mapping from values of the same basic type to
245 values of the same type), and variant (a container which may hold any
246 D-Bus type, including another variant).
248 Arrays are represented by Python lists, or by ``dbus.Array``, a subclass
249 of ``list``. When sending an array, if an introspected signature is
250 available, that will be used; otherwise, if the ``signature`` keyword
251 parameter was passed to the ``Array`` constructor, that will be used to
252 determine the contents' signature; otherwise, ``dbus-python`` will guess
253 from the array's first item.
255 The signature of an array is 'ax' where 'x' represents the signature of
256 one item. For instance, you could also have 'as' (array of strings) or
257 'a(ii)' (array of structs each containing two 32-bit integers).
259 There's also a type ``dbus.ByteArray`` which is a subclass of ``str``,
260 used as a more efficient representation of a D-Bus array of bytes
261 (signature 'ay').
263 Structs are represented by Python tuples, or by ``dbus.Struct``, a
264 subclass of ``tuple``. When sending a struct, if an introspected signature is
265 available, that will be used; otherwise, if the ``signature`` keyword
266 parameter was passed to the ``Array`` constructor, that will be used to
267 determine the contents' signature; otherwise, ``dbus-python`` will guess
268 from the array's first item.
270 The signature of a struct consists of the signatures of the contents,
271 in parentheses - for instance '(is)' is the signature of a struct
272 containing a 32-bit integer and a string.
274 Dictionaries are represented by Python dictionaries, or by
275 ``dbus.Dictionary``, a subclass of ``dict``. When sending a dictionary,
276 if an introspected signature is available, that will be used; otherwise,
277 if the ``signature`` keyword parameter was passed to the ``Dictionary``
278 constructor, that will be used to determine the contents' key and value
279 signatures; otherwise, ``dbus-python`` will guess from an arbitrary item
280 of the ``dict``.
282 The signature of a dictionary is 'a{xy}' where 'x' represents the
283 signature of the keys (which may not be a container type) and 'y'
284 represents the signature of the values. For instance,
285 'a{s(ii)}' is a dictionary where the keys are strings and the values are
286 structs containing two 32-bit integers.
288 Variants are represented by setting the ``variant_level`` keyword
289 argument in the constructor of any D-Bus data type to a value greater
290 than 0 (``variant_level`` 1 means a variant containing some other data type,
291 ``variant_level`` 2 means a variant containing a variant containing some
292 other data type, and so on). If a non-variant is passed as an argument
293 but introspection indicates that a variant is expected, it'll
294 automatically be wrapped in a variant.
296 The signature of a variant is 'v'.
298 .. _byte_arrays and utf8_strings:
300 Return values, and the ``byte_arrays`` and ``utf8_strings`` options
301 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
303 If a D-Bus method returns no value, the Python proxy method will return
304 ``None``.
306 If a D-Bus method returns one value, the Python proxy method will return
307 that value as one of the ``dbus.`` types - by default, strings are
308 returned as ``dbus.String`` (a subclass of Unicode) and byte arrays are
309 returned as a ``dbus.Array`` of ``dbus.Byte``.
311 If a D-Bus method returns multiple values, the Python proxy method
312 will return a tuple containing those values.
314 If you want strings returned as ``dbus.UTF8String`` (a subclass of
315 ``str``) pass the keyword parameter ``utf8_strings=True`` to the proxy
316 method.
318 If you want byte arrays returned as ``dbus.ByteArray`` (also a
319 subclass of ``str`` - in practice, this is often what you want) pass
320 the keyword parameter ``byte_arrays=True`` to the proxy method.
322 .. --------------------------------------------------------------------
324 Making asynchronous method calls
325 ================================
327 Asynchronous (non-blocking) method calls allow multiple method calls to
328 be in progress simultaneously, and allow your application to do other
329 work while it's waiting for the results. To make asynchronous calls,
330 you first need an event loop or "main loop".
332 Setting up an event loop
333 ------------------------
335 Currently, the only main loop supported by ``dbus-python`` is GLib.
337 ``dbus-python`` has a global default main loop, which is the easiest way
338 to use this functionality. To arrange for the GLib main loop to be the
339 default, use::
341     from dbus.mainloop.glib import DBusGMainLoop
343     DBusGMainLoop(set_as_default=True)
345 You must do this before `connecting to the bus`_.
347 Actually starting the main loop is as usual for ``pygobject``::
349     import gobject
351     loop = gobject.MainLoop()
352     loop.run()
354 While ``loop.run()`` is executing, GLib will run your callbacks when
355 appropriate. To stop, call ``loop.quit()``.
357 You can also set a main loop on a per-connection basis, by passing a
358 main loop to the Bus constructor::
360     import dbus
361     from dbus.mainloop.glib import DBusGMainLoop
363     dbus_loop = DBusGMainLoop()
365     bus = dbus.SessionBus(mainloop=dbus_loop)
367 This isn't very useful until we support more than one main loop, though.
369 Backwards compatibility: ``dbus.glib``
370 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
372 In versions of ``dbus-python`` prior to 0.80, the way to set GLib as the
373 default main loop was::
375     import dbus.glib
377 Executing that import statement would automatically load the GLib main
378 loop and make this the default. This is now deprecated, since it's
379 highly non-obvious, but may be useful if you want to write or understand
380 backwards-compatible code.
382 The Qt main loop
383 ~~~~~~~~~~~~~~~~
385 FIXME: describe how to use the Qt event loop too (requires recent pyqt)
387 Making asynchronous calls
388 -------------------------
390 To make a call asynchronous, pass two callables as keyword arguments
391 ``reply_handler`` and ``error_handler`` to the proxy method. The proxy
392 method will immediately return `None`. At some later time, when the event
393 loop is running, one of these will happen: either
395 * the ``reply_handler`` will be called with the method's return values
396   as arguments; or
398 * the ``error_handler`` will be called with one argument, an instance of
399   ``DBusException`` representing a remote exception.
401 See also
402 ~~~~~~~~
404 ``examples/example-async-client.py`` makes asynchronous method calls to
405 the service provided by ``examples/example-service.py`` which return
406 either a value or an exception. As for ``examples/example-client.py``,
407 you need to run ``examples/example-service.py`` in the background or
408 in another shell first.
410 .. --------------------------------------------------------------------
412 Receiving signals
413 =================
415 To receive signals, the Bus needs to be connected to an event loop - see
416 section `Setting up an event loop`_. Signals will only be received while
417 the event loop is running.
419 Signal matching
420 ---------------
422 To respond to signals, you can use the ``add_signal_receiver`` method on
423 `Bus objects`_. This arranges for a callback to be called when a
424 matching signal is received, and has the following arguments:
426 * a callable (the ``handler_function``) which will be called by the event loop
427   when the signal is received - its parameters will be the arguments of
428   the signal
430 * the signal name, ``signal_name``: here None (the default) matches all names
432 * the D-Bus interface, ``dbus_interface``: again None is the default,
433   and matches all interfaces
435 * a sender bus name (well-known or unique), ``bus_name``: None is again
436   the default, and matches all senders. Well-known names match signals
437   from whatever application is currently the primary owner of that
438   well-known name.
440 * a sender object path, ``path``: once again None is the default and
441   matches all object paths
443 ``add_signal_receiver`` also has keyword arguments ``utf8_strings`` and
444 ``byte_arrays`` which influence the types used when calling the
445 handler function, in the same way as the `byte_arrays and utf8_strings`_
446 options on proxy methods.
448 ``add_signal_receiver`` returns a ``SignalMatch`` object. Its only
449 useful public API at the moment is a ``remove`` method with no
450 arguments, which removes the signal match from the connection.
452 Getting more information from a signal
453 --------------------------------------
455 You can also arrange for more information to be passed to the handler
456 function. If you pass the keyword arguments ``sender_keyword``,
457 ``destination_keyword``, ``interface_keyword``, ``member_keyword`` or
458 ``path_keyword`` to the ``connect_to_signal`` method, the appropriate
459 part of the signal message will be passed to the handler function as a
460 keyword argument: for instance if you use ::
462     def handler(sender=None):
463         print "got signal from %r" % sender
465     iface.connect_to_signal("Hello", handler, sender_keyword='sender')
467 and a signal ``Hello`` with no arguments is received from
468 ``com.example.Foo``, the ``handler`` function will be called with
469 ``sender='com.example.Foo'``.
471 String argument matching
472 ------------------------
474 If there are keyword parameters for the form ``arg``\ *n* where n is a
475 small non-negative number, their values must be ``unicode`` objects
476 or UTF-8 strings. The handler will only be called if that argument
477 of the signal (numbered from zero) is a D-Bus string (in particular,
478 not an object-path or a signature) with that value.
480 .. *this comment is to stop the above breaking vim syntax highlighting*
482 Receiving signals from a proxy object
483 -------------------------------------
485 `Proxy objects`_ have a special method ``connect_to_signal`` which
486 arranges for a callback to be called when a signal is received
487 from the corresponding remote object. The parameters are:
489 * the name of the signal
491 * a callable (the handler function) which will be called by the event loop
492   when the signal is received - its parameters will be the arguments of
493   the signal
495 * the handler function, a callable: the same as for ``add_signal_receiver``
497 * the keyword argument ``dbus_interface`` qualifies the name with its
498   interface
500 `dbus.Interface` objects have a similar ``connect_to_signal`` method,
501 but in this case you don't need the ``dbus_interface`` keyword argument
502 since the interface to use is already known.
504 The same extra keyword arguments as for ``add_signal_receiver`` are also
505 available, and just like ``add_signal_receiver``, it returns a
506 SignalMatch.
508 You shouldn't use proxy objects just to listen to signals, since they
509 might activate the relevant service when created, but if you already have a
510 proxy object in order to call methods, it's often convenient to use it to add
511 signal matches too.
513 See also
514 --------
516 ``examples/signal-recipient.py`` receives signals - it demonstrates
517 general signal matching as well as ``connect_to_signal``. Before running it,
518 you'll need to run ``examples/signal-emitter.py`` in the background or
519 in another shell.
521 .. _BusName:
523 .. --------------------------------------------------------------------
525 Claiming a bus name
526 ===================
528 FIXME describe `BusName`_ - perhaps fix its API first?
530 The unique-instance idiom
531 -------------------------
533 FIXME provide exemplary code, put it in examples
535 .. _exported object:
536 .. _exported objects:
538 .. --------------------------------------------------------------------
540 Exporting objects
541 =================
543 Objects made available to other applications over D-Bus are said to be
544 *exported*. All subclasses of ``dbus.service.Object`` are automatically
545 exported.
547 To export objects, the Bus needs to be connected to an event loop - see
548 section `Setting up an event loop`_. Exported methods will only be called,
549 and queued signals will only be sent, while the event loop is running.
551 .. _dbus.service.Object:
553 Inheriting from ``dbus.service.Object``
554 ---------------------------------------
556 To export an object onto the Bus, just subclass
557 ``dbus.service.Object``. Object expects either a `BusName`_ or a `Bus
558 object`_, and an object-path, to be passed to its constructor: arrange
559 for this information to be available. For example::
561     class Example(dbus.service.Object):
562         def __init__(self, object_path):
563             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
565 This object will automatically support introspection, but won't do
566 anything particularly interesting. To fix that, you'll need to export some
567 methods and signals too.
569 FIXME also mention dbus.gobject.ExportedGObject once I've written it
571 Exporting methods with ``dbus.service.method``
572 ----------------------------------------------
574 To export a method, use the decorator ``dbus.service.method``. For
575 example::
577     class Example(dbus.service.Object):
578         def __init__(self, object_path):
579             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
581         @dbus.service.method(interface='com.example.Sample',
582                              in_signature='v', out_signature='s')
583         def StringifyVariant(self, variant):
584             return str(variant)
586 The ``in_signature`` and ``out_signature`` are D-Bus signature strings
587 as described in `Data Types`_.
589 As well as the keywords shown, you can pass ``utf8_strings`` and
590 ``byte_arrays`` keyword arguments, which influence the types which will
591 be passed to the decorated method when it's called via D-Bus, in the
592 same way that the `byte_arrays and utf8_strings`_ options affect the
593 return value of a proxy method.
595 You can find a simple example in ``examples/example-service.py``, which
596 we used earlier to demonstrate ``examples/example-client.py``.
598 Finding out the caller's bus name
599 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
601 The ``method`` decorator accepts a ``sender_keyword`` keyword argument.
602 If you set that to a string, the unique bus name of the sender will be
603 passed to the decorated method as a keyword argument of that name::
605     class Example(dbus.service.Object):
606         def __init__(self, object_path):
607             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
609         @dbus.service.method(interface='com.example.Sample',
610                              in_signature='', out_signature='s',
611                              sender_keyword='sender')
612         def SayHello(self, sender=None):
613             return 'Hello, %s!' % sender
614             # -> something like 'Hello, :1.1!'
616 Asynchronous method implementations
617 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
619 FIXME and also add an example, perhaps examples/example-async-service.py
621 Emitting signals with ``dbus.service.signal``
622 ---------------------------------------------
624 To export a signal, use the decorator ``dbus.service.signal``; to emit
625 that signal, call the decorated method. The decorated method can also
626 contain code which will be run when called, as usual. For example::
628     class Example(dbus.service.Object):
629         def __init__(self, object_path):
630             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
632         @dbus.service.signal(interface='com.example.Sample',
633                              signature='us')
634         def NumberOfBottlesChanged(self, number, contents):
635             print "%d bottles of %s on the wall" % (number, contents)
637     e = Example('/bottle-counter')
638     e.NumberOfBottlesChanged(100, 'beer')
639     # -> emits com.example.Sample.NumberOfBottlesChanged(100, 'beer')
640     #    and prints "100 bottles of beer on the wall"
642 The signal will be queued for sending when the decorated method returns -
643 you can prevent the signal from being sent by raising an exception
644 from the decorated method (for instance, if the parameters are
645 inappropriate). The signal will only actually be sent when the event loop
646 next runs.
648 Example
649 ~~~~~~~
651 ``examples/example-signal-emitter.py`` emits some signals on demand when
652 one of its methods is called. (In reality, you'd emit a signal when some
653 sort of internal state changed, which may or may not be triggered by a
654 D-Bus method call.)
656 .. --------------------------------------------------------------------
658 License for this document
659 =========================
661 Copyright 2006-2007 `Collabora Ltd.`_
663 Licensed under the Academic Free License version 2.1
665 This document is free software; you can redistribute it and/or modify
666 it under the terms of the GNU Lesser General Public License as published by
667 the Free Software Foundation; either version 2.1 of the License, or
668 (at your option) any later version.
670 This document is distributed in the hope that it will be useful,
671 but WITHOUT ANY WARRANTY; without even the implied warranty of
672 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
673 GNU Lesser General Public License for more details.
675 You should have received a copy of the GNU Lesser General Public License
676 along with this document; if not, write to the Free Software
677 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
680   vim:set ft=rst sw=4 sts=4 et tw=72: