Merge lp:~zeitgeist/zeitgeist/zeitgeist.client.extensions_interface into lp:zeitgeist/0.1

Proposed by Siegfried Gevatter
Status: Merged
Merged at revision: not available
Proposed branch: lp:~zeitgeist/zeitgeist/zeitgeist.client.extensions_interface
Merge into: lp:zeitgeist/0.1
Diff against target: 263 lines (+94/-97)
3 files modified
_zeitgeist/singleton.py (+1/-1)
test/blacklist-test.py (+14/-1)
zeitgeist/client.py (+79/-95)
To merge this branch: bzr merge lp:~zeitgeist/zeitgeist/zeitgeist.client.extensions_interface
Reviewer Review Type Date Requested Status
Zeitgeist Framework Team Pending
Review via email: mp+17950@code.launchpad.net

Commit message

Add a get_extension method to client.ZeitgeistDBusInterface to easily access interfaces
of extensions.

- The generic stuff from ZeitgeistDBusInterface is refactored into a new
  class, client._DBusInterface, so that it can also be used by the extensions.
- Fix client._DBusInterface.connect() so that it can take any number of argX=
  arguments.
- Remove get_session_bus. dbus.SessionBus() is a singleton.
- blacklist-test.py: add a test-case using the new get_extension() method

To post a comment you must log in.
Revision history for this message
Siegfried Gevatter (rainct) wrote :

Add a get_extension method to client.ZeitgeistDBusInterface to easily access interfaces
of extensions.

- The generic stuff from ZeitgeistDBusInterface is refactored into a new
  class, client._DBusInterface, so that it can also be used by the extensions.
- Fix client._DBusInterface.connect() so that it can take any number of argX=
  arguments.
