[PATCH][python] Implement DBusException in pure Python; add get_dbus_name() method and name= keyword argument

Simon McVittie simon.mcvittie at collabora.co.uk
Wed May 16 04:00:02 PDT 2007


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

- ---
 _dbus_bindings/bus.c                    |    5 +-
 _dbus_bindings/conn-methods.c           |    6 +-
 _dbus_bindings/dbus_bindings-internal.h |    2 +-
 _dbus_bindings/exceptions.c             |   99 ++++++++++++++++++-------------
 _dbus_bindings/message.c                |    6 +-
 _dbus_bindings/module.c                 |    2 -
 dbus/__init__.py                        |    7 +-
 dbus/_dbus.py                           |    3 +-
 dbus/bus.py                             |    2 +-
 dbus/connection.py                      |   11 +--
 dbus/dbus_bindings.py                   |    2 +-
 dbus/decorators.py                      |    2 +
 dbus/exceptions.py                      |   22 ++++++-
 dbus/service.py                         |   11 ++-
 14 files changed, 105 insertions(+), 75 deletions(-)

diff --git a/_dbus_bindings/bus.c b/_dbus_bindings/bus.c
index 1e3b81f..5d671ba 100644
- --- a/_dbus_bindings/bus.c
+++ b/_dbus_bindings/bus.c
@@ -103,9 +103,8 @@ DBusPyConnection_GetUniqueName(Connection *self, PyObject *args UNUSED)
     name = dbus_bus_get_unique_name(self->conn);
     Py_END_ALLOW_THREADS
     if (!name) {
- -        PyErr_SetString(DBusPyException, "This connection has no unique "
- -                        "name yet");
- -        return NULL;
+        return DBusPyException_SetString("This connection has no unique name "
+                                         "yet");
     }
     return PyString_FromString(name);
 }
