Update tutorial to describe add_signal_receiver before connect_to_signal.
[dbus-python-phuang.git] / doc / tutorial.txt
blobaa708327fc6f581f9065dd40f26521e6ab7b0c4f
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 the subject of a separate tutorial.
50 .. _udev:
51     http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
52 .. _NetworkManager:
53     http://www.gnome.org/projects/NetworkManager/
54 .. _Hardware Abstraction Layer daemon (hald):
55     http://www.freedesktop.org/wiki/Software/hal
57 .. --------------------------------------------------------------------
59 Making method calls
60 ===================
62 D-Bus applications can export objects for other applications' use. To
63 start working with an object in another application, you need to know:
65 * The *bus name*. This identifies which application you want to
66   communicate with. You'll usually identify applications by a
67   *well-known name*, which is a dot-separated string starting with a
68   reversed domain name, such as ``org.freedesktop.NetworkManager``
69   or ``com.example.WordProcessor``.
71 * The *object path*. Applications can export many objects - for
72   instance, example.com's word processor might provide an object
73   representing the word processor application itself and an object for
74   each document window opened, or it might also provide an object for
75   each paragraph within a document.
76   
77   To identify which one you want to interact with, you use an object path,
78   a slash-separated string resembling a filename. For instance, example.com's
79   word processor might provide an object at ``/`` representing the word
80   processor itself, and objects at ``/documents/123`` and
81   ``/documents/345`` representing opened document windows.
83 As you'd expect, one of the main things you can do with remote objects
84 is to call their methods. As in Python, methods may have parameters,
85 and they may return one or more values.
87 .. _proxy object:
89 Proxy objects
90 -------------
92 To interact with a remote object, you use a *proxy object*. This is a
93 Python object which acts as a proxy or "stand-in" for the remote object -
94 when you call a method on a proxy object, this causes dbus-python to make
95 a method call on the remote object, passing back any return values from
96 the remote object's method as the return values of the proxy method call.
98 To obtain a proxy object, call the ``get_object`` method on the ``Bus``.
99 For example, NetworkManager_ has the well-known name
100 ``org.freedesktop.NetworkManager`` and exports an object whose object
101 path is ``/org/freedesktop/NetworkManager``, plus an object per network
102 interface at object paths like
103 ``/org/freedesktop/NetworkManager/Devices/eth0``. You can get a proxy
104 for the object representing eth0 like this::
106     >>> import dbus
107     >>> bus = dbus.SystemBus()
108     >>> bus.get_object('org.freedesktop.NetworkManager',
109     ...                '/org/freedesktop/NetworkManager/Devices/eth0')
110     <ProxyObject wrapping <dbus.Bus on SYSTEM at 0x3007e150>
111     org.freedesktop.NetworkManager
112     /org/freedesktop/NetworkManager/Devices/eth0 at 0x301f0ad0>
113     >>>
115 Interfaces and methods
116 ----------------------
118 D-Bus uses *interfaces* to provide a namespacing mechanism for methods.
119 An interface is a group of related methods and signals (more on signals
120 later), identified by a name which is a series of dot-separated components
121 starting with a reversed domain name. For instance, each NetworkManager_
122 object representing a network interface implements the interface
123 ``org.freedesktop.NetworkManager.Devices``, which has methods like
124 ``getProperties``.
126 To call a method, call the method of the same name on the proxy object,
127 passing in the interface name via the ``dbus_interface`` keyword argument::
129     >>> import dbus
130     >>> bus = dbus.SystemBus()
131     >>> eth0 = bus.get_object('org.freedesktop.NetworkManager',
132     ...                       '/org/freedesktop/NetworkManager/Devices/eth0')
133     >>> eth0.getProperties(dbus_interface='org.freedesktop.NetworkManager.Devices')
134     (dbus.ObjectPath('/org/freedesktop/NetworkManager/Devices/eth0'), [...])
135     >>>
137 (I've truncated the list of properties here.)
139 .. _dbus.Interface:
141 As a short cut, if you're going to be calling many methods with the same
142 interface, you can construct a ``dbus.Interface`` object and call
143 methods on that, without needing to specify the interface again::
145     >>> import dbus
146     >>> bus = dbus.SystemBus()
147     >>> eth0 = bus.get_object('org.freedesktop.NetworkManager',
148     ...                       '/org/freedesktop/NetworkManager/Devices/eth0')
149     >>> eth0_dev_iface = dbus.Interface(eth0,
150     ...     dbus_interface='org.freedesktop.NetworkManager.Devices')
151     >>> eth0_dev_iface.getProperties()
152     (dbus.ObjectPath('/org/freedesktop/NetworkManager/Devices/eth0'), [...])
153     >>>
155 See also
156 ~~~~~~~~
158 See the example in ``examples/example-client.py``. Before running it,
159 you'll need to run ``examples/example-service.py`` in the background or
160 in another shell.
162 Data types
163 ----------
165 Unlike Python, D-Bus is statically typed - each method has a certain
166 *signature* representing the types of its arguments, and will not accept
167 arguments of other types.
169 D-Bus has an introspection mechanism, which ``dbus-python`` tries to use
170 to discover the correct argument types. If this succeeds, Python types
171 are converted into the right D-Bus data types automatically, if possible;
172 ``TypeError`` is raised if the type is inappropriate.
174 If the introspection mechanism fails (or the argument's type is
175 variant - see below), you have to provide arguments of
176 the correct type. ``dbus-python`` provides Python types corresponding to
177 the D-Bus data types, and a few native Python types are also converted to
178 D-Bus data types automatically. If you use a type which isn't among these,
179 a ``TypeError`` will be raised telling you that ``dbus-python`` was
180 unable to guess the D-Bus signature.
182 Basic types
183 ~~~~~~~~~~~
185 The following basic data types are supported.
187 ==========================  =============================  =====
188 Python type                 converted to D-Bus type        notes
189 ==========================  =============================  =====
190 D-Bus `proxy object`_       ObjectPath (signature 'o')     `(+)`_
191 `dbus.Interface`_           ObjectPath (signature 'o')     `(+)`_
192 `dbus.service.Object`_      ObjectPath (signature 'o')     `(+)`_
193 ``dbus.Boolean``            Boolean (signature 'b')        a subclass of ``int``
194 ``dbus.Byte``               byte (signature 'y')           a subclass of ``int``
195 ``dbus.Int16``              16-bit signed integer ('n')    a subclass of ``int``
196 ``dbus.Int32``              32-bit signed integer ('i')    a subclass of ``int``
197 ``dbus.Int64``              64-bit signed integer ('x')    `(*)`_
198 ``dbus.UInt16``             16-bit unsigned integer ('q')  a subclass of ``int``
199 ``dbus.UInt32``             32-bit unsigned integer ('u')  `(*)_`
200 ``dbus.UInt64``             64-bit unsigned integer ('t')  `(*)_`
201 ``dbus.Double``             double-precision float ('d')   a subclass of ``float``
202 ``dbus.ObjectPath``         object path ('o')              a subclass of ``str``
203 ``dbus.Signature``          signature ('g')                a subclass of ``str``
204 ``dbus.String``             string ('s')                   a subclass of 
205                                                            ``unicode``
206 ``dbus.UTF8String``         string ('s')                   a subclass of ``str``
207 ``bool``                    Boolean ('b')
208 ``int`` or subclass         32-bit signed integer ('i')
209 ``long`` or subclass        64-bit signed integer ('x')
210 ``float`` or subclass       double-precision float ('d')
211 ``str`` or subclass         string ('s')                   must be valid UTF-8
212 ``unicode`` or subclass     string ('s')
213 ==========================  =============================  =====
215 .. _(*):
217 Types marked (*) may be a subclass of either ``int`` or ``long``, depending
218 on platform.
220 .. _(+):
222 (+): D-Bus proxy objects, exported D-Bus service objects and anything
223 else with the special attribute ``__dbus_object_path__``, which
224 must be a string, are converted to their object-path. This might be
225 useful if you're writing an object-oriented API using dbus-python.
227 Basic type conversions
228 ~~~~~~~~~~~~~~~~~~~~~~
230 If introspection succeeded, ``dbus-python`` will also accept:
232 * for Boolean parameters, any object (converted as if via ``int(bool(...))``)
233 * for byte parameters, a single-character string (converted as if via ``ord()``)
234 * for byte and integer parameters, any integer (must be in the correct range)
235 * for object-path and signature parameters, any ``str`` or ``unicode``
236   subclass (the value must follow the appropriate syntax)
238 Container types
239 ~~~~~~~~~~~~~~~
241 D-Bus supports four container types: array (a variable-length sequence of the
242 same type), struct (a fixed-length sequence whose members may have
243 different types), dictionary (a mapping from values of the same basic type to
244 values of the same type), and variant (a container which may hold any
245 D-Bus type, including another variant).
247 Arrays are represented by Python lists, or by ``dbus.Array``, a subclass
248 of ``list``. When sending an array, if an introspected signature is
249 available, that will be used; otherwise, if the ``signature`` keyword
250 parameter was passed to the ``Array`` constructor, that will be used to
251 determine the contents' signature; otherwise, ``dbus-python`` will guess
252 from the array's first item.
254 The signature of an array is 'ax' where 'x' represents the signature of
255 one item. For instance, you could also have 'as' (array of strings) or
256 'a(ii)' (array of structs each containing two 32-bit integers).
258 There's also a type ``dbus.ByteArray`` which is a subclass of ``str``,
259 used as a more efficient representation of a D-Bus array of bytes
260 (signature 'ay').
262 Structs are represented by Python tuples, or by ``dbus.Struct``, a
263 subclass of ``tuple``. When sending a struct, if an introspected signature is
264 available, that will be used; otherwise, if the ``signature`` keyword
265 parameter was passed to the ``Array`` constructor, that will be used to
266 determine the contents' signature; otherwise, ``dbus-python`` will guess
267 from the array's first item.
269 The signature of a struct consists of the signatures of the contents,
270 in parentheses - for instance '(is)' is the signature of a struct
271 containing a 32-bit integer and a string.
273 Dictionaries are represented by Python dictionaries, or by
274 ``dbus.Dictionary``, a subclass of ``dict``. When sending a dictionary,
275 if an introspected signature is available, that will be used; otherwise,
276 if the ``signature`` keyword parameter was passed to the ``Dictionary``
277 constructor, that will be used to determine the contents' key and value
278 signatures; otherwise, ``dbus-python`` will guess from an arbitrary item
279 of the ``dict``.
281 The signature of a dictionary is 'a{xy}' where 'x' represents the
282 signature of the keys (which may not be a container type) and 'y'
283 represents the signature of the values. For instance,
284 'a{s(ii)}' is a dictionary where the keys are strings and the values are
285 structs containing two 32-bit integers.
287 Variants are represented by setting the ``variant_level`` keyword
288 argument in the constructor of any D-Bus data type to a value greater
289 than 0 (``variant_level`` 1 means a variant containing some other data type,
290 ``variant_level`` 2 means a variant containing a variant containing some
291 other data type, and so on). If a non-variant is passed as an argument
292 but introspection indicates that a variant is expected, it'll
293 automatically be wrapped in a variant.
295 The signature of a variant is 'v'.
297 .. _byte_arrays and utf8_strings:
299 Return values, and the ``byte_arrays`` and ``utf8_strings`` options
300 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
302 If a D-Bus method returns no value, the Python proxy method will return
303 ``None``.
305 If a D-Bus method returns one value, the Python proxy method will return
306 that value as one of the ``dbus.`` types - by default, strings are
307 returned as ``dbus.String`` (a subclass of Unicode) and byte arrays are
308 returned as a ``dbus.Array`` of ``dbus.Byte``.
310 If a D-Bus method returns multiple values, the Python proxy method
311 will return a tuple containing those values.
313 If you want strings returned as ``dbus.UTF8String`` (a subclass of
314 ``str``) pass the keyword parameter ``utf8_strings=True`` to the proxy
315 method.
317 If you want byte arrays returned as ``dbus.ByteArray`` (also a
318 subclass of ``str`` - in practice, this is often what you want) pass
319 the keyword parameter ``byte_arrays=True`` to the proxy method.
321 .. --------------------------------------------------------------------
323 Making asynchronous method calls
324 ================================
326 Asynchronous (non-blocking) method calls allow multiple method calls to
327 be in progress simultaneously, and allow your application to do other
328 work while it's waiting for the results. To make asynchronous calls,
329 you first need an event loop or "main loop".
331 Setting up an event loop
332 ------------------------
334 Currently, the only main loop supported by ``dbus-python`` is GLib.
336 ``dbus-python`` has a global default main loop, which is the easiest way
337 to use this functionality. To arrange for the GLib main loop to be the
338 default, use::
340     from dbus.mainloop.glib import DBusGMainLoop
342     DBusGMainLoop(set_as_default=True)
344 You must do this before `connecting to the bus`_.
346 Actually starting the main loop is as usual for ``pygobject``::
348     import gobject
350     loop = gobject.MainLoop()
351     loop.run()
353 While ``loop.run()`` is executing, GLib will run your callbacks when
354 appropriate. To stop, call ``loop.quit()``.
356 You can also set a main loop on a per-connection basis, by passing a
357 main loop to the Bus constructor::
359     import dbus
360     from dbus.mainloop.glib import DBusGMainLoop
362     dbus_loop = DBusGMainLoop()
364     bus = dbus.SessionBus(mainloop=dbus_loop)
366 This isn't very useful until we support more than one main loop, though.
368 Backwards compatibility: ``dbus.glib``
369 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
371 In versions of ``dbus-python`` prior to 0.80, the way to set GLib as the
372 default main loop was::
374     import dbus.glib
376 Executing that import statement would automatically load the GLib main
377 loop and make this the default. This is now deprecated, since it's
378 highly non-obvious, but may be useful if you want to write or understand
379 backwards-compatible code.
381 The Qt main loop
382 ~~~~~~~~~~~~~~~~
384 FIXME: describe how to use the Qt event loop too (requires recent pyqt)
386 Making asynchronous calls
387 -------------------------
389 To make a call asynchronous, pass two callables as keyword arguments
390 ``reply_handler`` and ``error_handler`` to the proxy method. The proxy
391 method will immediately return `None`. At some later time, when the event
392 loop is running, one of these will happen: either
394 * the ``reply_handler`` will be called with the method's return values
395   as arguments; or
397 * the ``error_handler`` will be called with one argument, an instance of
398   ``DBusException`` representing a remote exception.
400 See also
401 ~~~~~~~~
403 ``examples/example-async-client.py`` makes asynchronous method calls to
404 the service provided by ``examples/example-service.py`` which return
405 either a value or an exception. As for ``examples/example-client.py``,
406 you need to run ``examples/example-service.py`` in the background or
407 in another shell first.
409 .. --------------------------------------------------------------------
411 Receiving signals
412 =================
414 To receive signals, the Bus needs to be connected to an event loop - see
415 section `Setting up an event loop`_. Signals will only be received while
416 the event loop is running.
418 Signal matching
419 ---------------
421 To respond to signals, you can use the ``add_signal_receiver`` method on
422 `Bus objects`_. This arranges for a callback to be called when a
423 matching signal is received, and has the following arguments:
425 * a callable (the ``handler_function``) which will be called by the event loop
426   when the signal is received - its parameters will be the arguments of
427   the signal
429 * the signal name, ``signal_name``: here None (the default) matches all names
431 * the D-Bus interface, ``dbus_interface``: again None is the default,
432   and matches all interfaces
434 * a sender bus name (well-known or unique), ``bus_name``: None is again
435   the default, and matches all senders. Well-known names match signals
436   from whatever application is currently the primary owner of that
437   well-known name.
439 * a sender object path, ``path``: once again None is the default and
440   matches all object paths
442 ``add_signal_receiver`` also has keyword arguments ``utf8_strings`` and
443 ``byte_arrays`` which influence the types used when calling the
444 handler function, in the same way as the `byte_arrays and utf8_strings`_
445 options on proxy methods.
447 ``add_signal_receiver`` returns a ``SignalMatch`` object. Its only
448 useful public API at the moment is a ``remove`` method with no
449 arguments, which removes the signal match from the connection.
451 Getting more information from a signal
452 --------------------------------------
454 You can also arrange for more information to be passed to the handler
455 function. If you pass the keyword arguments ``sender_keyword``,
456 ``destination_keyword``, ``interface_keyword``, ``member_keyword`` or
457 ``path_keyword`` to the ``connect_to_signal`` method, the appropriate
458 part of the signal message will be passed to the handler function as a
459 keyword argument: for instance if you use ::
461     def handler(sender=None):
462         print "got signal from %r" % sender
464     iface.connect_to_signal("Hello", handler, sender_keyword='sender')
466 and a signal ``Hello`` with no arguments is received from
467 ``com.example.Foo``, the ``handler`` function will be called with
468 ``sender='com.example.Foo'``.
470 String argument matching
471 ------------------------
473 If there are keyword parameters for the form ``arg``\ *n* where n is a
474 small non-negative number, their values must be ``unicode`` objects
475 or UTF-8 strings. The handler will only be called if that argument
476 of the signal (numbered from zero) is a D-Bus string (in particular,
477 not an object-path or a signature) with that value.
479 .. *this comment is to stop the above breaking vim syntax highlighting*
481 Receiving signals from a proxy object
482 -------------------------------------
484 `Proxy objects`_ have a special method ``connect_to_signal`` which
485 arranges for a callback to be called when a signal is received
486 from the corresponding remote object. The parameters are:
488 * the name of the signal
490 * a callable (the handler function) which will be called by the event loop
491   when the signal is received - its parameters will be the arguments of
492   the signal
494 * the handler function, a callable: the same as for ``add_signal_receiver``
496 * the keyword argument ``dbus_interface`` qualifies the name with its
497   interface
499 `dbus.Interface` objects have a similar ``connect_to_signal`` method,
500 but in this case you don't need the ``dbus_interface`` keyword argument
501 since the interface to use is already known.
503 The same extra keyword arguments as for ``add_signal_receiver`` are also
504 available, and just like ``add_signal_receiver``, it returns a
505 SignalMatch.
507 You shouldn't use proxy objects just to listen to signals, since they
508 might activate the relevant service when created, but if you already have a
509 proxy object in order to call methods, it's often convenient to use it to add
510 signal matches too.
512 See also
513 --------
515 ``examples/signal-recipient.py`` receives signals - it demonstrates
516 general signal matching as well as ``connect_to_signal``. Before running it,
517 you'll need to run ``examples/signal-emitter.py`` in the background or
518 in another shell.
520 .. _BusName:
522 .. --------------------------------------------------------------------
524 Claiming a bus name
525 ===================
527 FIXME describe `BusName`_ - perhaps fix its API first?
529 The unique-instance idiom
530 -------------------------
532 FIXME provide exemplary code, put it in examples
534 .. _exported object:
535 .. _exported objects:
537 .. --------------------------------------------------------------------
539 Exporting objects
540 =================
542 Objects made available to other applications over D-Bus are said to be
543 *exported*. All subclasses of ``dbus.service.Object`` are automatically
544 exported.
546 To export objects, the Bus needs to be connected to an event loop - see
547 section `Setting up an event loop`_. Exported methods will only be called,
548 and queued signals will only be sent, while the event loop is running.
550 .. _dbus.service.Object:
552 Inheriting from ``dbus.service.Object``
553 ---------------------------------------
555 To export an object onto the Bus, just subclass
556 ``dbus.service.Object``. Object expects either a `BusName`_ or a `Bus
557 object`_, and an object-path, to be passed to its constructor: arrange
558 for this information to be available. For example::
560     class Example(dbus.service.Object):
561         def __init__(self, object_path):
562             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
564 This object will automatically support introspection, but won't do
565 anything particularly interesting. To fix that, you'll need to export some
566 methods and signals too.
568 FIXME also mention dbus.gobject.ExportedGObject once I've written it
570 Exporting methods with ``dbus.service.method``
571 ----------------------------------------------
573 To export a method, use the decorator ``dbus.service.method``. For
574 example::
576     class Example(dbus.service.Object):
577         def __init__(self, object_path):
578             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
580         @dbus.service.method(interface='com.example.Sample',
581                              in_signature='v', out_signature='s')
582         def StringifyVariant(self, variant):
583             return str(variant)
585 The ``in_signature`` and ``out_signature`` are D-Bus signature strings
586 as described in `Data Types`_.
588 As well as the keywords shown, you can pass ``utf8_strings`` and
589 ``byte_arrays`` keyword arguments, which influence the types which will
590 be passed to the decorated method when it's called via D-Bus, in the
591 same way that the `byte_arrays and utf8_strings`_ options affect the
592 return value of a proxy method.
594 You can find a simple example in ``examples/example-service.py``, which
595 we used earlier to demonstrate ``examples/example-client.py``.
597 Finding out the caller's bus name
598 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
600 The ``method`` decorator accepts a ``sender_keyword`` keyword argument.
601 If you set that to a string, the unique bus name of the sender will be
602 passed to the decorated method as a keyword argument of that name::
604     class Example(dbus.service.Object):
605         def __init__(self, object_path):
606             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
608         @dbus.service.method(interface='com.example.Sample',
609                              in_signature='', out_signature='s',
610                              sender_keyword='sender')
611         def SayHello(self, sender=None):
612             return 'Hello, %s!' % sender
613             # -> something like 'Hello, :1.1!'
615 Asynchronous method implementations
616 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
618 FIXME and also add an example, perhaps examples/example-async-service.py
620 Emitting signals with ``dbus.service.signal``
621 ---------------------------------------------
623 To export a signal, use the decorator ``dbus.service.signal``; to emit
624 that signal, call the decorated method. The decorated method can also
625 contain code which will be run when called, as usual. For example::
627     class Example(dbus.service.Object):
628         def __init__(self, object_path):
629             dbus.service.Object.__init__(self, dbus.SessionBus(), path)
631         @dbus.service.signal(interface='com.example.Sample',
632                              signature='us')
633         def NumberOfBottlesChanged(self, number, contents):
634             print "%d bottles of %s on the wall" % (number, contents)
636     e = Example('/bottle-counter')
637     e.NumberOfBottlesChanged(100, 'beer')
638     # -> emits com.example.Sample.NumberOfBottlesChanged(100, 'beer')
639     #    and prints "100 bottles of beer on the wall"
641 The signal will be queued for sending when the decorated method returns -
642 you can prevent the signal from being sent by raising an exception
643 from the decorated method (for instance, if the parameters are
644 inappropriate). The signal will only actually be sent when the event loop
645 next runs.
647 Example
648 ~~~~~~~
650 ``examples/example-signal-emitter.py`` emits some signals on demand when
651 one of its methods is called. (In reality, you'd emit a signal when some
652 sort of internal state changed, which may or may not be triggered by a
653 D-Bus method call.)
655 .. --------------------------------------------------------------------
657 License for this document
658 =========================
660 Copyright 2006-2007 `Collabora Ltd.`_
662 Licensed under the Academic Free License version 2.1
664 This document is free software; you can redistribute it and/or modify
665 it under the terms of the GNU Lesser General Public License as published by
666 the Free Software Foundation; either version 2.1 of the License, or
667 (at your option) any later version.
669 This document is distributed in the hope that it will be useful,
670 but WITHOUT ANY WARRANTY; without even the implied warranty of
671 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
672 GNU Lesser General Public License for more details.
674 You should have received a copy of the GNU Lesser General Public License
675 along with this document; if not, write to the Free Software
676 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
679   vim:set ft=rst sw=4 sts=4 et tw=72: