/usr/share/pyshared/djapian/decider.py is in python-django-djapian 2.3.1-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | import operator
import re
import xapian
from django.db import models
from django.utils.functional import curry
class X(models.Q):
pass
i = lambda f: lambda a, b: f(a.lower(), b.lower())
startswith = lambda a, b: a.startswith(b)
endswith = lambda a, b: a.endswith(b)
regex = lambda a, b: re.match(b, a) is not None
iregex = lambda a, b: re.match(b, a, re.I) is not None
class CompositeDecider(xapian.MatchDecider):
# operators map
op_map = {
'exact': operator.eq,
'iexact': i(operator.eq),
'startswith': startswith,
'istartswith': i(startswith),
'endswith': endswith,
'iendswith': i(endswith),
'contains': operator.contains,
'icontains': i(operator.contains),
'regex': regex,
'iregex': iregex,
'in': lambda a, b: operator.contains(b, a),
'gt': operator.gt,
'gte': operator.ge,
'lt': operator.lt,
'lte': operator.le,
}
def __init__(self, model, tags, filter, exclude):
xapian.MatchDecider.__init__(self)
self._model = model
self._tags = tags
self._values_map = dict([(t.prefix, t.number) for t in tags])
self._filter = filter
self._exclude = exclude
def __call__(self, document):
if self._filter and not self._do_x(self._filter, document):
return False
if self._exclude and self._do_x(self._exclude, document):
return False
return True
def get_tag(self, index):
for tag in self._tags:
if tag.number == index:
return tag
raise ValueError("No tag with number '%s'" % index)
def _do_x(self, field, document):
for child in field.children:
if isinstance(child, X):
result = self._do_x(child, document)
else:
result = self._do_field(child[0], child[1], document)
if (result and field.connector == 'OR')\
or (not result and field.connector == 'AND'):
break
if field.negated:
return not result
else:
return result
def _do_field(self, lookup, value, document):
if '__' in lookup:
field, op = lookup.split('__', 1)
else:
field, op = lookup, 'exact'
if op not in self.op_map:
raise ValueError("Unknown lookup operator '%s'" % op)
op = self.op_map[op]
doc_value = document.get_value(self._values_map[field])
convert = curry(
self.get_tag(self._values_map[field]).convert,
model=self._model
)
if isinstance(value, (list, tuple)):
value = map(convert, value)
else:
value = convert(value)
operands = [
doc_value,
value,
]
return reduce(op, operands)
|