From e40ec8e4f29d104b66d78b183300e6bf134c2714 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 30 Apr 2007 11:23:58 +0100 Subject: [PATCH] Remove BusImplementation, removing its remaining functionality to Connection. * 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 --- _dbus_bindings/bus.c | 134 +++++++++++++---------------------------- _dbus_bindings/conn-internal.h | 5 ++ _dbus_bindings/conn-methods.c | 30 +++++++++ _dbus_bindings/module.c | 2 - dbus/_dbus.py | 8 +-- 5 files changed, 79 insertions(+), 100 deletions(-) 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) -- 2.11.4.GIT