def __init__(self): self[0] = all_events template2 = Event.new_for_values(interpretation = \ Interpretation.ACCESS_EVENT) self[1] = ["Access Events", \ "Fetch all the access events", \ template2, \ TimeRange.always(), \ ResultType.MostRecentEvents] template3 = Event.new_for_values(interpretation = \ Interpretation.LEAVE_EVENT) self[2] = ["Leave Events", \ "Fetch all the leave events", \ template3, \ TimeRange.always(), \ ResultType.MostRecentEvents] template4 = Event.new_for_values(interpretation = \ Interpretation.MODIFY_EVENT) self[3] = ["Modify Events", \ "Fetch all the modify events", \ template4, \ TimeRange.always(), \ ResultType.MostRecentEvents] template5 = Event.new_for_values(actor = "application://banshee.desktop") self[4] = ["Banshee events", \ "All the Banshee related events", \ template5, \ TimeRange.always(), \ ResultType.MostRecentEvents]
def testFindEventIdsForTimeRange(self): # Make sure that filtering by time range we get the right ones retrieved_ids = self.findEventIdsAndWait([], timerange=TimeRange(133, 153)) self.assertEqual(retrieved_ids, [4, 2, 3]) # TS: [133, 143, 153] retrieved_ids = self.findEventIdsAndWait([], timerange=TimeRange(163, 163)) self.assertEqual(retrieved_ids, [5]) # Timestamps: [163]
def run(self, keywords, path, regex=False): """Run the Zeitgeist SearchMethod.""" self.stop_search = False event_template = Event() time_range = TimeRange.from_seconds_ago(60 * 3600 * 24) # 60 days at most results = iface.FindEvents( time_range, # (min_timestamp, max_timestamp) in milliseconds [event_template, ], datamodel.StorageState.Any, 1000, datamodel.ResultType.MostRecentSubjects ) results = (datamodel.Event(result) for result in results) uniques = [] for event in results: if self.stop_search: break for subject in event.get_subjects(): uri = str(subject.uri) if uri.startswith('file://'): fullname = str(uri[7:]) filepath, filename = os.path.split(fullname) if keywords.lower() in filename and \ uri not in uniques and \ path in filepath: uniques.append(uri) yield fullname self.stop_search = True
def testMonitorInstallRemoval(self): result = [] mainloop = self.create_mainloop() tmpl = Event.new_for_values(interpretation="stfu:OpenEvent") @asyncTestMethod(mainloop) def notify_insert_handler(notification_type, events): pass @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") mon = self.client.install_monitor(TimeRange.always(), [tmpl], notify_insert_handler, notify_delete_handler) @asyncTestMethod(mainloop) def removed_handler(result_state): result.append(result_state) mainloop.quit() self.client.remove_monitor(mon, removed_handler) mainloop.run() self.assertEqual(1, len(result)) self.assertEqual(1, result.pop())
def testMonitorReconnection(self): result = [] mainloop = self.create_mainloop() events = parse_events("test/data/three_events.js") @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): result.extend(events) mainloop.quit() @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") self.client.install_monitor(TimeRange.always(), [], notify_insert_handler, notify_delete_handler) # Restart the Zeitgeist daemon to test automagic monitor re-connection self.kill_daemon() self.spawn_daemon() # Insert events in idle loop to give the reconnection logic enough time GLib.idle_add(lambda *args: self.client.insert_events(events)) mainloop.run() self.assertEqual(3, len(result))
def testMonitorDeleteNonExistingEvent(self): result = [] mainloop = self.create_mainloop(None) events = parse_events("test/data/five_events.js") @asyncTestMethod(mainloop) def timeout(): # We want this timeout - we should not get informed # about deletions of non-existing events mainloop.quit() return False @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): event_ids = [ev.id for ev in events] self.client.delete_events([9999999]) @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Notified about deletion of non-existing events %s", events) self.client.install_monitor(TimeRange(125, 145), [], notify_insert_handler, notify_delete_handler) GLib.timeout_add_seconds(5, timeout) self.client.insert_events(events) mainloop.run()
def testMonitorInstallRemoval(self): result = [] mainloop = self.create_mainloop() tmpl = Event.new_for_values(interpretation="stfu:OpenEvent") @asyncTestMethod(mainloop) def notify_insert_handler(notification_type, events): pass @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") mon = self.client.install_monitor(TimeRange.always(), [tmpl], notify_insert_handler, notify_delete_handler) @asyncTestMethod(mainloop) def removed_handler(result_state): result.append(result_state) mainloop.quit() self.client.remove_monitor(mon, removed_handler) mainloop.run() self.assertEquals(1, len(result)) self.assertEquals(1, result.pop())
def testMonitorReconnection(self): result = [] mainloop = self.create_mainloop() events = parse_events("test/data/three_events.js") @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): result.extend(events) mainloop.quit() @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") self.client.install_monitor(TimeRange.always(), [], notify_insert_handler, notify_delete_handler) # Restart the Zeitgeist daemon to test automagic monitor re-connection self.kill_daemon() self.spawn_daemon() # Insert events in idle loop to give the reconnection logic enough time gobject.idle_add(lambda *args: self.client.insert_events(events)) mainloop.run() self.assertEquals(3, len(result))
def buildQuery(chromosome): storage = StorageState.Any numResults = 10 if chromosome[0] == 0 or chromosome[1] == 0: timerange = TimeRange.always() else: timerange = (chromosome[0]*60*60*24, chromosome[1]*60*60*24) if timerange[0] > timerange[1]: timerange = (timerange[1], timerange[0]) searchType = chromosome[2]%30 eventTemplate = {} subjectTemplate = {} if chromosome[3]%2 == 0: subjectTemplate['interpretation'] = random.choice(list(Interpretation.EVENT_INTERPRETATION.get_children())) if chromosome[4]%2 == 0: subjectTemplate['manifestation'] = random.choice(list(Manifestation.EVENT_MANIFESTATION.get_children())) if chromosome[5]%2 == 0: eventTemplate['actor'] = "application://google-chrome.desktop" if chromosome[6]%2 == 0: subjectTemplate['origin'] = "http://google.com" if chromosome[7]%2 == 0: subjectTemplate['uri'] = "http://google.com" if chromosome[8]%2 == 0: subjectTemplate['mimetype'] = "text/html" if chromosome[9]%2 == 0: subjectTemplate['text'] = "fish" if chromosome[10]%2 == 0: eventTemplate['manifestation'] = random.choice(list(Manifestation.EVENT_MANIFESTATION.get_children())) if chromosome[11]%2 == 0: eventTemplate['interpretation'] = random.choice(list(Interpretation.EVENT_INTERPRETATION.get_children())) templates = [Event.new_for_values(subjects=[Subject.new_for_values(**subjectTemplate)], **eventTemplate)] return (timerange, templates, storage, numResults, searchType)
def transport(self, events=[]): ''' Update couchdb with events ''' self.log(logging.INFO, "Insert events into couchdb") if events == []: last = self.last_transaction() #get events if (last): self.log(logging.INFO, "getting itens created after %s", last) #update of database #count from_last_to_now = TimeRange.until_now() from_last_to_now.begin = int(last) + 1 _events = self._zdclient.FindEvents( #timerange from_last_to_now, [], StorageState.Any, 0, ResultType.LeastRecentEvents ) else: self.log(logging.INFO, "First interaction, getting last item") #fist interaction with database _events = self._zdclient.FindEvents( #timerange TimeRange.always(), [], StorageState.Any, 1, ResultType.MostRecentEvents ) #convert into records records = [] [records.append( self.zgToDb(Event(event)) if isinstance(event, dbus.Struct)\ else self.zgToDb(event) if isinstance(event, Event)\ else event ) for event in events] #put on couchdb self.log(logging.INFO, "put %s records in couchdb", len(records)) self.put_records(records) #save last as last_transaction if len(records): self.last_transaction(records[-1]['timestamp'])
def find_related_uris_for_events(self, event_templates, uris_reply_handler, error_handler=None, time_range=None, result_event_templates=[], storage_state=StorageState.Any, num_events=10, result_type=0): """ Warning: This API is EXPERIMENTAL and is not fully supported yet. Get a list of URIs of subjects which frequently occur together with events matching `event_templates`. Possibly restricting to `time_range` or to URIs that occur as subject of events matching `result_event_templates`. :param event_templates: Templates for events that you want to find URIs that relate to :param uris_reply_handler: A callback that takes a list of strings with the URIs of the subjects related to the requested events :param time_range: A :class:`TimeRange <zeitgeist.datamodel.TimeRange>` to restrict to :param result_event_templates: The related URIs must occur as subjects of events matching these templates :param storage_state: The returned URIs must have this :class:`storage state <zeitgeist.datamodel.StorageState>` :param num_events: number of related uris you want to have returned :param result_type: sorting of the results by 0 for relevancy 1 for recency :param error_handler: An optional callback in case of errors. Must take a single argument being the error raised by the server. The default behaviour in case of errors is to call `uris_reply_handler` with an empty list and print an error message on standard error. """ if not callable(uris_reply_handler): raise TypeError("Reply handler not callable, found %s" % uris_reply_handler) if time_range is None: time_range = TimeRange.until_now() self._iface.FindRelatedUris( time_range, event_templates, result_event_templates, storage_state, num_events, result_type, reply_handler=self._safe_reply_handler(uris_reply_handler), error_handler=self._safe_error_handler(error_handler, uris_reply_handler, []))
def handle_most(results): self.most = [] for event in results: if exists(event.subjects[0].uri): self.most.append([event.subjects[0].uri, event.subjects[0].text]) if len(self.most) >= 5: break reformat_strings() self.update_menu() if not self.monitor: self.monitor = CLIENT.install_monitor(TimeRange.always(), [template], self.update_entries, self.update_entries)
def testTwoMonitorsDeleteEvents(self): result1 = [] result2 = [] mainloop = self.create_mainloop() events = parse_events("test/data/five_events.js") @asyncTestMethod(mainloop) def check_ok(): if len(result1) == 2 and len(result2) == 2: mainloop.quit() @asyncTestMethod(mainloop) def notify_insert_handler1(time_range, events): event_ids = [ev.id for ev in events] self.client.delete_events(event_ids) @asyncTestMethod(mainloop) def notify_delete_handler1(time_range, event_ids): result1.extend(event_ids) check_ok() @asyncTestMethod(mainloop) def notify_delete_handler2(time_range, event_ids): result2.extend(event_ids) check_ok() self.client.install_monitor(TimeRange(125, 145), [], notify_insert_handler1, notify_delete_handler1) self.client.install_monitor(TimeRange(125, 145), [], lambda x, y: x, notify_delete_handler2) self.client.insert_events(events) mainloop.run() self.assertEqual(2, len(result1)) self.assertEqual(2, len(result2))
def monitor(self, timerange=TimeRange.always(), event_templates=[], insert_handler=None, delete_handler=None): ''' Monitor for new and events deletes timerange: TimeRange to monitore event_templates: array with Event that need match to monitore insert_handler: function that receive insert events delete_handler: function that receive ids of removed events ''' def insert(timerange, events, *args, **kws): if insert_handler: insert_handler(timerange, events, *args, **kws) else: self.transport(events) def delete(timerange, events_ids, *args, **kws): if delete_handler: delete_handler(timerange, events_ids, *args, **kws) else: self.purge(events_ids) self._zclient.install_monitor(TimeRange.always(), [], insert, delete)
def _event_id_request_handler(uris): templates = [] if len(uris) > 0: for i, uri in enumerate(uris): sub = Subject.new_for_values(uri=uri) templates += [ Event.new_for_values(subjects=[sub]), ] CLIENT.find_event_ids_for_templates( templates, _event_request_handler, TimeRange.until_now(), num_events=len(uris), storage_state=StorageState.Available, result_type=ResultType.MostRecentSubjects)
def NotifyInsert(self, time_range, events): """ Receive notification that a set of events matching the monitor's templates has been recorded in the log. This method is the raw DBus callback and should normally not be overridden. Events are received via the *insert_callback* argument given in the constructor to this class. :param time_range: A two-tuple of 64 bit integers with the minimum and maximum timestamps found in *events*. DBus signature (xx) :param events: A list of DBus event structs, signature a(asaasay) with the events matching the monitor. See :meth:`ZeitgeistClient.install_monitor` """ self._insert_callback(TimeRange(time_range[0], time_range[1]), map(self._event_type, events))
def find_related_uris_for_events(self, event_templates, uris_reply_handler, error_handler=None, time_range = None, result_event_templates=[], storage_state=StorageState.Any, num_events=10, result_type=0): """ Warning: This API is EXPERIMENTAL and is not fully supported yet. Get a list of URIs of subjects which frequently occur together with events matching `event_templates`. Possibly restricting to `time_range` or to URIs that occur as subject of events matching `result_event_templates`. :param event_templates: Templates for events that you want to find URIs that relate to :param uris_reply_handler: A callback that takes a list of strings with the URIs of the subjects related to the requested events :param time_range: A :class:`TimeRange <zeitgeist.datamodel.TimeRange>` to restrict to :param result_event_templates: The related URIs must occur as subjects of events matching these templates :param storage_state: The returned URIs must have this :class:`storage state <zeitgeist.datamodel.StorageState>` :param num_events: number of related uris you want to have returned :param result_type: sorting of the results by 0 for relevancy 1 for recency :param error_handler: An optional callback in case of errors. Must take a single argument being the error raised by the server. The default behaviour in case of errors is to call `uris_reply_handler` with an empty list and print an error message on standard error. """ if not callable(uris_reply_handler): raise TypeError( "Reply handler not callable, found %s" % uris_reply_handler) if time_range is None: time_range = TimeRange.until_now() self._iface.FindRelatedUris(time_range, event_templates, result_event_templates, storage_state, num_events, result_type, reply_handler=self._safe_reply_handler(uris_reply_handler), error_handler=self._safe_error_handler(error_handler, uris_reply_handler, []) )
def buildQuery(chromosome): storage = StorageState.Any numResults = 10 if chromosome[0] == 0 or chromosome[1] == 0: timerange = TimeRange.always() else: timerange = (chromosome[0] * 60 * 60 * 24, chromosome[1] * 60 * 60 * 24) if timerange[0] > timerange[1]: timerange = (timerange[1], timerange[0]) searchType = chromosome[2] % 30 eventTemplate = {} subjectTemplate = {} if chromosome[3] % 2 == 0: subjectTemplate['interpretation'] = random.choice( list(Interpretation.EVENT_INTERPRETATION.get_children())) if chromosome[4] % 2 == 0: subjectTemplate['manifestation'] = random.choice( list(Manifestation.EVENT_MANIFESTATION.get_children())) if chromosome[5] % 2 == 0: eventTemplate['actor'] = "application://google-chrome.desktop" if chromosome[6] % 2 == 0: subjectTemplate['origin'] = "http://google.com" if chromosome[7] % 2 == 0: subjectTemplate['uri'] = "http://google.com" if chromosome[8] % 2 == 0: subjectTemplate['mimetype'] = "text/html" if chromosome[9] % 2 == 0: subjectTemplate['text'] = "fish" if chromosome[10] % 2 == 0: eventTemplate['manifestation'] = random.choice( list(Manifestation.EVENT_MANIFESTATION.get_children())) if chromosome[11] % 2 == 0: eventTemplate['interpretation'] = random.choice( list(Interpretation.EVENT_INTERPRETATION.get_children())) templates = [ Event.new_for_values( subjects=[Subject.new_for_values(**subjectTemplate)], **eventTemplate) ] return (timerange, templates, storage, numResults, searchType)
def NotifyDelete(self, time_range, event_ids): """ Receive notification that a set of events within the monitor's matched time range has been deleted. Note that this notification will also be emitted for deleted events that doesn't match the event templates of the monitor. It's just the time range which is considered here. This method is the raw DBus callback and should normally not be overridden. Events are received via the *delete_callback* argument given in the constructor to this class. :param time_range: A two-tuple of 64 bit integers with the minimum and maximum timestamps found in *events*. DBus signature (xx) :param event_ids: A list of event ids. An event id is simply and unsigned 32 bit integer. DBus signature au. """ self._delete_callback(TimeRange(time_range[0], time_range[1]), event_ids)
def testMonitorInsertEvents(self): result = [] mainloop = self.create_mainloop() tmpl = Event.new_for_values(interpretation="stfu:OpenEvent") events = parse_events("test/data/five_events.js") @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): result.extend(events) mainloop.quit() @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") self.client.install_monitor(TimeRange.always(), [tmpl], notify_insert_handler, notify_delete_handler) self.client.insert_events(events) mainloop.run() self.assertEquals(2, len(result))
def testMonitorDeleteEvents(self): result = [] mainloop = self.create_mainloop() events = parse_events("test/data/five_events.js") @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): event_ids = [ev.id for ev in events] self.client.delete_events(event_ids) @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() result.extend(event_ids) self.client.install_monitor(TimeRange(125, 145), [], notify_insert_handler, notify_delete_handler) self.client.insert_events(events) mainloop.run() self.assertEqual(2, len(result))
def testMonitorInsertEventsWithNegatedSubjectTemplate(self): result = [] mainloop = self.create_mainloop() tmpl = Event.new_for_values( subjects=[Subject.new_for_values(uri="!file:///tmp/bar.txt")]) events = parse_events("test/data/five_events.js") @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): result.extend(events) mainloop.quit() @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") self.client.install_monitor(TimeRange.always(), [tmpl], notify_insert_handler, notify_delete_handler) self.client.insert_events(events) mainloop.run() self.assertEquals(4, len(result))
def testMonitorInsertEvents(self): result = [] mainloop = self.create_mainloop() tmpl = Event.new_for_values(interpretation="stfu:OpenEvent") events = parse_events("test/data/five_events.js") @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): result.extend(events) mainloop.quit() @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") self.client.install_monitor(TimeRange.always(), [tmpl], notify_insert_handler, notify_delete_handler) self.client.insert_events(events) mainloop.run() self.assertEqual(2, len(result))
def __init__(self): super(Store, self).__init__() self.run_build_thread = False self._days = {} self._day_connections = {} self._deleted_uris = [] #Search for uris that have been deleted in order to not display them. #FIXME we should add a timestamp field with the deleted uri #to prevent that a recent event with same uri than an older and deleted one #isn't displayed. - cando self._deleted_uris = [] subject = Subject() subject.uri = "!application://*" template = Event.new_for_values( interpretation=Interpretation.DELETE_EVENT.uri, subjects=[subject], actor="!application://activity-log-manager.desktop") CLIENT.find_events_for_templates((template, ), self.__set_deleted_uris, TimeRange.until_now(), num_events=MAXEVENTS) global currentTimestamp, histogramLoaderCounter today = datetime.date.today() currentTimestamp = time.mktime(today.timetuple()) days_population = CLIENT_EXTENSION.GetHistogramData() for i in xrange(50 * 6): date = datetime.date.fromtimestamp(currentTimestamp) day = Day(date, days_population) self.add_day(date, day) currentTimestamp -= 86400 for day in self.days[-6:]: day.load_ids() content_objects.AbstractContentObject.connect_to_manager( "add", self.add_content_object_with_new_type) content_objects.AbstractContentObject.connect_to_manager( "remove", self.remove_content_objects_with_type)
def testMonitorInsertEventsWithNegatedSubjectTemplate(self): result = [] mainloop = self.create_mainloop() tmpl = Event.new_for_values( subjects=[Subject.new_for_values(uri="!file:///tmp/bar.txt")]) events = parse_events("test/data/five_events.js") @asyncTestMethod(mainloop) def notify_insert_handler(time_range, events): result.extend(events) mainloop.quit() @asyncTestMethod(mainloop) def notify_delete_handler(time_range, event_ids): mainloop.quit() self.fail("Unexpected delete notification") self.client.install_monitor(TimeRange.always(), [tmpl], notify_insert_handler, notify_delete_handler) self.client.insert_events(events) mainloop.run() self.assertEqual(4, len(result))
#! /usr/bin/env python from zeitgeist.client import ZeitgeistDBusInterface from zeitgeist.datamodel import Event, Interpretation, TimeRange, StorageState, ResultType from datetime import datetime import dateutil zg = ZeitgeistDBusInterface() events = zg.FindEvents( # timerange TimeRange.always(), # Evente template [Event.new_for_values(interpretation=Interpretation.EVENT_INTERPRETATION.LEAVE_EVENT)], # Storage State StorageState.Any, # How many results 10, # Result sort ResultType.MostRecentEvents, ) for event in events: last_event = Event(event) last_subject = last_event.get_subjects()[0] print last_subject.uri, datetime.fromtimestamp(float(last_event.timestamp) / 1000)
def find_events_for_templates (self, event_templates, events_reply_handler, timerange = None, storage_state = StorageState.Any, num_events = 20, result_type = ResultType.MostRecentEvents, error_handler=None): """ Send a query matching a collection of :class:`Event <zeitgeist.datamodel.Event>` templates to the Zeitgeist event log. The query will match if an event matches any of the templates. If an event template has more than one subject the query will match if any one of the subject templates match. The query will be done via an asynchronous DBus call and this method will return immediately. The return value will be passed to 'events_reply_handler' as a list of :class:`Event`s. This list must be the sole argument for the callback. If you need to do a query yielding a large (or unpredictable) result set and you only want to show some of the results at the same time (eg., by paging them), consider using :meth:`find_event_ids_for_templates`. In case of errors a message will be printed on stderr, and an empty result passed to events_reply_handler. To override this default set the error_handler named argument to a callable that takes a single exception as its sole argument. In order to use this method there needs to be a mainloop runnning. Both Qt and GLib mainloops are supported. :param event_templates: List or tuple of :class:`Event <zeitgeist.datamodel.Event>` instances :param events_reply_handler: Callable taking a list of integers :param timerange: A :class:`TimeRange <zeitgeist.datamodel.TimeRange>` instance that the events must have occured within. Defaults to :meth:`TimeRange.until_now()`. :param storage_state: A value from the :class:`StorageState <zeitgeist.datamodel.StorageState>` enumeration. Defaults to :const:`StorageState.Any` :param num_events: The number of events to return; default is 20 :param result_type: A value from the :class:`ResultType <zeitgeist.datamodel.ResultType>` enumeration. Defaults to ResultType.MostRecentEvent :param error_handler: Callback to catch error messages. Read about the default behaviour above """ self._check_list_or_tuple(event_templates) self._check_members(event_templates, Event) if not callable(events_reply_handler): raise TypeError( "Reply handler not callable, found %s" % events_reply_handler) if timerange is None: timerange = TimeRange.until_now() self._iface.FindEvents(timerange, event_templates, storage_state, num_events, result_type, reply_handler=lambda raw: events_reply_handler( map(self._event_type.new_for_struct, raw)), error_handler=self._safe_error_handler(error_handler, events_reply_handler, []))
def find_event_ids_for_templates (self, event_templates, ids_reply_handler, timerange = None, storage_state = StorageState.Any, num_events = 20, result_type = ResultType.MostRecentEvents, error_handler=None): """ Send a query matching a collection of :class:`Event <zeitgeist.datamodel.Event>` templates to the Zeitgeist event log. The query will match if an event matches any of the templates. If an event template has more than one subject the query will match if any one of the subject templates match. The query will be done via an asynchronous DBus call and this method will return immediately. The return value will be passed to 'ids_reply_handler' as a list of integer event ids. This list must be the sole argument for the callback. The actual :class:`Events` can be looked up via the :meth:`get_events()` method. This method is intended for queries potentially returning a large result set. It is especially useful in cases where only a portion of the results are to be displayed at the same time (eg., by using paging or dynamic scrollbars), as by holding a list of IDs you keep a stable ordering, and you can ask for the details associated to them in batches, when you need them. For queries with a small amount of results, or where you need the information about all results at once no matter how many of them there are, see :meth:`find_events_for_templates`. In case of errors a message will be printed on stderr, and an empty result passed to ids_reply_handler. To override this default set the error_handler named argument to a callable that takes a single exception as its sole argument. In order to use this method there needs to be a mainloop runnning. Both Qt and GLib mainloops are supported. :param event_templates: List or tuple of :class:`Event <zeitgeist.datamodel.Event>` instances :param ids_reply_handler: Callable taking a list of integers :param timerange: A :class:`TimeRange <zeitgeist.datamodel.TimeRange>` instance that the events must have occured within. Defaults to :meth:`TimeRange.until_now()`. :param storage_state: A value from the :class:`StorageState <zeitgeist.datamodel.StorageState>` enumeration. Defaults to :const:`StorageState.Any` :param num_events: The number of events to return; default is 20 :param result_type: A value from the :class:`ResultType <zeitgeist.datamodel.ResultType>` enumeration. Defaults to ResultType.MostRecentEvent :param error_handler: Callback to catch error messages. Read about the default behaviour above """ self._check_list_or_tuple(event_templates) self._check_members(event_templates, Event) if not callable(ids_reply_handler): raise TypeError( "Reply handler not callable, found %s" % ids_reply_handler) if timerange is None: timerange = TimeRange.until_now() self._iface.FindEventIds(timerange, event_templates, storage_state, num_events, result_type, reply_handler=self._safe_reply_handler(ids_reply_handler), error_handler=self._safe_error_handler(error_handler, ids_reply_handler, []))
#! /usr/bin/env python from zeitgeist.client import ZeitgeistDBusInterface from zeitgeist.datamodel import Event, Interpretation, TimeRange, \ StorageState, ResultType from datetime import datetime import dateutil zg = ZeitgeistDBusInterface() events = zg.FindEvents( #timerange TimeRange.always(), #Evente template [Event.new_for_values( interpretation=\ Interpretation.EVENT_INTERPRETATION.LEAVE_EVENT)], #Storage State StorageState.Any, #How many results 10, #Result sort ResultType.MostRecentEvents) for event in events: last_event = Event(event) last_subject = last_event.get_subjects()[0] print last_subject.uri, datetime.fromtimestamp(float(last_event.timestamp) / 1000)
def find_events_for_templates(self, event_templates, events_reply_handler, timerange=None, storage_state=StorageState.Any, num_events=20, result_type=ResultType.MostRecentEvents, error_handler=None): """ Send a query matching a collection of :class:`Event <zeitgeist.datamodel.Event>` templates to the Zeitgeist event log. The query will match if an event matches any of the templates. If an event template has more than one subject the query will match if any one of the subject templates match. The query will be done via an asynchronous DBus call and this method will return immediately. The return value will be passed to 'events_reply_handler' as a list of :class:`Event`s. This list must be the sole argument for the callback. If you need to do a query yielding a large (or unpredictable) result set and you only want to show some of the results at the same time (eg., by paging them), consider using :meth:`find_event_ids_for_templates`. In case of errors a message will be printed on stderr, and an empty result passed to events_reply_handler. To override this default set the error_handler named argument to a callable that takes a single exception as its sole argument. In order to use this method there needs to be a mainloop runnning. Both Qt and GLib mainloops are supported. :param event_templates: List or tuple of :class:`Event <zeitgeist.datamodel.Event>` instances :param events_reply_handler: Callable taking a list of integers :param timerange: A :class:`TimeRange <zeitgeist.datamodel.TimeRange>` instance that the events must have occured within. Defaults to :meth:`TimeRange.until_now()`. :param storage_state: A value from the :class:`StorageState <zeitgeist.datamodel.StorageState>` enumeration. Defaults to :const:`StorageState.Any` :param num_events: The number of events to return; default is 20 :param result_type: A value from the :class:`ResultType <zeitgeist.datamodel.ResultType>` enumeration. Defaults to ResultType.MostRecentEvent :param error_handler: Callback to catch error messages. Read about the default behaviour above """ self._check_list_or_tuple(event_templates) self._check_members(event_templates, Event) if not callable(events_reply_handler): raise TypeError("Reply handler not callable, found %s" % events_reply_handler) if timerange is None: timerange = TimeRange.until_now() self._iface.FindEvents(timerange, event_templates, storage_state, num_events, result_type, reply_handler=lambda raw: events_reply_handler( map(self._event_type.new_for_struct, raw)), error_handler=self._safe_error_handler( error_handler, events_reply_handler, []))
def find_event_ids_for_templates(self, event_templates, ids_reply_handler, timerange=None, storage_state=StorageState.Any, num_events=20, result_type=ResultType.MostRecentEvents, error_handler=None): """ Send a query matching a collection of :class:`Event <zeitgeist.datamodel.Event>` templates to the Zeitgeist event log. The query will match if an event matches any of the templates. If an event template has more than one subject the query will match if any one of the subject templates match. The query will be done via an asynchronous DBus call and this method will return immediately. The return value will be passed to 'ids_reply_handler' as a list of integer event ids. This list must be the sole argument for the callback. The actual :class:`Events` can be looked up via the :meth:`get_events()` method. This method is intended for queries potentially returning a large result set. It is especially useful in cases where only a portion of the results are to be displayed at the same time (eg., by using paging or dynamic scrollbars), as by holding a list of IDs you keep a stable ordering, and you can ask for the details associated to them in batches, when you need them. For queries with a small amount of results, or where you need the information about all results at once no matter how many of them there are, see :meth:`find_events_for_templates`. In case of errors a message will be printed on stderr, and an empty result passed to ids_reply_handler. To override this default set the error_handler named argument to a callable that takes a single exception as its sole argument. In order to use this method there needs to be a mainloop runnning. Both Qt and GLib mainloops are supported. :param event_templates: List or tuple of :class:`Event <zeitgeist.datamodel.Event>` instances :param ids_reply_handler: Callable taking a list of integers :param timerange: A :class:`TimeRange <zeitgeist.datamodel.TimeRange>` instance that the events must have occured within. Defaults to :meth:`TimeRange.until_now()`. :param storage_state: A value from the :class:`StorageState <zeitgeist.datamodel.StorageState>` enumeration. Defaults to :const:`StorageState.Any` :param num_events: The number of events to return; default is 20 :param result_type: A value from the :class:`ResultType <zeitgeist.datamodel.ResultType>` enumeration. Defaults to ResultType.MostRecentEvent :param error_handler: Callback to catch error messages. Read about the default behaviour above """ self._check_list_or_tuple(event_templates) self._check_members(event_templates, Event) if not callable(ids_reply_handler): raise TypeError("Reply handler not callable, found %s" % ids_reply_handler) if timerange is None: timerange = TimeRange.until_now() self._iface.FindEventIds( timerange, event_templates, storage_state, num_events, result_type, reply_handler=self._safe_reply_handler(ids_reply_handler), error_handler=self._safe_error_handler(error_handler, ids_reply_handler, []))
# monitor zeitgeist and do stuff from zeitgeist.client import ZeitgeistClient from zeitgeist.datamodel import TimeRange, Event from gobject import MainLoop #import hamster.client class e_handler: def handler(self, tr, ev): # because the mainloop appears to catch exceptions from traceback import print_exc from urlparse import urlparse try: # FIXME insert clever rules here app = urlparse(ev[0].actor).netloc #desk = open("/usr/share/applications/" + app) #comments = filter(lambda x: x.startswith("Comment[en_GB]="), desk) #comment = comments[0].split("=")[1].strip() #self.add_fact(comment + " - " + ev[0].subjects[0].text) print(ev[0].subjects[0].text) except: print_exc() hh = e_handler() ml = MainLoop() ZeitgeistClient().install_monitor( TimeRange.from_now(), [Event()], hh.handler, hh.handler) ml.run()
def search(self, text, templates=None): results, count = self.fts.Search(text, TimeRange.always(), templates if templates else [] , 0, 10, self.result_type_relevancy) return map(Event, results)