Merge lp:~zeitgeist/zeitgeist/mostusedwith into lp:zeitgeist/0.1

Proposed by Seif Lotfy
Status: Merged
Merged at revision: not available
Proposed branch: lp:~zeitgeist/zeitgeist/mostusedwith
Merge into: lp:zeitgeist/0.1
Diff against target: 292 lines (+67/-41)
7 files modified
_zeitgeist/engine/main.py (+23/-18)
_zeitgeist/engine/remote.py (+9/-3)
test/data/apriori_events.js (+1/-1)
test/engine-test.py (+18/-10)
test/remote-test.py (+2/-2)
zeitgeist/client.py (+12/-5)
zeitgeist/datamodel.py (+2/-2)
To merge this branch: bzr merge lp:~zeitgeist/zeitgeist/mostusedwith
Reviewer Review Type Date Requested Status
Zeitgeist Framework Team Pending
Review via email: mp+20154@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Seif Lotfy (seif) wrote :

This branch fixes https://bugs.edge.launchpad.net/zeitgeist/+bug/498878
Please take stabs at it

lp:~zeitgeist/zeitgeist/mostusedwith updated
1347. By Seif Lotfy

fixed test case

1348. By Seif Lotfy

removed second query

1349. By Seif Lotfy

merge and fix issues

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '_zeitgeist/engine/main.py'
--- _zeitgeist/engine/main.py 2010-02-16 19:36:42 +0000
+++ _zeitgeist/engine/main.py 2010-02-25 18:14:12 +0000
@@ -28,7 +28,7 @@
28import logging28import logging
2929
30from zeitgeist.datamodel import Event as OrigEvent, StorageState, TimeRange, \30from zeitgeist.datamodel import Event as OrigEvent, StorageState, TimeRange, \
31 ResultType, get_timestamp_for_now31 ResultType, get_timestamp_for_now, Interpretation
32from _zeitgeist.engine.datamodel import Event, Subject 32from _zeitgeist.engine.datamodel import Event, Subject
33from _zeitgeist.engine.extension import ExtensionsCollection, load_class33from _zeitgeist.engine.extension import ExtensionsCollection, load_class
34from _zeitgeist.engine import constants34from _zeitgeist.engine import constants
@@ -258,7 +258,7 @@
258 return self._find_events(1, *args)258 return self._find_events(1, *args)
259 259
260 def find_related_uris(self, timerange, event_templates, result_event_templates,260 def find_related_uris(self, timerange, event_templates, result_event_templates,
261 result_storage_state):261 result_storage_state, num_results, result_type):
262 """262 """
263 Return a list of subject URIs commonly used together with events263 Return a list of subject URIs commonly used together with events
264 matching the given template, considering data from within the indicated264 matching the given template, considering data from within the indicated
@@ -273,13 +273,14 @@
273 273
274 #templates = event_templates + result_event_templates274 #templates = event_templates + result_event_templates
275 275
276 events = self.find_events( timerange, result_event_templates, 276 events = self.find_events(timerange, result_event_templates,
277 result_storage_state, 0, 1)277 result_storage_state, 0, 1)
278 278
279 subject_uris = []279 subject_uris = []
280 for event in event_templates:280 for event in event_templates:
281 if not event.subjects[0].uri in subject_uris:281 if len(event.subjects) > 0:
282 subject_uris.append(event.subjects[0].uri)282 if not event.subjects[0].uri in subject_uris:
283 subject_uris.append(event.subjects[0].uri)
283 284
284 def create_buckets(events):285 def create_buckets(events):
285 """286 """
@@ -293,37 +294,41 @@
293 buckets.append({})294 buckets.append({})
294 buckets[len(buckets)-1][event.subjects[0].uri] = event295 buckets[len(buckets)-1][event.subjects[0].uri] = event
295 return buckets296 return buckets
297
296 buckets = create_buckets(events)298 buckets = create_buckets(events)
297 299
298 keys_counter = {}300 keys_counter = {}
299 keys_subjects = {}
300 min_support = 0
301 301
302 for bucket in buckets:302 for bucket in buckets:
303 counter = 0303 counter = 0
304 for event in event_templates:304 for event in event_templates:
305 if bucket.has_key(event.subjects[0].uri):305 if bucket.has_key(event.subjects[0].uri):
306 counter += 1306 counter += 1
307 break
307 if counter > 0:308 if counter > 0:
308 for key in bucket.keys():309 for key in bucket.keys():
309 if not key in subject_uris:310 if not key in subject_uris:
310 if not keys_counter.has_key(key):311 if not keys_counter.has_key(key):
311 keys_counter[key] = 0312 keys_counter[key] = 0
312 keys_counter[key] += 1313 keys_counter[key] += 1
313 min_support += 1
314 keys_subjects[key] = bucket[key]
315
316
317 min_support = min_support / len(keys_counter.keys())
318 314
319 sets = [[v, k] for k, v in keys_counter.iteritems()]315 sets = [[v, k] for k, v in keys_counter.iteritems()]
320 sets.sort()316 sets.sort()
321 317 sets.reverse()
322 results = []318
323 for r in sets:319 if result_type == 0:
324 if r[0] >= min_support:320 return map(lambda result: result[1], sets[:num_results])
325 results.append(r[1])321 elif result_type == 1:
326 return results322 events = []
323 for r in sets:
324 event = Event()
325 subject = Subject()
326 subject.uri = r[1]
327 event.set_subjects([subject])
328 events.append(event)
329 events = self.find_events(timerange, events, result_storage_state, num_results, 2)
330 return map(lambda event: event.subjects[0].uri, events)
331 raise NotImplementedError, "Unsupported ResultType."
327 332
328 def insert_events(self, events, sender=None):333 def insert_events(self, events, sender=None):
329 t = time.time()334 t = time.time()
330335
=== modified file '_zeitgeist/engine/remote.py'
--- _zeitgeist/engine/remote.py 2010-01-27 15:08:51 +0000
+++ _zeitgeist/engine/remote.py 2010-02-25 18:14:12 +0000
@@ -4,6 +4,7 @@
4#4#
5# Copyright © 2009-2010 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 © 2010 Seif Lotfy <seif@lotfy.com>
7#8#
8# This program is free software: you can redistribute it and/or modify9# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Lesser General Public License as published by10# it under the terms of the GNU Lesser General Public License as published by
@@ -86,10 +87,10 @@
86 sender=sender))87 sender=sender))
87 88
88 @dbus.service.method(constants.DBUS_INTERFACE,89 @dbus.service.method(constants.DBUS_INTERFACE,
89 in_signature="(xx)a("+constants.SIG_EVENT+")a("+constants.SIG_EVENT+")u",90 in_signature="(xx)a("+constants.SIG_EVENT+")a("+constants.SIG_EVENT+")uuu",
90 out_signature="as")91 out_signature="as")
91 def FindRelatedUris(self, time_range, event_templates,92 def FindRelatedUris(self, time_range, event_templates,
92 result_event_templates, storage_state):93 result_event_templates, storage_state, num_events, result_type):
93 """Warning: This API is EXPERIMENTAL and is not fully supported yet.94 """Warning: This API is EXPERIMENTAL and is not fully supported yet.
94 95
95 Get a list of URIs of subjects which frequently occur together96 Get a list of URIs of subjects which frequently occur together
@@ -122,11 +123,16 @@
122 available. The list of possible values is enumerated in the123 available. The list of possible values is enumerated in the
123 :class:`StorageState <zeitgeist.datamodel.StorageState>` class124 :class:`StorageState <zeitgeist.datamodel.StorageState>` class
124 :type storage_state: unsigned 32 bit integer, DBus signature :const:`u`125 :type storage_state: unsigned 32 bit integer, DBus signature :const:`u`
126 :param num_events: maximal amount of returned events
127 :type num_events: unsigned integer
128 :param result_type: unsigned integer 0 for relevancy 1 for recency
129 :type order: unsigned integer
125 :returns: A list of URIs matching the described criteria130 :returns: A list of URIs matching the described criteria
126 :rtype: An array of strings, DBus signature :const:`as`.131 :rtype: An array of strings, DBus signature :const:`as`.
127 """132 """
133 event_templates = map(Event, event_templates)
128 return _engine.find_related_uris(time_range, event_templates,134 return _engine.find_related_uris(time_range, event_templates,
129 result_event_templates, storage_state)135 result_event_templates, storage_state, num_events, result_type)
130 136
131 @dbus.service.method(constants.DBUS_INTERFACE,137 @dbus.service.method(constants.DBUS_INTERFACE,
132 in_signature="(xx)a("+constants.SIG_EVENT+")uuu",138 in_signature="(xx)a("+constants.SIG_EVENT+")uuu",
133139
=== modified file 'test/data/apriori_events.js'
--- test/data/apriori_events.js 2010-02-07 03:44:19 +0000
+++ test/data/apriori_events.js 2010-02-25 18:14:12 +0000
@@ -390,4 +390,4 @@
390 }390 }
391 ]391 ]
392 }392 }
393]393]
394\ No newline at end of file394\ No newline at end of file
395395
=== modified file 'test/engine-test.py'
--- test/engine-test.py 2010-02-10 02:17:34 +0000
+++ test/engine-test.py 2010-02-25 18:14:12 +0000
@@ -490,28 +490,36 @@
490 TimeRange.always(), [], StorageState.Any, 0, ResultType.LeastRecentActor)490 TimeRange.always(), [], StorageState.Any, 0, ResultType.LeastRecentActor)
491 self.assertEquals([e[0][1] for e in events], ["100", "101", "105"])491 self.assertEquals([e[0][1] for e in events], ["100", "101", "105"])
492492
493 def testRelatedForEvents(self):493 def testRelatedForEventsSortRelevancy(self):
494 import_events("test/data/apriori_events.js", self.engine)494 import_events("test/data/apriori_events.js", self.engine)
495 result = self.engine.find_related_uris(495 result = self.engine.find_related_uris(
496 TimeRange.always(), [Event.new_for_values(subject_uri = "i2")], [],496 TimeRange.always(), [Event.new_for_values(subject_uri = "i2")], [],
497 StorageState.Any)497 StorageState.Any, 2, 0)
498 self.assertEquals(result, ["i1", "i3"])
499
500 def testRelatedForEventsSortRecency(self):
501 import_events("test/data/apriori_events.js", self.engine)
502 result = self.engine.find_related_uris(
503 TimeRange.always(), [Event.new_for_values(subject_uri = "i2")], [],
504 StorageState.Any, 2, 1)
498 self.assertEquals(result, ["i3", "i1"])505 self.assertEquals(result, ["i3", "i1"])
499 506
500 def testRelatedForMultipleEvents(self):507 def testRelatedForMultipleEvents(self):
501 import_events("test/data/apriori_events.js", self.engine)508 import_events("test/data/apriori_events.js", self.engine)
502 result = self.engine.find_related_uris(509 result = self.engine.find_related_uris(
503 TimeRange.always(), [Event.new_for_values(subject_uri = "i1"),510 TimeRange.always(), [Event.new_for_values(subject_uri = "i1"),
504 Event.new_for_values(subject_uri = "i4")],511 Event.new_for_values(subject_uri = "i4")], [],
505 [], StorageState.Any),512 StorageState.Any, 2, 0),
506 self.assertEquals(result, (["i3", "i2"],))513 self.assertEquals(result, (["i2", "i3"],))
507 514
508 def testRelatedForEventsWithManifestation(self):515 def testRelatedForEventsWithManifestation(self):
509 import_events("test/data/apriori_events.js", self.engine)516 import_events("test/data/apriori_events.js", self.engine)
510 result = self.engine.find_related_uris(TimeRange.always(),517 result = self.engine.find_related_uris(TimeRange.always(),
511 [Event.new_for_values(subject_uri = "i4")],518 [Event.new_for_values(subject_uri = "i4")],
512 [Event.new_for_values(subject_manifestation="stfu:File")],519 [Event.new_for_values(subject_manifestation="stfu:File")],
513 StorageState.Any)520 StorageState.Any,
514 self.assertEquals(result, ["i3", "i5", "i1"])521 10, 0)
522 self.assertEquals(result, ["i1", "i5", "i3"])
515523
516if __name__ == "__main__":524if __name__ == "__main__":
517 unittest.main()525 unittest.main()
518526
=== modified file 'test/remote-test.py'
--- test/remote-test.py 2010-02-16 09:43:31 +0000
+++ test/remote-test.py 2010-02-25 18:14:12 +0000
@@ -224,9 +224,9 @@
224 224
225 def callback(uris):225 def callback(uris):
226 mainloop.quit()226 mainloop.quit()
227 self.assertEquals(uris, ["i3", "i2", "i1", "i5"])227 self.assertEquals(uris, ["i2", "i1", "i5", "i3"])
228 228
229 result = self.client.find_related_uris_for_uris(["i4"], callback)229 result = self.client.find_related_uris_for_uris(["i4"], callback, num_events=4, result_type=0)
230 mainloop.run()230 mainloop.run()
231 231
232 def testFindEventsForValues(self):232 def testFindEventsForValues(self):
233233
=== modified file 'zeitgeist/client.py'
--- zeitgeist/client.py 2010-02-16 09:43:31 +0000
+++ zeitgeist/client.py 2010-02-25 18:14:12 +0000
@@ -670,8 +670,8 @@
670 error_handler=self._safe_error_handler(error_handler))670 error_handler=self._safe_error_handler(error_handler))
671 671
672 def find_related_uris_for_events(self, event_templates, uris_reply_handler,672 def find_related_uris_for_events(self, event_templates, uris_reply_handler,
673 time_range = None, result_event_templates=[],673 error_handler=None, time_range = None, result_event_templates=[],
674 storage_state=StorageState.Any, error_handler=None):674 storage_state=StorageState.Any, num_events=10, result_type=0):
675 """675 """
676 Warning: This API is EXPERIMENTAL and is not fully supported yet.676 Warning: This API is EXPERIMENTAL and is not fully supported yet.
677 677
@@ -690,6 +690,10 @@
690 as subjects of events matching these templates690 as subjects of events matching these templates
691 :param storage_state: The returned URIs must have this691 :param storage_state: The returned URIs must have this
692 :class:`storage state <zeitgeist.datamodel.StorageState>`692 :class:`storage state <zeitgeist.datamodel.StorageState>`
693 :param num_events: number of related uris you want to have returned
694 :param result_type: sorting of the results by
695 0 for relevancy
696 1 for recency
693 :param error_handler: An optional callback in case of errors.697 :param error_handler: An optional callback in case of errors.
694 Must take a single argument being the error raised by the698 Must take a single argument being the error raised by the
695 server. The default behaviour in case of errors is to call699 server. The default behaviour in case of errors is to call
@@ -704,15 +708,16 @@
704 time_range = TimeRange.always()708 time_range = TimeRange.always()
705 709
706 self._iface.FindRelatedUris(time_range, event_templates,710 self._iface.FindRelatedUris(time_range, event_templates,
707 result_event_templates, storage_state,711 result_event_templates, storage_state, num_events, result_type,
708 reply_handler=self._safe_reply_handler(uris_reply_handler),712 reply_handler=self._safe_reply_handler(uris_reply_handler),
709 error_handler=self._safe_error_handler(error_handler,713 error_handler=self._safe_error_handler(error_handler,
710 uris_reply_handler,714 uris_reply_handler,
711 []))715 [])
716 )
712 717
713 def find_related_uris_for_uris(self, subject_uris, uris_reply_handler,718 def find_related_uris_for_uris(self, subject_uris, uris_reply_handler,
714 time_range=None, result_event_templates=[],719 time_range=None, result_event_templates=[],
715 storage_state=StorageState.Any, error_handler=None):720 storage_state=StorageState.Any, num_events=10, result_type=0, error_handler=None):
716 """721 """
717 Warning: This API is EXPERIMENTAL and is not fully supported yet.722 Warning: This API is EXPERIMENTAL and is not fully supported yet.
718 723
@@ -728,6 +733,8 @@
728 time_range=time_range,733 time_range=time_range,
729 result_event_templates=result_event_templates,734 result_event_templates=result_event_templates,
730 storage_state=storage_state,735 storage_state=storage_state,
736 num_events = num_events,
737 result_type = result_type,
731 error_handler=error_handler)738 error_handler=error_handler)
732 739
733 def install_monitor (self, time_range, event_templates,740 def install_monitor (self, time_range, event_templates,
734741
=== modified file 'zeitgeist/datamodel.py'
--- zeitgeist/datamodel.py 2010-01-30 13:35:22 +0000
+++ zeitgeist/datamodel.py 2010-02-25 18:14:12 +0000
@@ -4,7 +4,7 @@
4#4#
5# Copyright © 2009 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@gmail.com>5# Copyright © 2009 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@gmail.com>
6# Copyright © 2009 Markus Korn <thekorn@gmx.de>6# Copyright © 2009 Markus Korn <thekorn@gmx.de>
7# Copyright © 2009 Seif Lotfy <seif@lotfy.com>7# Copyright © 2009-2010 Seif Lotfy <seif@lotfy.com>
8# Copyright © 2009-2010 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>8# Copyright © 2009-2010 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>
9#9#
10# This program is free software: you can redistribute it and/or modify10# This program is free software: you can redistribute it and/or modify
@@ -532,7 +532,7 @@
532 "ordered ascendently by the popularity of the actor"))532 "ordered ascendently by the popularity of the actor"))
533 MostRecentActor = enum_factory(("The last event of each different actor"))533 MostRecentActor = enum_factory(("The last event of each different actor"))
534 LeastRecentActor = enum_factory(("The first event of each different actor"))534 LeastRecentActor = enum_factory(("The first event of each different actor"))
535535
536class Subject(list):536class Subject(list):
537 """537 """
538 Represents a subject of an :class:`Event`. This class is both used to538 Represents a subject of an :class:`Event`. This class is both used to

Subscribers

People subscribed via source and target branches