From c51b148077479381844a84989292719417c543b2 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 30 Aug 2006 20:15:07 +0100 Subject: [PATCH] Add some docstrings (reStructuredText with epydoc annotations) --- dbus/__init__.py | 9 ++++++++ dbus/_dbus.py | 35 ++++++++++++++--------------- dbus/decorators.py | 44 +++++++++++++++++++++++++++++++++++++ dbus/exceptions.py | 7 ++++++ dbus/service.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 139 insertions(+), 20 deletions(-) diff --git a/dbus/__init__.py b/dbus/__init__.py index 4b4c541..9632470 100644 --- a/dbus/__init__.py +++ b/dbus/__init__.py @@ -1,3 +1,12 @@ +"""\ +Implements the public API for a D-Bus client. See the dbus.service module +to implement services. + +FIXME +----- +Which of the imported symbols constitute public API? +""" + from _dbus import * from types import * diff --git a/dbus/_dbus.py b/dbus/_dbus.py index 7e17d9f..7b72cfb 100644 --- a/dbus/_dbus.py +++ b/dbus/_dbus.py @@ -1,4 +1,3 @@ - """Module for high-level communication over the FreeDesktop.org Bus (DBus) DBus allows you to share and access remote objects between processes @@ -13,34 +12,36 @@ have a RemoteService you can get a RemoteObject that implements a specific inter (an interface is just a standard group of member functions). Then you can call those member functions directly. -You can think of a complete method call as looking something like: +You can think of a complete method call as looking something like:: -Bus:SESSION -> Service:org.gnome.Evolution -> Object:/org/gnome/Evolution/Inbox -> Interface: org.gnome.Evolution.MailFolder -> Method: Forward('message1', 'seth@gnome.org') + Bus:SESSION -> Service:org.gnome.Evolution -> Object:/org/gnome/Evolution/Inbox -> Interface: org.gnome.Evolution.MailFolder -> Method: Forward('message1', 'seth@gnome.org') This communicates over the SESSION Bus to the org.gnome.Evolution process to call the Forward method of the /org/gnome/Evolution/Inbox object (which provides the org.gnome.Evolution.MailFolder interface) with two string arguments. -For example, the dbus-daemon itself provides a service and some objects: +For example, the dbus-daemon itself provides a service and some objects:: -# Get a connection to the desktop-wide SESSION bus -bus = dbus.Bus(dbus.Bus.TYPE_SESSION) + # Get a connection to the desktop-wide SESSION bus + bus = dbus.Bus(dbus.Bus.TYPE_SESSION) -# Get the service provided by the dbus-daemon named org.freedesktop.DBus -dbus_service = bus.get_service('org.freedesktop.DBus') + # Get the service provided by the dbus-daemon named org.freedesktop.DBus + dbus_service = bus.get_service('org.freedesktop.DBus') -# Get a reference to the desktop bus' standard object, denoted -# by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus -# implements the 'org.freedesktop.DBus' interface -dbus_object = dbus_service.get_object('/org/freedesktop/DBus', - 'org.freedesktop.DBus') + # Get a reference to the desktop bus' standard object, denoted + # by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus + # implements the 'org.freedesktop.DBus' interface + dbus_object = dbus_service.get_object('/org/freedesktop/DBus', + 'org.freedesktop.DBus') -# One of the member functions in the org.freedesktop.DBus interface -# is ListServices(), which provides a list of all the other services -# registered on this bus. Call it, and print the list. -print(dbus_object.ListServices()) + # One of the member functions in the org.freedesktop.DBus interface + # is ListServices(), which provides a list of all the other services + # registered on this bus. Call it, and print the list. + print(dbus_object.ListServices()) """ +__docformat__ = 'reStructuredText' + import dbus import dbus_bindings import weakref diff --git a/dbus/decorators.py b/dbus/decorators.py index c9bc17f..0949100 100644 --- a/dbus/decorators.py +++ b/dbus/decorators.py @@ -1,8 +1,52 @@ +"""Service-side D-Bus decorators.""" + +__all__ = ('explicitly_pass_message', 'method', 'signal') +__docformat__ = 'restructuredtext' + import _util import inspect import dbus_bindings def method(dbus_interface, in_signature=None, out_signature=None, async_callbacks=None, sender_keyword=None): + """Factory for decorators used to mark methods of a `dbus.service.Object` + to be exported on the D-Bus. + + :Parameters: + `dbus_interface` : str + Name of a D-Bus interface + `in_signature` : str or None + If not None, the signature of the method parameters in the usual + D-Bus notation + `out_signature` : str or None + If not None, the signature of the return value in the usual + D-Bus notation + `async_callbacks` : tuple containing (str,str), or None + If None (default) the decorated method is expected to return + values matching the `out_signature` as usual, or raise + an exception on error. If not None, the following applies: + + `async_callbacks` contains the names of two keyword arguments to + the decorated function, which will be used to provide a success + callback and an error callback (in that order). + + When the decorated method is called via the D-Bus, its normal + return value will be ignored; instead, a pair of callbacks are + passed as keyword arguments, and the decorated method is + expected to arrange for one of them to be called. + + On success the success callback must be called, passing the + results of this method as positional parameters in the format + given by the `out_signature`. + + On error the decorated method may either raise an exception + before it returns, or arrange for the error callback to be + called with an Exception instance as parameter. + + `sender_keyword` : str or None + If not None, contains the name of a keyword argument to the + decorated function. When the method is called, the sender's + unique name will be passed as this keyword argument. + """ _util._validate_interface_or_name(dbus_interface) def decorator(func): diff --git a/dbus/exceptions.py b/dbus/exceptions.py index 2b01b96..ab43ce1 100644 --- a/dbus/exceptions.py +++ b/dbus/exceptions.py @@ -1,3 +1,10 @@ +"""D-Bus exceptions.""" + +__all__ = ('DBusException', 'ConnectionError', 'MissingErrorHandlerException', + 'MissingReplyHandlerException', 'ValidationException', + 'IntrospectionParserException', 'UnknownMethodException', + 'NameExistsException') + import dbus_bindings DBusException = dbus_bindings.DBusException diff --git a/dbus/service.py b/dbus/service.py index 78f9eba..f839a48 100644 --- a/dbus/service.py +++ b/dbus/service.py @@ -1,3 +1,6 @@ +__all__ = ('BusName', 'Object', 'method', 'signal') +__docformat__ = 'restructuredtext' + import dbus_bindings import _dbus import operator @@ -9,14 +12,48 @@ from decorators import method from decorators import signal class BusName(object): - """A base class for exporting your own Named Services across the Bus + """A base class for exporting your own Named Services across the Bus. + + When instantiated, objects of this class attempt to claim the given + well-known name on the given bus for the current process. The name is + released when the BusName object becomes unreferenced. + + If a well-known name is requested multiple times, multiple references + to the same BusName object will be returned. + + Caveats + ------- + - Assumes that named services are only ever requested using this class - + if you request names from the bus directly, confusion may occur. + - Does not handle queueing. """ def __new__(cls, name, bus=None, allow_replacement=False , replace_existing=False, do_not_queue=False): + """Constructor, which may either return an existing cached object + or a new object. + + :Parameters: + `name` : str + The well-known name to be advertised + `bus` : dbus.Bus + A Bus on which this service will be advertised; if None + (default) a default bus will be used + `allow_replacement` : bool + If True, other processes trying to claim the same well-known + name will take precedence over this one. + `replace_existing` : bool + If True, this process can take over the well-known name + from other processes already holding it. + `do_not_queue` : bool + If True, this service will not be placed in the queue of + services waiting for the requested name if another service + already holds it. + """ # get default bus if bus == None: bus = _dbus.Bus() # see if this name is already defined, return it if so + # FIXME: accessing internals of Bus if name in bus._bus_names: return bus._bus_names[name] @@ -50,7 +87,8 @@ class BusName(object): bus_name._bus = bus bus_name._name = name - # cache instance + # cache instance (weak ref only) + # FIXME: accessing Bus internals again bus._bus_names[name] = bus_name return bus_name @@ -264,9 +302,26 @@ class Object(Interface): """A base class for exporting your own Objects across the Bus. Just inherit from Object and provide a list of methods to share - across the Bus + across the Bus. + + Issues + ------ + - The constructor takes a well-known name: this is wrong. There should be + no requirement to register a well-known name in order to export bus + objects. """ def __init__(self, bus_name, object_path): + """Constructor. + + :Parameters: + `bus_name` : BusName + Represents a well-known name claimed by this process. A + reference to the BusName object will be held by this + Object, preventing the name from being released during this + Object's lifetime (subject to status). + `object_path` : str + The D-Bus object path at which to export this Object. + """ self._object_path = object_path self._name = bus_name self._bus = bus_name.get_bus() @@ -350,6 +405,9 @@ class Object(Interface): @method('org.freedesktop.DBus.Introspectable', in_signature='', out_signature='s') def Introspect(self): + """Return a string of XML encoding this object's supported interfaces, + methods and signals. + """ reflection_data = '\n' reflection_data += '\n' % (self._object_path) -- 2.11.4.GIT