diff --git a/_dbus_bindings/conn-methods.c b/_dbus_bindings/conn-methods.c
index 6c1f90f..1b41c46 100644
- --- a/_dbus_bindings/conn-methods.c
+++ b/_dbus_bindings/conn-methods.c
@@ -405,9 +405,8 @@ Connection_send_message_with_reply(Connection *self, PyObject *args, PyObject *k
 
     if (!pending) {
         /* connection is disconnected (doesn't return FALSE!) */
- -        PyErr_SetString (DBusPyException, "Connection is disconnected - "
+        return DBusPyException_SetString ("Connection is disconnected - "
                                           "unable to make method call");
- -        return NULL;
     }
 
     return DBusPyPendingCall_ConsumeDBusPendingCall(pending, callable);
@@ -473,6 +472,9 @@ Connection_send_message_with_reply_and_block(Connection *self, PyObject *args)
                                                       timeout_ms, &error);
     Py_END_ALLOW_THREADS
 
+    /* FIXME: if we instead used send_with_reply and blocked on the resulting
+     * PendingCall, then we could get all args from the error, not just
+     * the first */
     if (!reply) {
         return DBusPyException_ConsumeError(&error);
     }
diff --git a/_dbus_bindings/dbus_bindings-internal.h b/_dbus_bindings/dbus_bindings-internal.h
index 392f58d..2e7f6ff 100644
- --- a/_dbus_bindings/dbus_bindings-internal.h
+++ b/_dbus_bindings/dbus_bindings-internal.h
@@ -65,7 +65,7 @@ extern dbus_bool_t dbus_py_init_bus_types(void);
 extern dbus_bool_t dbus_py_insert_bus_types(PyObject *this_module);
 
 /* exceptions.c */
- -extern PyObject *DBusPyException;
+extern PyObject *DBusPyException_SetString(const char *msg);
 extern PyObject *DBusPyException_ConsumeError(DBusError *error);
 extern dbus_bool_t dbus_py_init_exception_types(void);
 extern dbus_bool_t dbus_py_insert_exception_types(PyObject *this_module);
diff --git a/_dbus_bindings/exceptions.c b/_dbus_bindings/exceptions.c
index 3578de1..c5554ba 100644
- --- a/_dbus_bindings/exceptions.c
+++ b/_dbus_bindings/exceptions.c
@@ -22,60 +22,75 @@
 
 #include "dbus_bindings-internal.h"
 
- -PyObject *DBusPyException;
+static PyObject *imported_dbus_exception = NULL;
 
- -PyDoc_STRVAR(DBusException__doc__, "Represents any D-Bus-related error.");
+static dbus_bool_t
+import_exception(void)
+{
+    PyObject *name;
+    PyObject *exceptions;
+
+    if (imported_dbus_exception != NULL) {
+        return TRUE;
+    }
+
+    name = PyString_FromString("dbus.exceptions");
+    if (name == NULL) {
+        return FALSE;
+    }
+    exceptions = PyImport_Import(name);
+    Py_DECREF(name);
+    if (exceptions == NULL) {
+        return FALSE;
+    }
+    imported_dbus_exception = PyObject_GetAttrString(exceptions,
+                                                     "DBusException");
+    Py_DECREF(exceptions);
+
+    return (imported_dbus_exception != NULL);
+}
 
 PyObject *
- -DBusPyException_ConsumeError(DBusError *error)
+DBusPyException_SetString(const char *msg)
 {
- -    PyErr_Format(DBusPyException, "%s: %s",
- -                 error->name, error->message);
- -    dbus_error_free(error);
+    if (imported_dbus_exception != NULL || import_exception()) {
+        PyErr_SetString(imported_dbus_exception, msg);
+    }
     return NULL;
 }
 
- -dbus_bool_t
- -dbus_py_init_exception_types(void)
+PyObject *
+DBusPyException_ConsumeError(DBusError *error)
 {
- -    PyObject *bases;
- -    PyObject *dict = PyDict_New();
- -    PyObject *name;
+    PyObject *exc_value = NULL;
 
- -    if (!dict)
- -        return 0;
- -    if (PyDict_SetItemString(dict, "__doc__",
- -                             PyString_FromString(DBusException__doc__)) < 0)
- -        return 0;
- -    if (PyDict_SetItemString(dict, "__module__",
- -                             PyString_FromString("dbus")) < 0)
- -        return 0;
- -    bases = Py_BuildValue("(O)", (PyObject *)PyExc_Exception);
- -    if (!bases) {
- -        Py_DECREF(dict);
- -        return 0;
+    if (imported_dbus_exception == NULL && !import_exception()) {
+        goto finally;
     }
- -    name = PyString_FromString("DBusException");
- -    if (!name) {
- -        Py_DECREF(dict);
- -        Py_DECREF(bases);
- -        return 0;
- -    }
- -    DBusPyException = PyClass_New(bases, dict, name);
- -    Py_DECREF(bases);
- -    Py_DECREF(dict);
- -    if (!DBusPyException)
- -        return 0;
- -    return 1;
- -}
 
- -dbus_bool_t
- -dbus_py_insert_exception_types(PyObject *this_module)
- -{
- -    if (PyModule_AddObject(this_module, "DBusException", DBusPyException) < 0) {
- -        return 0;
+    exc_value = PyObject_CallFunction(imported_dbus_exception,
+                                      "s",
+                                      error->message ? error->message
+                                                     : "");
+    if (error->name) {
+        PyObject *name = PyString_FromString(error->name);
+        int ret;
+
+        if (!name)
+            goto finally;
+        ret = PyObject_SetAttrString(exc_value, "_dbus_error_name", name);
+        Py_DECREF(name);
+        if (ret < 0) {
+            goto finally;
+        }
     }
- -    return 1;
+
+    PyErr_SetObject(imported_dbus_exception, exc_value);
+
+finally:
+    Py_XDECREF(exc_value);
+    dbus_error_free(error);
+    return NULL;
 }
 
 /* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/message.c b/_dbus_bindings/message.c
index 436690e..3887aaa 100644
- --- a/_dbus_bindings/message.c
+++ b/_dbus_bindings/message.c
@@ -36,9 +36,9 @@ static inline int Message_Check(PyObject *o)
 PyObject *
 DBusPy_RaiseUnusableMessage(void)
 {
- -    PyErr_SetString(DBusPyException,
- -                    "Message object is uninitialized, or has become unusable "
- -                     "due to error while appending arguments");
+    DBusPyException_SetString("Message object is uninitialized, or has become "
+                              "unusable due to error while appending "
+                              "arguments");
     return NULL;
 }
 
diff --git a/_dbus_bindings/module.c b/_dbus_bindings/module.c
index cb74ac2..a0e5c95 100644
- --- a/_dbus_bindings/module.c
+++ b/_dbus_bindings/module.c
@@ -254,7 +254,6 @@ init_dbus_bindings(void)
     }
 
     if (!dbus_py_init_generic()) return;
- -    if (!dbus_py_init_exception_types()) return;
     if (!dbus_py_init_abstract()) return;
     if (!dbus_py_init_signature()) return;
     if (!dbus_py_init_int_types()) return;
@@ -270,7 +269,6 @@ init_dbus_bindings(void)
     this_module = Py_InitModule3("_dbus_bindings", module_functions, module_doc);
     if (!this_module) return;
 
- -    if (!dbus_py_insert_exception_types(this_module)) return;
     if (!dbus_py_insert_abstract_types(this_module)) return;
     if (!dbus_py_insert_signature(this_module)) return;
     if (!dbus_py_insert_int_types(this_module)) return;
diff --git a/dbus/__init__.py b/dbus/__init__.py
index efd9aa6..9ad884b 100644
- --- a/dbus/__init__.py
+++ b/dbus/__init__.py
@@ -50,13 +50,12 @@ __all__ = (
            'LOCAL_PATH', 'LOCAL_IFACE', 'PEER_IFACE',
            'INTROSPECTABLE_IFACE', 'PROPERTIES_IFACE',
 
- -           'DBusException',
- -
            'ObjectPath', 'ByteArray', 'Signature', 'Byte', 'Boolean',
            'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64',
            'Double', 'String', 'Array', 'Struct', 'Dictionary', 'UTF8String',
 
            # from exceptions
+           'DBusException',
            'MissingErrorHandlerException', 'MissingReplyHandlerException',
            'ValidationException', 'IntrospectionParserException',
            'UnknownMethodException', 'NameExistsException',
@@ -82,14 +81,14 @@ from _dbus_bindings import get_default_main_loop, set_default_main_loop,\
 from _dbus_bindings import BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE,\
                            LOCAL_PATH, LOCAL_IFACE, PEER_IFACE,\
                            INTROSPECTABLE_IFACE, PROPERTIES_IFACE
- -from _dbus_bindings import DBusException
 
 from dbus.exceptions import MissingErrorHandlerException, \
                             MissingReplyHandlerException, \
                             ValidationException, \
                             IntrospectionParserException, \
                             UnknownMethodException, \
- -                            NameExistsException
+                            NameExistsException, \
+                            DBusException
 from _dbus_bindings import ObjectPath, ByteArray, Signature, Byte, Boolean,\
                            Int16, UInt16, Int32, UInt32, Int64, UInt64,\
                            Double, String, Array, Struct, Dictionary, \
diff --git a/dbus/_dbus.py b/dbus/_dbus.py
index d46aa9b..3b96201 100644
- --- a/dbus/_dbus.py
+++ b/dbus/_dbus.py
@@ -31,8 +31,9 @@ import sys
 import weakref
 from traceback import print_exc
 
+from dbus.exceptions import DBusException
 from _dbus_bindings import BUS_DAEMON_NAME, BUS_DAEMON_PATH,\
- -                           BUS_DAEMON_IFACE, DBusException, UTF8String,\
+                           BUS_DAEMON_IFACE, UTF8String,\
                            validate_member_name, validate_interface_name,\
                            validate_bus_name, validate_object_path,\
                            BUS_SESSION, BUS_SYSTEM, BUS_STARTER,\
diff --git a/dbus/bus.py b/dbus/bus.py
index 80118aa..645f6a8 100644
- --- a/dbus/bus.py
+++ b/dbus/bus.py
@@ -25,13 +25,13 @@ import weakref
 from _dbus_bindings import validate_interface_name, validate_member_name,\
                            validate_bus_name, validate_object_path,\
                            validate_error_name,\
- -                           DBusException, \
                            BUS_SESSION, BUS_STARTER, BUS_SYSTEM, \
                            DBUS_START_REPLY_SUCCESS, \
                            DBUS_START_REPLY_ALREADY_RUNNING, \
                            BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE,\
                            HANDLER_RESULT_NOT_YET_HANDLED
 from dbus.connection import Connection
+from dbus.exceptions import DBusException
 
 
 _NAME_OWNER_CHANGE_MATCH = ("type='signal',sender='%s',"
diff --git a/dbus/connection.py b/dbus/connection.py
index fd0fe7a..1304058 100644
- --- a/dbus/connection.py
+++ b/dbus/connection.py
@@ -28,12 +28,13 @@ import weakref
 
 from _dbus_bindings import Connection as _Connection, ErrorMessage, \
                            MethodCallMessage, MethodReturnMessage, \
- -                           DBusException, LOCAL_PATH, LOCAL_IFACE, \
+                           LOCAL_PATH, LOCAL_IFACE, \
                            validate_interface_name, validate_member_name,\
                            validate_bus_name, validate_object_path,\
                            validate_error_name, \
                            HANDLER_RESULT_NOT_YET_HANDLED, \
                            UTF8String, SignalMessage
+from dbus.exceptions import DBusException
 from dbus.proxies import ProxyObject
 
 
@@ -548,12 +549,8 @@ class Connection(_Connection):
             if isinstance(message, MethodReturnMessage):
                 reply_handler(*message.get_args_list(**get_args_opts))
             elif isinstance(message, ErrorMessage):
- -                args = message.get_args_list()
- -                # FIXME: should we do something with the rest?
- -                if len(args) > 0:
- -                    error_handler(DBusException(args[0]))
- -                else:
- -                    error_handler(DBusException())
+                error_handler(DBusException(name=message.get_error_name(),
+                                            *message.get_args_list()))
             else:
                 error_handler(TypeError('Unexpected type for reply '
                                         'message: %r' % message))
diff --git a/dbus/dbus_bindings.py b/dbus/dbus_bindings.py
index 050a4e1..a45ca9f 100644
- --- a/dbus/dbus_bindings.py
+++ b/dbus/dbus_bindings.py
@@ -16,7 +16,7 @@ If you need additional public API, please contact the maintainers via
 _warn(_dbus_bindings_warning, DeprecationWarning, stacklevel=2)
 
 # Exceptions
- -from _dbus_bindings import DBusException
+from dbus.exceptions import DBusException
 class ConnectionError(Exception): pass
 
 # Types
diff --git a/dbus/decorators.py b/dbus/decorators.py
index aa08940..9cc0dbe 100644
- --- a/dbus/decorators.py
+++ b/dbus/decorators.py
@@ -28,6 +28,8 @@ import inspect
 
 import _dbus_bindings
 
+from dbus.exceptions import DBusException
+
 
 def method(dbus_interface, in_signature=None, out_signature=None,
         async_callbacks=None,
diff --git a/dbus/exceptions.py b/dbus/exceptions.py
index 801ede6..545d62f 100644
- --- a/dbus/exceptions.py
+++ b/dbus/exceptions.py
@@ -5,9 +5,23 @@ __all__ = ('DBusException', 'MissingErrorHandlerException',
            'IntrospectionParserException', 'UnknownMethodException',
            'NameExistsException')
 
- -import _dbus_bindings
- -
- -DBusException = _dbus_bindings.DBusException
+class DBusException(Exception):
+    def __init__(self, *args, **kwargs):
+        self._dbus_error_name = kwargs.pop('name', None)
+        if kwargs:
+            raise TypeError('DBusException does not take keyword arguments: %s'
+                            % ', '.join(kwargs.keys()))
+        Exception.__init__(self, *args)
+
+    def __str__(self):
+        s = Exception.__str__(self)
+        if self._dbus_error_name is not None:
+            return '%s: %s' % (self._dbus_error_name, s)
+        else:
+            return s
+
+    def get_dbus_name(self):
+        return self._dbus_error_name
 
 class MissingErrorHandlerException(DBusException):
     def __init__(self):
@@ -26,10 +40,10 @@ class IntrospectionParserException(DBusException):
         DBusException.__init__(self, "Error parsing introspect data: %s"%msg)
 
 class UnknownMethodException(DBusException):
+    _dbus_error_name = 'org.freedesktop.DBus.Error.UnknownMethod'
     def __init__(self, method):
         DBusException.__init__(self, "Unknown method: %s"%method)
 
 class NameExistsException(DBusException):
     def __init__(self, name):
         DBusException.__init__(self, "Bus name already exists: %s"%name)
- -
diff --git a/dbus/service.py b/dbus/service.py
index 9b4c262..9d3dc3f 100644
- --- a/dbus/service.py
+++ b/dbus/service.py
@@ -29,8 +29,9 @@ import traceback
 
 import _dbus_bindings
 from dbus import SessionBus
- -from dbus.exceptions import NameExistsException
- -from dbus.exceptions import UnknownMethodException
+from dbus.exceptions import DBusException, \
+                            NameExistsException, \
+                            UnknownMethodException
 from dbus.decorators import method
 from dbus.decorators import signal
 from dbus.proxies import LOCAL_PATH
@@ -249,8 +250,10 @@ def _method_reply_return(connection, message, method_name, signature, *retval):
 
 
 def _method_reply_error(connection, message, exception):
- -    if hasattr(exception, '_dbus_error_name'):
- -        name = exception._dbus_error_name
+    name = getattr(exception, '_dbus_error_name', None)
+
+    if name is not None:
+        pass
     elif getattr(exception, '__module__', '') in ('', '__main__'):
         name = 'org.freedesktop.DBus.Python.%s' % exception.__class__.__name__
     else:
- -- 
1.5.2-rc2.GIT

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: OpenPGP key: http://www.pseudorandom.co.uk/2003/contact/ or pgp.net

iD8DBQFGSuQxWSc8zVUw7HYRApPvAJ4vi1v/IR0nd/opAYAugiH/FlGnxQCgsJ6Q
/lKdRaguMRWbt0zm94xo8Po=
=NT/3
-----END PGP SIGNATURE-----


More information about the dbus mailing list