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

John (J5) Palmieri johnp at redhat.com
Fri May 18 08:54:28 PDT 2007


Looks good

On Wed, 2007-05-16 at 12:00 +0100, Simon McVittie wrote:
> -----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-----
> _______________________________________________
> dbus mailing list
> dbus at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dbus



More information about the dbus mailing list