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
=== modified file '_zeitgeist/singleton.py'
--- _zeitgeist/singleton.py 2009-12-30 19:51:33 +0000
+++ _zeitgeist/singleton.py 2010-01-23 19:00:29 +0000
@@ -35,7 +35,7 @@
35 35
36 def __init__ (self):36 def __init__ (self):
37 logging.debug("Checking for another running instance...")37 logging.debug("Checking for another running instance...")
38 sbus = ZeitgeistDBusInterface.get_session_bus()38 sbus = dbus.SessionBus()
39 dbus_service = sbus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")39 dbus_service = sbus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")
40 40
41 if dbus_service.NameHasOwner(ZeitgeistDBusInterface.BUS_NAME):41 if dbus_service.NameHasOwner(ZeitgeistDBusInterface.BUS_NAME):
4242
=== modified file 'test/blacklist-test.py'
--- test/blacklist-test.py 2010-01-04 19:10:40 +0000
+++ test/blacklist-test.py 2010-01-23 19:00:29 +0000
@@ -8,6 +8,7 @@
8import dbus8import dbus
99
10sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))10sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
11from zeitgeist.client import ZeitgeistDBusInterface
11from zeitgeist.datamodel import *12from zeitgeist.datamodel import *
12from testutils import RemoteTestCase13from testutils import RemoteTestCase
1314
@@ -22,7 +23,7 @@
22 # engine to come up23 # engine to come up
23 super(BlacklistTest, self).setUp()24 super(BlacklistTest, self).setUp()
24 obj = dbus.SessionBus().get_object("org.gnome.zeitgeist.Engine",25 obj = dbus.SessionBus().get_object("org.gnome.zeitgeist.Engine",
25 "/org/gnome/zeitgeist/blacklist")26 "/org/gnome/zeitgeist/blacklist")
26 self.blacklist = dbus.Interface(obj, "org.gnome.zeitgeist.Blacklist")27 self.blacklist = dbus.Interface(obj, "org.gnome.zeitgeist.Blacklist")
27 28
28 def testClear(self):29 def testClear(self):
@@ -62,5 +63,17 @@
62 self.assertEquals(1, len(inserted_ids))63 self.assertEquals(1, len(inserted_ids))
63 self.assertTrue(0 != inserted_ids[0])64 self.assertTrue(0 != inserted_ids[0])
6465
66 def testBlacklistUsingClientDBusInterface(self):
67 """
68 Ensure that get_extension() from client.py method works correctly.
69 """
70
71 del self.blacklist
72 iface = ZeitgeistDBusInterface()
73 blacklist = iface.get_extension("Blacklist", "blacklist")
74 blacklist.SetBlacklist([])
75 empty = blacklist.GetBlacklist()
76 self.assertEquals(empty, [])
77
65if __name__ == "__main__":78if __name__ == "__main__":
66 unittest.main()79 unittest.main()
6780
=== modified file 'zeitgeist/client.py'
--- zeitgeist/client.py 2010-01-15 18:59:16 +0000
+++ zeitgeist/client.py 2010-01-23 19:00:29 +0000
@@ -2,7 +2,7 @@
22
3# Zeitgeist3# Zeitgeist
4#4#
5# Copyright © 2009 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>5# Copyright © 2009-2010 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>
6# Copyright © 2009 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@gmail.com>6# Copyright © 2009 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@gmail.com>
7# Copyright © 2009 Markus Korn <thekorn@gmx.de>7# Copyright © 2009 Markus Korn <thekorn@gmx.de>
8#8#
@@ -39,23 +39,12 @@
39logging.basicConfig(level=logging.DEBUG)39logging.basicConfig(level=logging.DEBUG)
40log = logging.getLogger("zeitgeist.client")40log = logging.getLogger("zeitgeist.client")
4141
42class ZeitgeistDBusInterface(dbus.Interface):42class _DBusInterface(dbus.Interface):
43 """ Central DBus interface to the zeitgeist engine43 """Subclass of dbus.Interface adding convenience methods."""
44 44
45 There does not necessarily have to be one single instance of this
46 interface class, but all instances should share the same state
47 (like use the same bus and be connected to the same proxy). This is
48 achieved by extending the `Borg Pattern` as described by Alex Martelli
49 """
50 __shared_state = {}
51
52 BUS_NAME = "org.gnome.zeitgeist.Engine"
53 INTERFACE_NAME = "org.gnome.zeitgeist.Log"
54 OBJECT_PATH = "/org/gnome/zeitgeist/log/activity"
55
56 @staticmethod45 @staticmethod
57 def get_members(introspection_xml):46 def get_members(introspection_xml):
58 """Parses the xml context returned by Introspect() and returns47 """Parses the XML context returned by Introspect() and returns
59 a tuple, where the first item is a list of all methods and the48 a tuple, where the first item is a list of all methods and the
60 second one a list of all signals for the related interface49 second one a list of all signals for the related interface
61 """50 """
@@ -69,96 +58,91 @@
69 except ValueError:58 except ValueError:
70 pass59 pass
71 return methods, signals60 return methods, signals
72 61
73 @classmethod62 def connect(self, signal, callback, **kwargs):
74 def get_session_bus(cls):63 """Connect a callback to a signal of the current proxy instance."""
75 """Returns the bus used by the interface.64 if signal not in self.__signals:
76 65 raise TypeError("Unknown signal name: %s" % signal)
77 If there is no bus set, the '_bus' attribute is set to66 self.__proxy.connect_to_signal(
78 dbus.SessionBus() and returned67 signal,
79 """68 callback,
80 return cls.__shared_state.setdefault("_bus", dbus.SessionBus())69 dbus_interface=self.INTERFACE_NAME,
81 70 **kwargs)
82 @classmethod71
83 def _get_proxy(cls):72 def connect_exit(self, callback):
84 """Returns the proxy instance used by the interface.73 """Executes callback when the RemoteInterface exists"""
85 74 bus_obj = dbus.SessionBus().get_object(dbus.BUS_DAEMON_IFACE,
86 If the current interface has no proxy object set, it tries to75 dbus.BUS_DAEMON_PATH)
87 generate one. If this fails because no zeitgeist-daemon is
88 running a RuntimeError will be raised
89 """
90 try:
91 return cls.__shared_state["proxy_object"]
92 except KeyError, e:
93 bus = cls.get_session_bus()
94 try:
95 cls.__shared_state["proxy_object"] = bus.get_object(
96 cls.BUS_NAME,
97 cls.OBJECT_PATH
98 )
99 except dbus.exceptions.DBusException, e:
100 if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
101 raise RuntimeError(("Found no running instance of the "
102 "Zeitgeist daemon: %s") % e.get_dbus_message())
103 else:
104 raise
105 else:
106 introspection_xml = cls.__shared_state["proxy_object"].Introspect()
107 methods, signals = cls.get_members(introspection_xml)
108 cls.__shared_state["__methods"] = methods
109 cls.__shared_state["__signals"] = signals
110 return cls.__shared_state["proxy_object"]
111
112 @classmethod
113 def connect(cls, signal, callback, arg0=None):
114 """Connect a callback to a signal of the current proxy instance """
115 proxy = cls._get_proxy()
116 if signal not in cls.__shared_state["__signals"]:
117 raise TypeError("unknown signal name: %s" %signal)
118 if arg0 is None:
119 proxy.connect_to_signal(
120 signal,
121 callback,
122 dbus_interface=cls.INTERFACE_NAME
123 )
124 else:
125 # TODO: This is ugly and limited to 1 argument. Find a better
126 # way to do it.
127 proxy.connect_to_signal(
128 signal,
129 callback,
130 dbus_interface=cls.INTERFACE_NAME,
131 arg0=arg0
132 )
133
134 @classmethod
135 def connect_exit(cls, callback):
136 """executes callback when the RemoteInterface exists"""
137 bus = cls.get_session_bus()
138 bus_obj = bus.get_object(dbus.BUS_DAEMON_IFACE, dbus.BUS_DAEMON_PATH)
139 bus_obj.connect_to_signal(76 bus_obj.connect_to_signal(
140 "NameOwnerChanged",77 "NameOwnerChanged",
141 lambda *args: callback(),78 lambda *args: callback(),
142 dbus_interface=dbus.BUS_DAEMON_IFACE,79 dbus_interface=dbus.BUS_DAEMON_IFACE,
143 arg0=cls.BUS_NAME, #only match dying zeitgeist engines80 arg0=self.BUS_NAME, # only match dying zeitgeist engines
144 arg2="", #only match services with no new owner81 arg2="", # only match services with no new owner
145 )82 )
146 83
84 def __init__(self, proxy, interface):
85 self.__proxy = proxy
86 super(_DBusInterface, self).__init__(proxy, interface)
87 self.__methods, self.__signals = self.get_members(proxy.Introspect())
88
89class ZeitgeistDBusInterface(_DBusInterface):
90 """ Central DBus interface to the zeitgeist engine
91
92 There does not necessarily have to be one single instance of this
93 interface class, but all instances should share the same state
94 (like use the same bus and be connected to the same proxy). This is
95 achieved by extending the `Borg Pattern` as described by Alex Martelli
96 """
97 __shared_state = {}
98
99 BUS_NAME = "org.gnome.zeitgeist.Engine"
100 INTERFACE_NAME = "org.gnome.zeitgeist.Log"
101 OBJECT_PATH = "/org/gnome/zeitgeist/log/activity"
102
147 @classmethod103 @classmethod
148 def version(cls):104 def version(cls):
149 """ get the API version """105 """Returns the API version"""
150 proxy = cls._get_proxy()106 return cls.__shared_state["__proxy"].get_dbus_method("Get",
151 return proxy.get_dbus_method("Get",
152 dbus_interface=dbus.PROPERTIES_IFACE)(cls.INTERFACE_NAME, "version")107 dbus_interface=dbus.PROPERTIES_IFACE)(cls.INTERFACE_NAME, "version")
153 108
109 @classmethod
110 def get_extension(cls, name, path):
111 """ Returns an interface to the given extension.
112
113 Example usage:
114 >> reg = get_extension("DataSourceRegistry", "data_source_registry")
115 >> reg.RegisterDataSource(...)
116 """
117 if not name in cls.__shared_state["extension_interfaces"]:
118 interface_name = "org.gnome.zeitgeist.%s" % name
119 object_path = "/org/gnome/zeitgeist/%s" % path
120 proxy = dbus.SessionBus().get_object(cls.BUS_NAME, object_path)
121 iface = _DBusInterface(proxy, interface_name)
122 iface.BUS_NAME = cls.BUS_NAME
123 iface.INTERFACE_NAME = interface_name
124 iface.OBJECT_PATH = object_path
125 cls.__shared_state["extension_interfaces"][name] = iface
126
127 return cls.__shared_state["extension_interfaces"][name]
128
154 def __init__(self):129 def __init__(self):
155 self.__dict__ = self.__shared_state130 self.__dict__ = self.__shared_state
156 proxy = self._get_proxy()131 if not "__proxy" in self.__shared_state:
157 dbus.Interface.__init__(132 try:
158 self,133 self.__shared_state["__proxy"] = dbus.SessionBus().get_object(
159 proxy,134 self.BUS_NAME, self.OBJECT_PATH)
160 self.INTERFACE_NAME135 except dbus.exceptions.DBusException, e:
161 )136 if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
137 raise RuntimeError(
138 "Found no running zeitgeist-daemon instance: %s" % \
139 e.get_dbus_message())
140 else:
141 raise
142 if not "extension_interfaces" in self.__shared_state:
143 self.__shared_state["extension_interfaces"] = {}
144 super(_DBusInterface, self).__init__(self.__shared_state["__proxy"],
145 self.INTERFACE_NAME)
162146
163class Monitor(dbus.service.Object):147class Monitor(dbus.service.Object):
164 """148 """

Subscribers

People subscribed via source and target branches