zeitgeist team mailing list archive
-
zeitgeist team
-
Mailing list archive
-
Message #01309
[Merge] lp:~zeitgeist/zeitgeist/hooks into lp:zeitgeist
Markus Korn has proposed merging lp:~zeitgeist/zeitgeist/hooks into lp:zeitgeist.
Requested reviews:
Zeitgeist Framework Team (zeitgeist)
Related bugs:
#604747 Hook before event deletions missing
https://bugs.launchpad.net/bugs/604747
Fixed the "hook renaming"/"add missing hooks"-bug
Renaming of existing hooks (API change!):
* insert_event_hook() -> pre_insert_event()
* get_event_hook() -> get_event()
* delete_events_hook() -> post_delete_events()
Added additional hooks:
* added post_insert_event()
* added pre_delete_events()
changes to the tests:
* added tests for all hooks
--
https://code.launchpad.net/~zeitgeist/zeitgeist/hooks/+merge/31522
Your team Zeitgeist Framework Team is requested to review the proposed merge of lp:~zeitgeist/zeitgeist/hooks into lp:zeitgeist.
=== modified file '_zeitgeist/engine/extension.py'
--- _zeitgeist/engine/extension.py 2010-07-01 08:04:55 +0000
+++ _zeitgeist/engine/extension.py 2010-08-02 10:23:57 +0000
@@ -49,7 +49,7 @@
def __init__(self, engine):
self.engine = weakref.proxy(engine)
- def insert_event_hook(self, event, sender):
+ def pre_insert_event(self, event, sender):
"""
Hook applied to all events before they are inserted into the
log. The returned event is progressively passed through all
@@ -69,7 +69,27 @@
"""
return event
- def get_event_hook(self, event, sender):
+ def post_insert_event(self, event, sender):
+ """
+ Hook applied to all events after they are inserted into the
+ log. The returned event is progressively passed through all
+ extensions before the final result is inserted.
+
+ To block an event completely simply return :const:`None`.
+ The event may also be modified or completely substituted for
+ another event.
+
+ The default implementation of this method simply returns the
+ event as is.
+
+ :param event: An :class:`Event <zeitgeist.datamodel.Event>`
+ instance
+ :param sender: The D-Bus bus name of the client
+ :returns: Nothing
+ """
+ pass
+
+ def get_event(self, event, sender):
"""
Hook applied to all events before they are returned to a client.
The event returned from this method is progressively passed
@@ -84,22 +104,32 @@
event as is.
:param event: An :class:`Event <zeitgeist.datamodel.Event>`
- instance
+ instance or :const:`None`
:param sender: The D-Bus bus name of the client
:returns: The filtered event instance as the client
should see it
"""
return event
- def delete_events_hook(self, ids, sender):
+ def post_delete_events(self, ids, sender):
"""
- Hook applied after events has been deleted from the log.
+ Hook applied after events have been deleted from the log.
:param ids: A list of event ids for the events that has been deleted
:param sender: The unique DBus name for the client triggering the delete
:returns: Nothing
"""
pass
+
+ def pre_delete_events(self, ids, sender):
+ """
+ Hook applied before events are deleted from the log.
+
+ :param ids: A list of event ids for the events that has been deleted
+ :param sender: The unique DBus name for the client triggering the delete
+ :returns: The filtered list of event ids which should be deleted
+ """
+ return ids
def get_extensions():
@@ -233,7 +263,7 @@
# FIXME: We need a stable iteration order
for ext in self.__extensions.itervalues():
- event = ext.get_event_hook(event, sender)
+ event = ext.get_event(event, sender)
if event is None:
# The event has been blocked by
# the extension pretend it's
@@ -241,23 +271,36 @@
continue
return event
- def apply_delete_hooks(self, ids, sender):
- # Apply extension filters if we have an event
-
- # FIXME: We need a stable iteration order
- for ext in self.__extensions.itervalues():
- event = ext.delete_events_hook(ids, sender)
-
-
- def apply_insert_hooks(self, event, sender):
- # FIXME: We need a stable iteration order
- for ext in self.__extensions.itervalues():
- event = ext.insert_event_hook(event, sender)
+ def apply_post_delete(self, ids, sender):
+ # Apply extension filters if we have an event
+
+ # FIXME: We need a stable iteration order
+ for ext in self.__extensions.itervalues():
+ event = ext.post_delete_events(ids, sender)
+
+ def apply_pre_delete(self, ids, sender):
+ # Apply extension filters if we have an event
+
+ # FIXME: We need a stable iteration order
+ for ext in self.__extensions.itervalues():
+ ids = ext.pre_delete_events(ids, sender)
+
+ return ids
+
+ def apply_pre_insert(self, event, sender):
+ # FIXME: We need a stable iteration order
+ for ext in self.__extensions.itervalues():
+ event = ext.pre_insert_event(event, sender)
if event is None:
# The event has been blocked by the extension
return None
return event
+ def apply_post_insert(self, event, sender):
+ # FIXME: We need a stable iteration order
+ for ext in self.__extensions.itervalues():
+ event = ext.post_insert_event(event, sender)
+
def __len__(self):
return len(self.__extensions)
=== modified file '_zeitgeist/engine/extensions/blacklist.py'
--- _zeitgeist/engine/extensions/blacklist.py 2010-01-21 15:31:07 +0000
+++ _zeitgeist/engine/extensions/blacklist.py 2010-08-02 10:23:57 +0000
@@ -68,7 +68,7 @@
log.debug("No existing blacklist config found")
self._blacklist = []
- def insert_event_hook(self, event, sender):
+ def pre_insert_event(self, event, sender):
for tmpl in self._blacklist:
if event.matches_template(tmpl): return None
return event
=== modified file '_zeitgeist/engine/extensions/datasource_registry.py'
--- _zeitgeist/engine/extensions/datasource_registry.py 2010-07-22 22:59:25 +0000
+++ _zeitgeist/engine/extensions/datasource_registry.py 2010-08-02 10:23:57 +0000
@@ -104,7 +104,7 @@
if datasource[DataSource.UniqueId] == unique_id:
return datasource
- def insert_event_hook(self, event, sender):
+ def pre_insert_event(self, event, sender):
for (unique_id, bus_names) in self._running.iteritems():
if sender in bus_names:
datasource = self._get_data_source(unique_id)
=== modified file '_zeitgeist/engine/main.py'
--- _zeitgeist/engine/main.py 2010-07-28 20:10:07 +0000
+++ _zeitgeist/engine/main.py 2010-08-02 10:23:57 +0000
@@ -511,7 +511,7 @@
id = self.next_event_id()
event[0][Event.Id] = id
- event = self.extensions.apply_insert_hooks(event, sender)
+ event = self.extensions.apply_pre_insert(event, sender)
if event is None:
raise AssertionError("Inserting of event was blocked by an extension")
elif not issubclass(type(event), OrigEvent):
@@ -569,6 +569,9 @@
self._mimetype[subject.mimetype],
subject.text,
subject.storage))
+
+ self.extensions.apply_post_insert(event, sender)
+
except sqlite3.IntegrityError:
# The event was already registered.
# Rollback _last_event_id and return the ID of the original event
@@ -606,6 +609,7 @@
return ""
def delete_events (self, ids, sender=None):
+ ids = self.extensions.apply_pre_delete(ids, sender)
# Extract min and max timestamps for deleted events
self._cursor.execute("""
SELECT MIN(timestamp), MAX(timestamp)
@@ -622,7 +626,7 @@
self._cursor.connection.commit()
log.debug("Deleted %s" % map(int, ids))
- self.extensions.apply_delete_hooks(ids, sender)
+ self.extensions.apply_post_delete(ids, sender)
return timestamps
else:
=== modified file 'test/engine-extension-test.py'
--- test/engine-extension-test.py 2010-07-22 09:29:31 +0000
+++ test/engine-extension-test.py 2010-08-02 10:23:57 +0000
@@ -68,14 +68,26 @@
class BlockAllInsertExtension(Extension):
PUBLIC_METHODS = []
-
- def insert_event_hook(self, event, sender):
+ insert_count = 0
+ do_insert = True
+
+ @classmethod
+ def pre_insert_event(cls, event, sender):
+ if cls.do_insert:
+ cls.do_insert = False
+ return event
return None
+ @classmethod
+ def post_insert_event(cls, event, sender):
+ cls.insert_count += 1
+
self.engine.extensions.load(BlockAllInsertExtension)
ids = import_events("test/data/five_events.js", self.engine)
- # all inserts where blocked, so each id is 0 to indicate this
- self.assertEquals(filter(None, ids), [])
+
+ # all but the first one events are blocked
+ self.assertEquals(filter(None, ids), [1])
+ self.assertEquals(BlockAllInsertExtension.insert_count, 1)
def testDeleteHook(self):
@@ -84,14 +96,43 @@
del_ids = []
@classmethod
- def delete_events_hook(self, del_ids, sender):
- self.del_ids = del_ids
+ def pre_delete_events(cls, ids, sender):
+ return ids[:1]
+
+ @classmethod
+ def post_delete_events(cls, del_ids, sender):
+ cls.del_ids = del_ids
self.engine.extensions.load(DeleteAllInsertExtension)
ids = import_events("test/data/five_events.js", self.engine)
- # all inserts where blocked, so each id is 0 to indicate this
- self.engine.delete_events([ids[1]])
- self.assertEquals(DeleteAllInsertExtension.del_ids, [ids[1]])
+
+ # we try to delete the first two events, but the engine will
+ # block the deletion of the seconds one
+ self.engine.delete_events(ids[:2])
+ self.assertEquals(DeleteAllInsertExtension.del_ids, ids[:1])
+
+ def testGetHook(self):
+
+ class BlockGetExtension(Extension):
+ PUBLIC_METHODS = []
+
+ @classmethod
+ def get_event(self, event, sender):
+ if event is not None and int(event.timestamp) > 130:
+ return None
+ return event
+
+ self.engine.extensions.load(BlockGetExtension)
+ ids = import_events("test/data/five_events.js", self.engine)
+
+ # request all events, but only the first event object
+ # will be returned, the other events are blocked by the extension
+ # and presented as `None`
+ events = self.engine.get_events(ids)
+ self.assertEqual(len(filter(lambda x: x is not None, events)), 1)
+
+
+
if __name__ == "__main__":
unittest.main()