[PATCH 02/17] Remove BusImplementation, removing its remaining functionality to Connection.

Simon McVittie simon.mcvittie at collabora.co.uk
Mon Apr 30 03:23:58 PDT 2007


* Move get_unique_name to Connection (it can be useful for connections which
  aren't to a real bus daemon but partially emulate one, like Telepathy's
  Tubes)
* Add set_unique_name to Connection (same reason)
* Convert BusImplementation.__new__ into Connection._new_for_bus
* Have dbus.Bus subclass _dbus_bindings.Connection directly

diff --git a/_dbus_bindings/bus.c b/_dbus_bindings/bus.c
index 761b67e..1e3b81f 100644
--- a/_dbus_bindings/bus.c
+++ b/_dbus_bindings/bus.c
@@ -23,26 +23,8 @@
 #include "dbus_bindings-internal.h"
 #include "conn-internal.h"
 
-PyDoc_STRVAR(Bus_tp_doc,
-"If the address is an int it must be one of the constants BUS_SESSION,\n"
-"BUS_SYSTEM, BUS_STARTER; if a string, it must be a D-Bus address.\n"
-"The default is BUS_SESSION.\n"
-"\n"
-"Constructor::\n"
-"\n"
-"   BusImplementation([address: str or int])\n"
-);
-
-/* Bus definition =================================================== */
-
-static PyTypeObject BusType;
-
-#define Bus_Check(ob) PyObject_TypeCheck(ob, &BusType)
-
-/* Bus methods ====================================================== */
-
-static PyObject *
-Bus_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyConnection_NewForBus(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
 {
     PyObject *first = NULL, *mainloop = NULL;
     DBusConnection *conn;
@@ -110,11 +92,8 @@ Bus_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
     return DBusPyConnection_NewConsumingDBusConnection(cls, conn, mainloop);
 }
 
-PyDoc_STRVAR(Bus_get_unique_name__doc__,
-"get_unique_name() -> str\n\n"
-"Return this application's unique name on this bus.\n");
-static PyObject *
-Bus_get_unique_name(Connection *self, PyObject *args UNUSED)
+PyObject *
+DBusPyConnection_GetUniqueName(Connection *self, PyObject *args UNUSED)
 {
     const char *name;
 
@@ -124,81 +103,50 @@ Bus_get_unique_name(Connection *self, PyObject *args UNUSED)
     name = dbus_bus_get_unique_name(self->conn);
     Py_END_ALLOW_THREADS
     if (!name) {
-        /* shouldn't happen, but C subtypes could have done something stupid */
-        PyErr_SetString(DBusPyException, "Unable to retrieve unique name");
+        PyErr_SetString(DBusPyException, "This connection has no unique "
+                        "name yet");
         return NULL;
     }
     return PyString_FromString(name);
 }
 
-/* Bus type object ================================================== */
-
-static struct PyMethodDef Bus_tp_methods[] = {
-#define ENTRY(name, flags) {#name, (PyCFunction)Bus_##name, flags, Bus_##name##__doc__},
-    ENTRY(get_unique_name, METH_NOARGS)
-#undef ENTRY
-    {NULL},
-};
-
-static PyTypeObject BusType = {
-        PyObject_HEAD_INIT(NULL)
-        0,                      /*ob_size*/
-        "_dbus_bindings.BusImplementation",  /*tp_name*/
-        0,                      /*tp_basicsize*/
-        0,                      /*tp_itemsize*/
-        /* methods */
-        0,                      /*tp_dealloc*/
-        0,                      /*tp_print*/
-        0,                      /*tp_getattr*/
-        0,                      /*tp_setattr*/
-        0,                      /*tp_compare*/
-        0,                      /*tp_repr*/
-        0,                      /*tp_as_number*/
-        0,                      /*tp_as_sequence*/
-        0,                      /*tp_as_mapping*/
-        0,                      /*tp_hash*/
-        0,                      /*tp_call*/
-        0,                      /*tp_str*/
-        0,                      /*tp_getattro*/
-        0,                      /*tp_setattro*/
-        0,                      /*tp_as_buffer*/
-        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /*tp_flags*/
-        Bus_tp_doc,             /*tp_doc*/
-        0,                      /*tp_traverse*/
-        0,                      /*tp_clear*/
-        0,                      /*tp_richcompare*/
-        0,                      /*tp_weaklistoffset*/
-        0,                      /*tp_iter*/
-        0,                      /*tp_iternext*/
-        Bus_tp_methods,         /*tp_methods*/
-        0,                      /*tp_members*/
-        0,                      /*tp_getset*/
-        DEFERRED_ADDRESS(&ConnectionType), /*tp_base*/
-        0,                      /*tp_dict*/
-        0,                      /*tp_descr_get*/
-        0,                      /*tp_descr_set*/
-        0,                      /*tp_dictoffset*/
-        0,                      /*tp_init*/
-        0,                      /*tp_alloc*/
-        Bus_tp_new,             /*tp_new*/
-        0,                      /*tp_free*/
-        0,                      /*tp_is_gc*/
-};
-
-dbus_bool_t
-dbus_py_init_bus_types(void)
+PyObject *
+DBusPyConnection_SetUniqueName(Connection *self, PyObject *args)
 {
-    BusType.tp_base = &DBusPyConnection_Type;
-    if (PyType_Ready(&BusType) < 0) return 0;
-    return 1;
-}
+    const char *old_name, *new_name;
 
-dbus_bool_t
-dbus_py_insert_bus_types(PyObject *this_module)
-{
-    if (PyModule_AddObject(this_module, "BusImplementation",
-                           (PyObject *)&BusType) < 0) return 0;
-    return 1;
+    if (!PyArg_ParseTuple(args, "s:set_unique_name", &new_name)) {
+        return NULL;
+    }
+
+    TRACE(self);
+    DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+
+    /* libdbus will assert if we try to set a unique name when there's
+     * already one, so we need to make sure that can't happen.
+     * (Thanks, libdbus.)
+     *
+     * The things that can set the unique name are:
+     * - this function - but we don't release the GIL, so only one instance of
+     *   this function can run
+     * - dbus_bus_get - but this is only called in a __new__ or __new__-like
+     *   function, so the new connection isn't available to other code yet
+     *   and this function can't be called on it
+     * - dbus_bus_register - same as dbus_bus_get
+     *
+     * Code outside dbus-python shouldn't be setting the unique name, because
+     * we're using a private connection; we have to trust the authors
+     * of mainloop bindings not to do silly things like that.
+     */
+    old_name = dbus_bus_get_unique_name(self->conn);
+    if (old_name != NULL) {
+        PyErr_Format(PyExc_ValueError, "This connection already has a "
+                     "unique name: '%s'", old_name);
+        return NULL;
+    }
+    dbus_bus_set_unique_name(self->conn, new_name);
+
+    Py_RETURN_NONE;
 }
 
 /* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/conn-internal.h b/_dbus_bindings/conn-internal.h
index 8a542b4..9ca8f54 100644
--- a/_dbus_bindings/conn-internal.h
+++ b/_dbus_bindings/conn-internal.h
@@ -50,4 +50,9 @@ extern PyObject *DBusPyConnection_ExistingFromDBusConnection(DBusConnection *);
 extern PyObject *DBusPyConnection_GetObjectPathHandlers(PyObject *self,
                                                         PyObject *path);
 
+extern PyObject *DBusPyConnection_NewForBus(PyTypeObject *cls, PyObject *args,
+                                            PyObject *kwargs);
+extern PyObject *DBusPyConnection_SetUniqueName(Connection *, PyObject *);
+extern PyObject *DBusPyConnection_GetUniqueName(Connection *, PyObject *);
+
 #endif
diff --git a/_dbus_bindings/conn-methods.c b/_dbus_bindings/conn-methods.c
index 23ca1d3..6c1f90f 100644
--- a/_dbus_bindings/conn-methods.c
+++ b/_dbus_bindings/conn-methods.c
@@ -914,6 +914,27 @@ Connection__unregister_object_path(Connection *self, PyObject *args,
 
 /* dbus_connection_get_outgoing_size - almost certainly unneeded */
 
+PyDoc_STRVAR(new_for_bus__doc__,
+"Connection._new_for_bus([address: str or int]) -> Connection\n"
+"\n"
+"If the address is an int it must be one of the constants BUS_SESSION,\n"
+"BUS_SYSTEM, BUS_STARTER; if a string, it must be a D-Bus address.\n"
+"The default is BUS_SESSION.\n"
+);
+
+PyDoc_STRVAR(get_unique_name__doc__,
+"get_unique_name() -> str\n\n"
+"Return this application's unique name on this bus.\n"
+"\n"
+":Raises DBusException: if the connection has no unique name yet\n"
+"   (for Bus objects this can't happen, for peer-to-peer connections\n"
+"   this means you haven't called `set_unique_name`)\n");
+
+PyDoc_STRVAR(set_unique_name__doc__,
+"set_unique_name(str)\n\n"
+"Set this application's unique name on this bus. Raise ValueError if it has\n"
+"already been set.\n");
+
 struct PyMethodDef DBusPyConnection_tp_methods[] = {
 #define ENTRY(name, flags) {#name, (PyCFunction)Connection_##name, flags, Connection_##name##__doc__}
     ENTRY(_require_main_loop, METH_NOARGS),
@@ -932,6 +953,15 @@ struct PyMethodDef DBusPyConnection_tp_methods[] = {
     ENTRY(send_message_with_reply, METH_VARARGS|METH_KEYWORDS),
     ENTRY(send_message_with_reply_and_block, METH_VARARGS),
     ENTRY(_unregister_object_path, METH_VARARGS|METH_KEYWORDS),
+    {"_new_for_bus", (PyCFunction)DBusPyConnection_NewForBus,
+        METH_CLASS|METH_VARARGS|METH_KEYWORDS,
+        new_for_bus__doc__},
+    {"get_unique_name", (PyCFunction)DBusPyConnection_GetUniqueName,
+        METH_NOARGS,
+        get_unique_name__doc__},
+    {"set_unique_name", (PyCFunction)DBusPyConnection_SetUniqueName,
+        METH_VARARGS,
+        set_unique_name__doc__},
     {NULL},
 #undef ENTRY
 };
diff --git a/_dbus_bindings/module.c b/_dbus_bindings/module.c
index e21792d..cb74ac2 100644
--- a/_dbus_bindings/module.c
+++ b/_dbus_bindings/module.c
@@ -266,7 +266,6 @@ init_dbus_bindings(void)
     if (!dbus_py_init_pending_call()) return;
     if (!dbus_py_init_mainloop()) return;
     if (!dbus_py_init_conn_types()) return;
-    if (!dbus_py_init_bus_types()) return;
 
     this_module = Py_InitModule3("_dbus_bindings", module_functions, module_doc);
     if (!this_module) return;
@@ -283,7 +282,6 @@ init_dbus_bindings(void)
     if (!dbus_py_insert_pending_call(this_module)) return;
     if (!dbus_py_insert_mainloop_types(this_module)) return;
     if (!dbus_py_insert_conn_types(this_module)) return;
-    if (!dbus_py_insert_bus_types(this_module)) return;
 
     if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_NAME",
                                    DBUS_SERVICE_DBUS) < 0) return;
