Thomas Waldmann avatar Thomas Waldmann committed 8ac1f87

MoinMoin.storage.terms + tests removed (unused), please use whoosh queries

Comments (0)

Files changed (3)

MoinMoin/storage/_tests/test_backends.py

 from MoinMoin.storage import Item, NewRevision
 from MoinMoin.storage.backends import memory
 from MoinMoin.storage.error import NoSuchItemError, ItemAlreadyExistsError, NoSuchRevisionError, RevisionAlreadyExistsError
-from MoinMoin.storage import terms
 from MoinMoin.config import SIZE
 
 item_names = (u"quite_normal",

MoinMoin/storage/_tests/test_terms.py

-# Copyright: 2008 MoinMoin:JohannesBerg
-# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
-
-"""
-    MoinMoin - Term tests.
-"""
-
-
-import re
-
-from MoinMoin.config import NAME, CONTENTTYPE
-from MoinMoin.storage import terms as term
-from MoinMoin.storage.backends.memory import MemoryBackend
-
-
-_item_contents = {
-    u'a': u'abcdefg hijklmnop',
-    u'b': u'bbbbbbb bbbbbbbbb',
-    u'c': u'Abiturienten Apfeltortor',
-    u'Lorem': u'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis placerat, tortor quis sollicitudin dictum, nisi tellus aliquam quam, ac varius lacus diam eget tortor. Nulla vehicula, nisi ac hendrerit aliquam, libero erat tempor ante, lobortis placerat lacus justo vitae erat. In rutrum odio a sem. In ac risus vel diam vulputate luctus. Fusce sit amet est. Morbi consectetuer eros vel risus. In nulla lacus, ultrices id, vestibulum tempus, dictum in, mauris. Quisque rutrum faucibus nisl. Suspendisse potenti. In hac habitasse platea dictumst. Donec ac magna ac eros malesuada facilisis. Pellentesque viverra nibh nec dui. Praesent venenatis lectus vehicula eros. Phasellus pretium, ante at mollis luctus, nibh lacus ultricies eros, vitae pharetra lacus leo at neque. Nullam vel sapien. In in diam id massa nonummy suscipit. Curabitur vel dui sed tellus pellentesque pretium.',
-}
-
-_item_metadata = {
-    u'a': {'m1': 'True', 'm2': '222'},
-    u'A': {'m1': 'True', 'm2': '333'},
-    u'b': {'m1': 'False', 'm2': '222'},
-    u'c': {'m1': 'True', 'm2': '222'},
-    u'B': {'m1': 'False', 'm2': '333'},
-    u'Lorem': {'m1': '7', 'm2': '444'},
-}
-
-_lastrevision_metadata = {
-    u'a': {'a': '1'},
-    u'A': {'a': ''},
-    u'b': {'a': '0'},
-    u'c': {'a': 'False'},
-    u'B': {'a': ''},
-    u'Lorem': {'a': '42'},
-}
-
-for n in _item_contents.keys():
-    nl = n.lower()
-    nu = n.upper()
-    _item_contents[nl] = _item_contents[n].lower()
-    _item_contents[nu] = _item_contents[n].upper()
-    if not nl in _item_metadata:
-        _item_metadata[nl] = _item_metadata[n]
-    if not nu in _item_metadata:
-        _item_metadata[nu] = _item_metadata[n]
-    if not nl in _lastrevision_metadata:
-        _lastrevision_metadata[nl] = _lastrevision_metadata[n]
-    if not nu in _lastrevision_metadata:
-        _lastrevision_metadata[nu] = _lastrevision_metadata[n]
-
-memb = MemoryBackend()
-for iname, md in _item_metadata.iteritems():
-    item = memb.create_item(iname)
-    item.change_metadata()
-    item.update(md)
-    item.publish_metadata()
-
-    rev = item.create_revision(0)
-    md = _lastrevision_metadata[iname]
-    rev.update({NAME: iname, CONTENTTYPE: u"application/octet-stream"})
-    rev.update(md)
-    rev.write(_item_contents[iname])
-    item.commit()
-
-item = memb.create_item('NR')
-item.change_metadata()
-item.update({'m1': 'True'})
-item.publish_metadata()
-del item
-
-class TermTestData:
-    def __init__(self, text):
-        self.text = text
-    def read(self, size=None):
-        return self.text
-
-class CacheAssertTerm(term.Term):
-    def __init__(self):
-        term.Term.__init__(self)
-        self.evalonce = False
-
-    def _evaluate(self, item):
-        assert not self.evalonce
-        self.evalonce = True
-        return True
-
-class AssertNotCalledTerm(term.Term):
-    def _evaluate(self, item):
-        assert False
-
-class TestTerms:
-    def _evaluate(self, term, itemname, expected):
-        if itemname is not None:
-            item = memb.get_item(itemname)
-        else:
-            item = None
-        term.prepare()
-        assert expected == term.evaluate(item)
-
-    def testSimpleTextSearch(self):
-        terms = [term.Text(u'abcdefg', True), term.Text(u'ijklmn', True)]
-        for item, expected in [('a', True), ('A', False), ('b', False), ('B', False), ('lorem', False), ('NR', False)]:
-            for t in terms:
-                yield self._evaluate, t, item, expected
-
-    def testSimpleTextSearchCI(self):
-        terms = [term.Text(u'abcdefg', False), term.Text(u'ijklmn', False)]
-        for item, expected in [('a', True), ('A', True), ('b', False), ('B', False), ('lorem', False)]:
-            for t in terms:
-                yield self._evaluate, t, item, expected
-
-    def testANDOR(self):
-        tests = [
-            (True,  [1, 1, 1, 1, 1]),
-            (True,  [1, 1, 1, 1]),
-            (True,  [1, 1, 1]),
-            (True,  [1, 1]),
-            (False, [0, 1, 1]),
-            (False, [0, 1, 1, 1]),
-            (False, [1, 0, 1, 1]),
-            (False, [1, 1, 0, 1]),
-            (False, [1, 1, 1, 0]),
-            (False, [0, 1, 1, 0]),
-        ]
-        for expected, l in tests:
-            l = [term.BOOL(i) for i in l]
-            t = term.AND(*l)
-            yield self._evaluate, t, 'a', expected
-        for expected, l in tests:
-            l = [term.BOOL(1 - i) for i in l]
-            t = term.OR(*l)
-            yield self._evaluate, t, 'a', not expected
-
-    def testXOR(self):
-        tests = [
-            (False, [1, 1, 1, 1, 1]),
-            (False, [1, 1, 1, 1]),
-            (False, [1, 1, 1]),
-            (False, [1, 1]),
-            (False, [0, 1, 1]),
-            (False, [0, 1, 1, 1]),
-            (False, [1, 0, 1, 1]),
-            (False, [1, 1, 0, 1]),
-            (False, [1, 1, 1, 0]),
-            (False, [0, 1, 1, 0]),
-            (True,  [0, 0, 0, 1, 0]),
-            (True,  [0, 0, 1, 0]),
-            (True,  [1, 0, 0]),
-            (True,  [0, 1]),
-            (False, [0, 0, 0]),
-        ]
-        for expected, l in tests:
-            l = [term.BOOL(i) for i in l]
-            t = term.XOR(*l)
-            yield self._evaluate, t, 'a', expected
-
-    def testTextSearchRE(self):
-        terms = [term.TextRE(re.compile('^abc')), term.TextRE(re.compile('\shij'))]
-        for item, expected in [('a', True), ('A', False), ('b', False), ('B', False), ('lorem', False), ('NR', False)]:
-            for t in terms:
-                yield self._evaluate, t, item, expected
-
-    def testTextSearchRE2(self):
-        terms = [term.TextRE(re.compile('sollici')), term.TextRE(re.compile('susci'))]
-        for item, expected in [('a', False), ('A', False), ('b', False), ('B', False), ('lorem', True), ('NR', False)]:
-            for t in terms:
-                yield self._evaluate, t, item, expected
-
-    def testResultCaching1(self):
-        cat = CacheAssertTerm()
-        expected = True
-        t = term.AND(cat, cat, cat)
-        yield self._evaluate, t, None, expected
-
-    def testResultCaching2(self):
-        cat = CacheAssertTerm()
-        expected = True
-        t = term.OR(cat, cat, cat)
-        yield self._evaluate, t, None, expected
-
-    def testResultCaching3(self):
-        cat = CacheAssertTerm()
-        expected = False
-        t = term.AND(cat, cat, cat, term.FALSE)
-        yield self._evaluate, t, None, expected
-
-    def testResultCaching4(self):
-        cat = CacheAssertTerm()
-        expected = True
-        t = term.OR(cat, cat, cat)
-        yield self._evaluate, t, None, expected
-
-    def testShortCircuitEval1(self):
-        yield self._evaluate, term.AND(term.TRUE, term.FALSE, AssertNotCalledTerm()), None, False
-
-    def testShortCircuitEval2(self):
-        yield self._evaluate, term.OR(term.TRUE, term.FALSE, AssertNotCalledTerm()), None, True
-
-    def testSimpleTitleSearch(self):
-        for item, expected in [('a', True), ('A', False), ('b', False), ('B', False), ('lorem', False), ('NR', False)]:
-            yield self._evaluate, term.Name(u'a', True), item, expected
-
-    def testSimpleTitleSearchCI(self):
-        for item, expected in [('a', True), ('A', True), ('b', False), ('B', False), ('lorem', False), ('NR', False)]:
-            yield self._evaluate, term.Name(u'a', False), item, expected
-
-    def testTitleRESearch(self):
-        for item, expected in [('a', True), ('A', False), ('b', False), ('B', False), ('lorem', True), ('NR', False)]:
-            yield self._evaluate, term.NameRE(re.compile('(a|e)')), item, expected
-
-    def testMetaMatch1(self):
-        t = term.ItemMetaDataMatch('m1', 'True')
-        for item, expected in [('a', True), ('A', True), ('b', False), ('B', False), ('lorem', False), ('NR', True)]:
-            yield self._evaluate, t, item, expected
-
-    def testMetaMatch2(self):
-        t = term.ItemMetaDataMatch('m2', '333')
-        for item, expected in [('a', False), ('A', True), ('b', False), ('B', True), ('lorem', False), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testMetaMatch3(self):
-        t = term.ItemMetaDataMatch('m2', '444')
-        for item, expected in [('a', False), ('A', False), ('b', False), ('B', False), ('lorem', True), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testHasMeta1(self):
-        t = term.ItemHasMetaDataKey('m3')
-        for item, expected in [('a', False), ('A', False), ('b', False), ('B', False), ('lorem', False), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testHasMeta2(self):
-        t = term.ItemHasMetaDataKey('m1')
-        for item, expected in [('a', True), ('A', True), ('b', True), ('B', True), ('lorem', True), ('NR', True)]:
-            yield self._evaluate, t, item, expected
-
-    def testHasMeta3(self):
-        t = term.LastRevisionHasMetaDataKey('a')
-        for item, expected in [('a', True), ('A', True), ('b', True), ('B', True), ('lorem', True), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testHasMeta4(self):
-        t = term.LastRevisionMetaDataMatch('a', '')
-        for item, expected in [('a', False), ('A', True), ('b', False), ('B', True), ('lorem', False), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testNameFn(self):
-        t = term.NameFn(lambda x: x in ['a', 'b', 'lorem'])
-        for item, expected in [('a', True), ('A', False), ('b', True), ('B', False), ('lorem', True), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testWordCI(self):
-        t = term.Word('Curabitur', False)
-        for item, expected in [('B', False), ('Lorem', True), ('lorem', True), ('LOREM', True), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testWord(self):
-        t = term.Word('Curabitur', True)
-        for item, expected in [('B', False), ('Lorem', True), ('lorem', False), ('LOREM', False), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testWordStartCI(self):
-        t = term.WordStart('Curabi', False)
-        for item, expected in [('B', False), ('Lorem', True), ('lorem', True), ('LOREM', True), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testWordStart(self):
-        t = term.WordStart('Curabi', True)
-        for item, expected in [('c', False), ('Lorem', True), ('lorem', False), ('LOREM', False), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testWordStart2(self):
-        t = term.WordStart('abitur', True)
-        for item, expected in [('c', True), ('C', False), ('Lorem', False), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testWordStart2CI(self):
-        t = term.WordStart('abitur', False)
-        for item, expected in [('c', True), ('C', True), ('Lorem', False), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-    def testWordEndCI(self):
-        t = term.WordEnd('abitur', False)
-        for item, expected in [('c', False), ('Lorem', True), ('lorem', True), ('LOREM', True), ('NR', False)]:
-            yield self._evaluate, t, item, expected
-
-coverage_modules = ['MoinMoin.storage.terms']

MoinMoin/storage/terms.py

-# Copyright: 2008 MoinMoin:JohannesBerg
-# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
-
-"""
-    MoinMoin - search expression object representation
-
-    DEPRECATED - please use storage.search with whoosh queries.
-
-    This module defines the possible search terms for a query to the
-    storage backend. This is used, for example, to implement searching,
-    page lists etc.
-
-    Note that some backends can optimise some of the search terms, for
-    example a backend that has indexed various metadata keys can optimise
-    easy expressions containing ItemMetaDataMatch terms. This is only allowed
-    for classes documented as being 'final' which hence also means that
-    their _evaluate function may not be overridden by descendent classes.
-
-    For example, that metadata backend could test if the expression is an
-    ItemMetaDataMatch expression, and if so, simply return the appropriate
-    index; or if it is an AND() expression build the page list from the
-    index, remove the ItemMetaDataMatch instance from the AND list and match
-    the resulting expression only for pages in that list. Etc.
-
-    TODO: Should we write some generic code for picking apart expressions
-          like that?
-"""
-
-
-import re
-
-from MoinMoin.storage.error import NoSuchRevisionError
-
-# Base classes
-
-class Term(object):
-    """
-    Base class for search terms.
-    """
-    # relative cost of this search term
-    _cost = 0
-
-    def __init__(self):
-        pass
-
-    def evaluate(self, item):
-        """
-        Evaluate this term and return True or False if the
-        item identified by the parameters matches.
-
-        :param item: the item
-        """
-        assert hasattr(self, '_result')
-
-        if self._result is None:
-            self._result = self._evaluate(item)
-
-        return self._result
-
-    def _evaluate(self, item):
-        """
-        Implements the actual evaluation
-        """
-        raise NotImplementedError()
-
-    def prepare(self):
-        """
-        Prepare this search term to make it ready for testing.
-        Must be called before each outermost-level evaluate.
-        """
-        self._result = None
-
-    def copy(self):
-        """
-        Make a copy of this search term.
-        """
-        return self.__class__()
-
-class UnaryTerm(Term):
-    """
-    Base class for search terms that has a single contained
-    search term, e.g. NOT.
-    """
-    def __init__(self, term):
-        Term.__init__(self)
-        assert isinstance(term, Term)
-        self.term = term
-
-    def prepare(self):
-        Term.prepare(self)
-        self.term.prepare()
-        self._cost = self.term._cost
-
-    def __repr__(self):
-        return u'<%s(%r)>' % (self.__class__.__name__, self.term)
-
-    def copy(self):
-        return self.__class__(self.term.copy())
-
-class ListTerm(Term):
-    """
-    Base class for search terms that contain multiple other
-    search terms, e.g. AND.
-    """
-    def __init__(self, *terms):
-        Term.__init__(self)
-        for e in terms:
-            assert isinstance(e, Term)
-        self.terms = list(terms)
-
-    def prepare(self):
-        Term.prepare(self)
-        # the sum of all costs is a bit of a worst-case cost...
-        self._cost = 0
-        for e in self.terms:
-            e.prepare()
-            self._cost += e._cost
-        self.terms.sort(cmp=lambda x, y: cmp(x._cost, y._cost))
-
-    def remove(self, subterm):
-        self.terms.remove(subterm)
-
-    def add(self, subterm):
-        self.terms.append(subterm)
-
-    def __repr__(self):
-        return u'<%s(%s)>' % (self.__class__.__name__,
-                              ', '.join([repr(t) for t in self.terms]))
-
-    def copy(self):
-        terms = [t.copy() for t in self.terms]
-        return self.__class__(*terms)
-
-# Logical expression classes
-
-class AND(ListTerm):
-    """
-    AND connection between multiple terms. Final.
-    """
-    def _evaluate(self, item):
-        for e in self.terms:
-            if not e.evaluate(item):
-                return False
-        return True
-
-class OR(ListTerm):
-    """
-    OR connection between multiple terms. Final.
-    """
-    def _evaluate(self, item):
-        for e in self.terms:
-            if e.evaluate(item):
-                return True
-        return False
-
-class NOT(UnaryTerm):
-    """
-    Inversion of a single term. Final.
-    """
-    def _evaluate(self, item):
-        return not self.term.evaluate(item)
-
-class XOR(ListTerm):
-    """
-    XOR connection between multiple terms, i.e. exactly
-    one must be True. Final.
-    """
-    def _evaluate(self, item):
-        count = 0
-        for e in self.terms:
-            if e.evaluate(item):
-                count += 1
-        return count == 1
-
-class _BOOL(Term):
-    _cost = 0
-    def __init__(self, val):
-        self._val = val
-
-    def prepare(self):
-        self._result = self._val
-
-    def __repr__(self):
-        return '<%s>' % str(self._val).upper()
-
-    def copy(self):
-        return self
-
-TRUE = _BOOL(True)
-FALSE = _BOOL(False)
-
-def BOOL(b):
-    if b:
-        return TRUE
-    return FALSE
-
-# Actual Moin search terms
-
-class TextRE(Term):
-    """
-    Regular expression full text match, use as last resort.
-    """
-    _cost = 1000 # almost prohibitive
-    def __init__(self, needle_re):
-        Term.__init__(self)
-        assert hasattr(needle_re, 'search')
-        self._needle_re = needle_re
-
-    def _evaluate(self, item):
-        try:
-            rev = item.get_revision(-1)
-        except NoSuchRevisionError:
-            return False
-        data = rev.read()
-        return not (not self._needle_re.search(data))
-
-    def __repr__(self):
-        return u'<term.TextRE(...)>'
-
-    def copy(self):
-        return TextRE(self._needle_re)
-
-class Text(TextRE):
-    """
-    Full text match including middle of words and over word
-    boundaries. Final.
-    """
-    def __init__(self, needle, case_sensitive):
-        flags = re.UNICODE
-        if not case_sensitive:
-            flags = flags | re.IGNORECASE
-        _needle_re = re.compile(re.escape(needle), flags)
-        TextRE.__init__(self, _needle_re)
-        self.needle = needle
-        self.case_sensitive = case_sensitive
-
-    def __repr__(self):
-        return u'<term.Text(%s, %s)>' % (self.needle, self.case_sensitive)
-
-    def copy(self):
-        return Text(self.needle, self.case_sensitive)
-
-class Word(TextRE):
-    """
-    Full text match finding exact words. Final.
-    """
-    def __init__(self, needle, case_sensitive):
-        flags = re.UNICODE
-        if not case_sensitive:
-            flags = flags | re.IGNORECASE
-        _needle_re = re.compile('\\b' + re.escape(needle) + '\\b', flags)
-        TextRE.__init__(self, _needle_re)
-        self.needle = needle
-        self.case_sensitive = case_sensitive
-
-    def __repr__(self):
-        return u'<term.Word(%s, %s)>' % (self.needle, self.case_sensitive)
-
-    def copy(self):
-        return Word(self.needle, self.case_sensitive)
-
-class WordStart(TextRE):
-    """
-    Full text match finding the start of a word. Final.
-    """
-    def __init__(self, needle, case_sensitive):
-        flags = re.UNICODE
-        if not case_sensitive:
-            flags = flags | re.IGNORECASE
-        _needle_re = re.compile('\\b' + re.escape(needle), flags)
-        TextRE.__init__(self, _needle_re)
-        self.needle = needle
-        self.case_sensitive = case_sensitive
-
-    def __repr__(self):
-        return u'<term.WordStart(%s, %s)>' % (self.needle, self.case_sensitive)
-
-    def copy(self):
-        return WordStart(self.needle, self.case_sensitive)
-
-class WordEnd(TextRE):
-    """
-    Full text match finding the end of a word. Final.
-    """
-    def __init__(self, needle, case_sensitive):
-        flags = re.UNICODE
-        if not case_sensitive:
-            flags = flags | re.IGNORECASE
-        _needle_re = re.compile(re.escape(needle) + '\\b', flags)
-        TextRE.__init__(self, _needle_re)
-        self.needle = needle
-        self.case_sensitive = case_sensitive
-
-    def __repr__(self):
-        return u'<term.WordEnd(%s, %s)>' % (self.needle, self.case_sensitive)
-
-    def copy(self):
-        return WordEnd(self.needle, self.case_sensitive)
-
-class NameRE(Term):
-    """
-    Matches the item's name with a given regular expression.
-    """
-    _cost = 10 # one of the cheapest
-    def __init__(self, needle_re):
-        Term.__init__(self)
-        assert hasattr(needle_re, 'search')
-        self._needle_re = needle_re
-
-    def _evaluate(self, item):
-        return not (not self._needle_re.search(item.name))
-
-    def __repr__(self):
-        return u'<term.NameRE(...)>'
-
-    def copy(self):
-        return NameRE(self._needle_re)
-
-class Name(NameRE):
-    """
-    Item name match, given needle must occur in item's name. Final.
-    """
-    def __init__(self, needle, case_sensitive):
-        assert isinstance(needle, unicode)
-        flags = re.UNICODE
-        if not case_sensitive:
-            flags = flags | re.IGNORECASE
-        _needle_re = re.compile(re.escape(needle), flags)
-        NameRE.__init__(self, _needle_re)
-        self.needle = needle
-        self.case_sensitive = case_sensitive
-
-    def __repr__(self):
-        return u'<term.Name(%s, %s)>' % (self.needle, self.case_sensitive)
-
-    def copy(self):
-        return Name(self.needle, self.case_sensitive)
-
-class NameFn(Term):
-    """
-    Arbitrary item name matching function.
-    """
-    def __init__(self, fn):
-        Term.__init__(self)
-        assert callable(fn)
-        self._fn = fn
-
-    def _evaluate(self, item):
-        return not (not self._fn(item.name))
-
-    def __repr__(self):
-        return u'<term.NameFn(%r)>' % (self._fn, )
-
-    def copy(self):
-        return NameFn(self._fn)
-
-class ItemMetaDataMatch(Term):
-    """
-    Matches a metadata key/value pair of an item, requires
-    existence of the metadata key. Final.
-    """
-    _cost = 100 # fairly expensive but way cheaper than text
-    def __init__(self, key, val):
-        Term.__init__(self)
-        self.key = key
-        self.val = val
-
-    def _evaluate(self, item):
-        return self.key in item and item[self.key] == self.val
-
-    def __repr__(self):
-        return u'<%s(%s: %s)>' % (self.__class__.__name__, self.key, self.val)
-
-    def copy(self):
-        return ItemMetaDataMatch(self.key, self.val)
-
-class ItemHasMetaDataValue(Term):
-    """
-    Match when the metadata value for a given key contains the given
-    value (when the item's metadata value is a dict or list), requires
-    existence of the metadata key. Final.
-    """
-    _cost = 100 # fairly expensive but way cheaper than text
-    def __init__(self, key, val):
-        Term.__init__(self)
-        self.key = key
-        self.val = val
-
-    def _evaluate(self, item):
-        return self.key in item and self.val in item[self.key]
-
-    def __repr__(self):
-        return u'<%s(%s: %s)>' % (self.__class__.__name__, self.key, self.val)
-
-    def copy(self):
-        return ItemHasMetaDataValue(self.key, self.val)
-
-class ItemHasMetaDataKey(Term):
-    """
-    Requires existence of the metadata key. Final.
-    """
-    _cost = 90 # possibly cheaper than ItemMetaDataMatch
-    def __init__(self, key):
-        Term.__init__(self)
-        self.key = key
-
-    def _evaluate(self, item):
-        return self.key in item
-
-    def __repr__(self):
-        return u'<%s(%s)>' % (self.__class__.__name__, self.key)
-
-    def copy(self):
-        return ItemHasMetaDataKey(self.key)
-
-class LastRevisionMetaDataMatch(Term):
-    """
-    Matches a metadata key/value pair of an item, requires
-    existence of the metadata key. Final.
-    """
-    _cost = 100 # fairly expensive but way cheaper than text
-    def __init__(self, key, val):
-        Term.__init__(self)
-        self.key = key
-        self.val = val
-
-    def _evaluate(self, item):
-        try:
-            rev = item.get_revision(-1)
-        except NoSuchRevisionError:
-            return False
-        return self.key in rev and rev[self.key] == self.val
-
-    def __repr__(self):
-        return u'<%s(%s: %s)>' % (self.__class__.__name__, self.key, self.val)
-
-    def copy(self):
-        return LastRevisionMetaDataMatch(self.key, self.val)
-
-class LastRevisionHasMetaDataKey(Term):
-    """
-    Requires existence of the metadata key. Final.
-    """
-    _cost = 90 # possibly cheaper than LastRevisionMetaDataMatch
-    def __init__(self, key):
-        Term.__init__(self)
-        self.key = key
-
-    def _evaluate(self, item):
-        try:
-            rev = item.get_revision(-1)
-        except NoSuchRevisionError:
-            return False
-        return self.key in rev
-
-    def __repr__(self):
-        return u'<%s(%s)>' % (self.__class__.__name__, self.key)
-
-    def copy(self):
-        return LastRevisionHasMetaDataKey(self.key)
-
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.