[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