- Remove get_session_bus. dbus.SessionBus() is a singleton.
- blacklist-test.py: add a test-case using the new get_extension() method

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '_zeitgeist/singleton.py'
2--- _zeitgeist/singleton.py 2009-12-30 19:51:33 +0000
3+++ _zeitgeist/singleton.py 2010-01-23 19:00:29 +0000
4@@ -35,7 +35,7 @@
5
6 def __init__ (self):
7 logging.debug("Checking for another running instance...")
8- sbus = ZeitgeistDBusInterface.get_session_bus()
9+ sbus = dbus.SessionBus()
10 dbus_service = sbus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")
11
12 if dbus_service.NameHasOwner(ZeitgeistDBusInterface.BUS_NAME):
13
14=== modified file 'test/blacklist-test.py'
15--- test/blacklist-test.py 2010-01-04 19:10:40 +0000
16+++ test/blacklist-test.py 2010-01-23 19:00:29 +0000
17@@ -8,6 +8,7 @@
18 import dbus
19
20 sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
21+from zeitgeist.client import ZeitgeistDBusInterface
22 from zeitgeist.datamodel import *
23 from testutils import RemoteTestCase
24
25@@ -22,7 +23,7 @@
26 # engine to come up
27 super(BlacklistTest, self).setUp()
28 obj = dbus.SessionBus().get_object("org.gnome.zeitgeist.Engine",
29- "/org/gnome/zeitgeist/blacklist")
30+ "/org/gnome/zeitgeist/blacklist")
31 self.blacklist = dbus.Interface(obj, "org.gnome.zeitgeist.Blacklist")
32
33 def testClear(self):
34@@ -62,5 +63,17 @@
35 self.assertEquals(1, len(inserted_ids))
36 self.assertTrue(0 != inserted_ids[0])
37
38+ def testBlacklistUsingClientDBusInterface(self):
39+ """
40+ Ensure that get_extension() from client.py method works correctly.
41+ """
42+
43+ del self.blacklist
44+ iface = ZeitgeistDBusInterface()
45+ blacklist = iface.get_extension("Blacklist", "blacklist")
46+ blacklist.SetBlacklist([])
47+ empty = blacklist.GetBlacklist()
48+ self.assertEquals(empty, [])
49+
50 if __name__ == "__main__":
51 unittest.main()
52
53=== modified file 'zeitgeist/client.py'
54--- zeitgeist/client.py 2010-01-15 18:59:16 +0000
55+++ zeitgeist/client.py 2010-01-23 19:00:29 +0000
56@@ -2,7 +2,7 @@
57
58 # Zeitgeist
59 #
60-# Copyright © 2009 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>
61+# Copyright © 2009-2010 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>
62 # Copyright © 2009 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@gmail.com>
63 # Copyright © 2009 Markus Korn <thekorn@gmx.de>
64 #
65@@ -39,23 +39,12 @@
66 logging.basicConfig(level=logging.DEBUG)
67 log = logging.getLogger("zeitgeist.client")
68
69-class ZeitgeistDBusInterface(dbus.Interface):
70- """ Central DBus interface to the zeitgeist engine
71-
72- There does not necessarily have to be one single instance of this
73- interface class, but all instances should share the same state
74- (like use the same bus and be connected to the same proxy). This is
75- achieved by extending the `Borg Pattern` as described by Alex Martelli
76- """
77- __shared_state = {}
78-
79- BUS_NAME = "org.gnome.zeitgeist.Engine"
80- INTERFACE_NAME = "org.gnome.zeitgeist.Log"
81- OBJECT_PATH = "/org/gnome/zeitgeist/log/activity"
82-
83+class _DBusInterface(dbus.Interface):
84+ """Subclass of dbus.Interface adding convenience methods."""
85+
86 @staticmethod
87 def get_members(introspection_xml):
88- """Parses the xml context returned by Introspect() and returns
89+ """Parses the XML context returned by Introspect() and returns
90 a tuple, where the first item is a list of all methods and the
91 second one a list of all signals for the related interface
92 """
93@@ -69,96 +58,91 @@
94 except ValueError:
95 pass
96 return methods, signals
97-
98- @classmethod
99- def get_session_bus(cls):
100- """Returns the bus used by the interface.
101-
102- If there is no bus set, the '_bus' attribute is set to
103- dbus.SessionBus() and returned
104- """
105- return cls.__shared_state.setdefault("_bus", dbus.SessionBus())
106-
107- @classmethod
108- def _get_proxy(cls):
109- """Returns the proxy instance used by the interface.
110-
111- If the current interface has no proxy object set, it tries to
112- generate one. If this fails because no zeitgeist-daemon is
113- running a RuntimeError will be raised
114- """
115- try:
116- return cls.__shared_state["proxy_object"]
117- except KeyError, e:
118- bus = cls.get_session_bus()
119- try:
120- cls.__shared_state["proxy_object"] = bus.get_object(
121- cls.BUS_NAME,
122- cls.OBJECT_PATH
123- )
124- except dbus.exceptions.DBusException, e:
125- if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
126- raise RuntimeError(("Found no running instance of the "
127- "Zeitgeist daemon: %s") % e.get_dbus_message())
128- else:
129- raise
130- else:
131- introspection_xml = cls.__shared_state["proxy_object"].Introspect()
132- methods, signals = cls.get_members(introspection_xml)
133- cls.__shared_state["__methods"] = methods
134- cls.__shared_state["__signals"] = signals
135- return cls.__shared_state["proxy_object"]
136-
137- @classmethod
138- def connect(cls, signal, callback, arg0=None):
139- """Connect a callback to a signal of the current proxy instance """
140- proxy = cls._get_proxy()
141- if signal not in cls.__shared_state["__signals"]:
142- raise TypeError("unknown signal name: %s" %signal)
143- if arg0 is None:
144- proxy.connect_to_signal(
145- signal,
146- callback,
147- dbus_interface=cls.INTERFACE_NAME
148- )
149- else:
150- # TODO: This is ugly and limited to 1 argument. Find a better
151- # way to do it.
152- proxy.connect_to_signal(
153- signal,
154- callback,
155- dbus_interface=cls.INTERFACE_NAME,
156- arg0=arg0
157- )
158-
159- @classmethod
160- def connect_exit(cls, callback):
161- """executes callback when the RemoteInterface exists"""
162- bus = cls.get_session_bus()
163- bus_obj = bus.get_object(dbus.BUS_DAEMON_IFACE, dbus.BUS_DAEMON_PATH)
164+
165+ def connect(self, signal, callback, **kwargs):
166+ """Connect a callback to a signal of the current proxy instance."""
167+ if signal not in self.__signals:
168+ raise TypeError("Unknown signal name: %s" % signal)
169+ self.__proxy.connect_to_signal(
170+ signal,
171+ callback,
172+ dbus_interface=self.INTERFACE_NAME,
173+ **kwargs)
174+
175+ def connect_exit(self, callback):
176+ """Executes callback when the RemoteInterface exists"""
177+ bus_obj = dbus.SessionBus().get_object(dbus.BUS_DAEMON_IFACE,
178+ dbus.BUS_DAEMON_PATH)
179 bus_obj.connect_to_signal(
180 "NameOwnerChanged",
181 lambda *args: callback(),
182 dbus_interface=dbus.BUS_DAEMON_IFACE,
183- arg0=cls.BUS_NAME, #only match dying zeitgeist engines
184- arg2="", #only match services with no new owner
185+ arg0=self.BUS_NAME, # only match dying zeitgeist engines
186+ arg2="", # only match services with no new owner
187 )
188-
189+
190+ def __init__(self, proxy, interface):
191+ self.__proxy = proxy
192+ super(_DBusInterface, self).__init__(proxy, interface)
193+ self.__methods, self.__signals = self.get_members(proxy.Introspect())
194+
195+class ZeitgeistDBusInterface(_DBusInterface):
196+ """ Central DBus interface to the zeitgeist engine
197+
198+ There does not necessarily have to be one single instance of this
199+ interface class, but all instances should share the same state
200+ (like use the same bus and be connected to the same proxy). This is
201+ achieved by extending the `Borg Pattern` as described by Alex Martelli
202+ """
203+ __shared_state = {}
204+
205+ BUS_NAME = "org.gnome.zeitgeist.Engine"
206+ INTERFACE_NAME = "org.gnome.zeitgeist.Log"
207+ OBJECT_PATH = "/org/gnome/zeitgeist/log/activity"
208+
209 @classmethod
210 def version(cls):
211- """ get the API version """
212- proxy = cls._get_proxy()
213- return proxy.get_dbus_method("Get",
214+ """Returns the API version"""
215+ return cls.__shared_state["__proxy"].get_dbus_method("Get",
216 dbus_interface=dbus.PROPERTIES_IFACE)(cls.INTERFACE_NAME, "version")
217
218+ @classmethod
219+ def get_extension(cls, name, path):
220+ """ Returns an interface to the given extension.
221+
222+ Example usage:
223+ >> reg = get_extension("DataSourceRegistry", "data_source_registry")
224+ >> reg.RegisterDataSource(...)
225+ """
226+ if not name in cls.__shared_state["extension_interfaces"]:
227+ interface_name = "org.gnome.zeitgeist.%s" % name
228+ object_path = "/org/gnome/zeitgeist/%s" % path
229+ proxy = dbus.SessionBus().get_object(cls.BUS_NAME, object_path)
230+ iface = _DBusInterface(proxy, interface_name)
231+ iface.BUS_NAME = cls.BUS_NAME
232+ iface.INTERFACE_NAME = interface_name
233+ iface.OBJECT_PATH = object_path
234+ cls.__shared_state["extension_interfaces"][name] = iface
235+
236+ return cls.__shared_state["extension_interfaces"][name]
237+
238 def __init__(self):
239 self.__dict__ = self.__shared_state
240- proxy = self._get_proxy()
241- dbus.Interface.__init__(
242- self,
243- proxy,
244- self.INTERFACE_NAME
245- )
246+ if not "__proxy" in self.__shared_state:
247+ try:
248+ self.__shared_state["__proxy"] = dbus.SessionBus().get_object(
249+ self.BUS_NAME, self.OBJECT_PATH)
250+ except dbus.exceptions.DBusException, e:
251+ if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
252+ raise RuntimeError(
253+ "Found no running zeitgeist-daemon instance: %s" % \
254+ e.get_dbus_message())
255+ else:
256+ raise
257+ if not "extension_interfaces" in self.__shared_state:
258+ self.__shared_state["extension_interfaces"] = {}
259+ super(_DBusInterface, self).__init__(self.__shared_state["__proxy"],
260+ self.INTERFACE_NAME)
261
262 class Monitor(dbus.service.Object):
263 """

Subscribers

People subscribed via source and target branches