Hello all,

I have created one module 'tracker.keywords' that wraps the DBus
interface 'Keywords' through a Pythonic API (via attachment).

The 'search' function uses a generator along with the 'offset'
parameter to do lazy-live-search, where the files are fetched as
needed by batches of '$step' entries.

The class 'Keywords' has the interface of a 'set' (where possible). So
manipulating keywords of a certain filename (or tracker-id) becomes
very natural.

I have done this code only for pleasure, since I love programming in
Python. I think it might be of some use, thus I am sending it to the
mailling list. Oh, and I am not using this code for anything --- other
than playing with Tracker's API --- so it will bit-rot in my harddrive
if you dont want it.

PS: please CC me as I am not in the list.
"""
A pythonic interface to tracker.

Submodules:

 * keywords
 
"""
__author__ = "Tiago Cogumbreiro <[EMAIL PROTECTED]>"
__license__ = "MIT <http://www.opensource.org/licenses/mit-license.php>"

import dbus
_bus = dbus.SessionBus()
_tracker = _bus.get_object('org.freedesktop.Tracker','/org/freedesktop/tracker')
"""
A pythonic interface to the 'Keywords' interface.
"""
__author__ = "Tiago Cogumbreiro <[EMAIL PROTECTED]>"
__license__ = "MIT <http://www.opensource.org/licenses/mit-license.php>"

import dbus
import random

from tracker import _tracker

_keywords = dbus.Interface(_tracker, 'org.freedesktop.Tracker.Keywords')


def search(service, keywords, step=10):
    """
    Gets a list of all unique keywords/tags that are in use by the
    specified service irrespective of the uri or id of the entity.
    """
    live_id = random.randint(0,65000)

    offset = 0
    while True:
        found = False
        for hit in _keywords.Search(live_id, service, keywords, offset, step):
            yield unicode(hit)
            found = True
            offset += 1
        if not found:
            break

class Keywords(object):
    """
    Wraps all operations that affect the keywords of an id.  The
    interface is set-like. Containing the operations that apply to
    sets.
    """
    def __init__(self, track_id, service="Files"):
        self.filename = track_id
        self.service = service

    def __iter__(self):
        return iter(self.data)

    def _get_data(self):
        try:
            return self._data
        except AttributeError:
            self._data = set(map(unicode, _keywords.Get(self.service, self.filename)))
            
        return self._data
    
    def _set_data(self, new_data):
        data = self.data
        if data == new_data:
            return
        # make it atomic
        self.clear()
        self.update(new_data)
        
    data = property(get_data, set_data)

    def __contains__(self, keyword):
        return keyword in self.data

    def __repr__(self):
        return "Keywords(%r,%s" % (self.filename, repr(self.data)[len("set("):])

    def _reset_data(self):
        # Clear cache
        try:
            del self._data
        except AttributeError:
            pass
        
    def clear(self):
        """
        Remove all elements from this set.
        """
        _keywords.RemoveAll(self.service, self.filename)
        self._reset_data()

    def difference_update(self, keywords):
        """
        Remove all elements of another set from this set.
        """
        if len(keywords) == 0:
            return
        _keywords.Remove(self.service, self.filename, keywords)
        self._reset_data()
    
    def update(self, keywords):
        """
        Update a set with the union of itself and another.
        """
        if len(keywords) == 0:
            return
        _keywords.Add(self.service, self.filename, keywords)
        self._reset_data()

    def add(self, keyword):
        """
        Add an element to a set.

        This has no effect if the element is already present.
        """
        self.update([keyword])

    def discard(self, keyword):
        """
        Remove an element from a set if it is a member.
        """
        self.difference_update((keyword,))

    def intersection_update(self, other_set):
        """
        Update a set with the intersection of itself and another.
        """
        new_data = self.data.copy()
        new_data.intersection_update()
        self.data = new_data

    def issubset(self, other_set):
        """
        Report whether another set contains this set.
        """
        return self.data.issubset(other_set)

    def issuperset(self, other_set):
        """
        Report whether this set contains another set.
        """
        return self.data.issuperset(other_set)

    def pop(self, other_set):
        """
        Remove and return an arbitrary set element.
        """
        self.discard(self.data.pop())

    def remove(self, keyword):
        """
        Remove an element from a set; it must be a member.

        If the element is not a member, raise a KeyError.
        """
        if keyword in self:
            self.discard(keyword)
        raise KeyError(keyword)

    def symmetric_difference_update(self, other_set):
        """
        Return the symmetric difference of two sets as a new set.

        (i.e. all elements that are in exactly one of the sets.)
        """
        new_data = self.data.copy()
        new_data.symmetric_difference_update(other_set)
        self.data = new_data

    

_______________________________________________
tracker-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/tracker-list

Reply via email to