From c87b55c6ab30542d5d17f2e2041e4c87b3df712d Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 30 May 2007 15:19:46 +0100 Subject: [PATCH] dbus.service: Make it possible to unexport objects (fd.o#10457) --- dbus/service.py | 33 ++++++++++++++++++++++++++++++++- test/test-client.py | 20 ++++++++++++++++++++ test/test-service.py | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/dbus/service.py b/dbus/service.py index be30b9b..65af3ff 100644 --- a/dbus/service.py +++ b/dbus/service.py @@ -380,7 +380,7 @@ class Object(Interface): is also required. :Parameters: - `conn` : dbus.Connection + `conn` : dbus.connection.Connection The connection on which to export this object. If None, use the Bus associated with the given ``bus_name``, @@ -426,6 +426,37 @@ class Object(Interface): __dbus_object_path__ = property(lambda self: self._object_path, None, None, "The D-Bus object path of this object") + def unexport(self, connection=None, path=None): + """Unexport this object. It will no longer be accessible via D-Bus. + + It's not currently possible to export an object on more than one + connection or with more than one object-path, but this will be + supported in future. + + :Parameters: + `connection` : dbus.connection.Connection or None + Only unexport the object from this Connection. If None, + unexport from all Connections. + `path` : dbus.ObjectPath or other str, or None + Only unexport the object from this object path. If None, + unexport from all object paths. + :Raises LookupError: + if the object was not exported on the requested connection + or path, or (if both are None) was not exported at all. + """ + if self._object_path is None or self._connection is None: + raise LookupError('%r is not exported' % self) + if path is not None and self._object_path != path: + raise LookupError('%r is not exported at path %r' % (self, path)) + if connection is not None and self._connection != connection: + raise LookupError('%r is not exported on %r' % (self, connection)) + + try: + self._connection._unregister_object_path(self._object_path) + finally: + self._connection = None + self._object_path = None + def _unregister_cb(self, connection): _logger.info('Unregistering exported object %r', self) diff --git a/test/test-client.py b/test/test-client.py index 2de34fb..fbf0555 100755 --- a/test/test-client.py +++ b/test/test-client.py @@ -388,6 +388,26 @@ class TestDBusBindings(unittest.TestCase): def testListExportedChildObjects(self): self.assert_(self.iface.TestListExportedChildObjects()) + def testUnexport(self): + # https://bugs.freedesktop.org/show_bug.cgi?id=10457 + self.assert_(not self.iface.HasRemovableObject()) + self.assert_(self.iface.AddRemovableObject()) + self.assert_(self.iface.HasRemovableObject()) + + removable = self.bus.get_object(NAME, OBJECT + '/RemovableObject') + iface = dbus.Interface(removable, IFACE) + self.assert_(iface.IsThere()) + self.assert_(iface.RemoveSelf()) + + self.assert_(not self.iface.HasRemovableObject()) + + # and again... + self.assert_(self.iface.AddRemovableObject()) + self.assert_(self.iface.HasRemovableObject()) + self.assert_(iface.IsThere()) + self.assert_(iface.RemoveSelf()) + self.assert_(not self.iface.HasRemovableObject()) + """ Remove this for now class TestDBusPythonToGLibBindings(unittest.TestCase): def setUp(self): diff --git a/test/test-service.py b/test/test-service.py index c27c55f..8f588c8 100755 --- a/test/test-service.py +++ b/test/test-service.py @@ -48,6 +48,20 @@ NAME = "org.freedesktop.DBus.TestSuitePythonService" IFACE = "org.freedesktop.DBus.TestSuiteInterface" OBJECT = "/org/freedesktop/DBus/TestSuitePythonObject" +class RemovableObject(dbus.service.Object): + # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457 + def __init__(self, bus_name, object_path=OBJECT + '/RemovableObject'): + super(RemovableObject, self).__init__(bus_name, object_path) + + @dbus.service.method(IFACE, in_signature='', out_signature='b') + def IsThere(self): + return True + + @dbus.service.method(IFACE, in_signature='', out_signature='b') + def RemoveSelf(self): + self.unexport() + return True + class TestGObject(ExportedGObject): def __init__(self, bus_name, object_path=OBJECT + '/GObject'): super(TestGObject, self).__init__(bus_name, object_path) @@ -64,6 +78,7 @@ class TestInterface(dbus.service.Interface): class TestObject(dbus.service.Object, TestInterface): def __init__(self, bus_name, object_path=OBJECT): dbus.service.Object.__init__(self, bus_name, object_path) + self._removables = [] """ Echo whatever is sent """ @@ -210,14 +225,27 @@ class TestObject(dbus.service.Object, TestInterface): def WhoAmI(self, sender): return sender + @dbus.service.method(IFACE, in_signature='', out_signature='b') + def AddRemovableObject(self): + # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457 + # Keep the removable object reffed, since that's the use case for this + self._removables.append(RemovableObject(global_name)) + return True + + @dbus.service.method(IFACE, in_signature='', out_signature='b') + def HasRemovableObject(self): + # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457 + objs = session_bus.list_exported_child_objects(OBJECT) + return ('RemovableObject' in objs) + @dbus.service.method(IFACE) def MultipleReturnWithoutSignature(self): # https://bugs.freedesktop.org/show_bug.cgi?id=10174 return dbus.String('abc'), dbus.Int32(123) session_bus = dbus.SessionBus() -name = dbus.service.BusName(NAME, bus=session_bus) -object = TestObject(name) -g_object = TestGObject(name) +global_name = dbus.service.BusName(NAME, bus=session_bus) +object = TestObject(global_name) +g_object = TestGObject(global_name) loop = gobject.MainLoop() loop.run() -- 2.11.4.GIT