diff --git a/dbus/_dbus.py b/dbus/_dbus.py
index 838b223..6812127 100644
--- a/dbus/_dbus.py
+++ b/dbus/_dbus.py
@@ -29,7 +29,6 @@ __docformat__ = 'reStructuredText'
 import _dbus_bindings
 UTF8String = _dbus_bindings.UTF8String
 DBusException = _dbus_bindings.DBusException
-BusImplementation = _dbus_bindings.BusImplementation
 
 import os
 import logging
@@ -222,7 +221,7 @@ class SignalMatch(object):
                                         **self._args_match)
 
 
-class Bus(BusImplementation, _BusDaemonMixin):
+class Bus(_dbus_bindings.Connection, _BusDaemonMixin):
     """A connection to a DBus daemon.
 
     One of three possible standard buses, the SESSION, SYSTEM,
@@ -288,8 +287,7 @@ class Bus(BusImplementation, _BusDaemonMixin):
         else:
             raise ValueError('invalid bus_type %s' % bus_type)
 
-        bus = _dbus_bindings.BusImplementation.__new__(subclass, bus_type,
-                                                       mainloop=mainloop)
+        bus = subclass._new_for_bus(bus_type, mainloop=mainloop)
 
         bus._bus_type = bus_type
         # _bus_names is used by dbus.service.BusName!
@@ -319,7 +317,7 @@ class Bus(BusImplementation, _BusDaemonMixin):
         t = self._bus_type
         if self.__class__._shared_instances[t] is self:
             del self.__class__._shared_instances[t]
-        BusImplementation.close(self)
+        _dbus_bindings.Connection.close(self)
 
     def get_connection(self):
         """(Deprecated - in new code, just use self)


More information about the dbus mailing list