def test_andnot(): lm1 = matching.ListMatcher([1, 4, 10, 20, 90]) lm2 = matching.ListMatcher([0, 4, 20]) anm = matching.AndNotMatcher(lm1, lm2) ls = [] while anm.is_active(): ls.append((anm.id(), anm.score())) anm.next() assert ls == [(1, 1.0), (10, 1.0), (90, 1.0)] echo_lm = matching.ListMatcher([0, 1, 2, 3, 4]) bravo_lm = matching.ListMatcher([0, 1]) anm = matching.AndNotMatcher(echo_lm, bravo_lm) assert list(anm.all_ids()) == [2, 3, 4] lm1 = matching.ListMatcher([1, 4, 10, 20, 90]) lm2 = matching.ListMatcher([0, 4, 20]) anm = matching.AndNotMatcher(lm1, lm2) assert list(anm.all_ids()) == [1, 10, 90] lm1 = matching.ListMatcher([1, 4, 10, 20, 90]) lm2 = matching.ListMatcher([0, 4, 20]) anm = matching.AndNotMatcher(lm1, lm2) anm.next() anm.next() anm = anm.copy() ls = [] while anm.is_active(): ls.append(anm.id()) anm.next() assert ls == [90]
def test_empty_andnot(): pos = matching.NullMatcher() neg = matching.NullMatcher() anm = matching.AndNotMatcher(pos, neg) assert not anm.is_active() assert not list(anm.all_ids()) pos = matching.ListMatcher([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) neg = matching.NullMatcher() ans = matching.AndNotMatcher(pos, neg) ids = list(ans.all_ids()) assert ids == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def test_random_andnot(): testcount = 100 rangesize = 100 rng = list(range(rangesize)) for _ in xrange(testcount): negs = sorted(sample(rng, randint(0, rangesize - 1))) negset = frozenset(negs) matched = [n for n in rng if n not in negset] pos = matching.ListMatcher(rng) neg = matching.ListMatcher(negs) anm = matching.AndNotMatcher(pos, neg) ids = list(anm.all_ids()) assert ids == matched
def _matcher(self, matchercls, q_weight_fn, searcher, weighting=None, **kwargs): # q_weight_fn is a function which is called on each query and returns a # "weight" value which is used to build a huffman-like matcher tree. If # q_weight_fn is None, an order-preserving binary tree is used instead. # Pull any queries inside a Not() out into their own list subs, nots = self._split_queries() if not subs: return matching.NullMatcher() # Create a matcher from the list of subqueries subms = [q.matcher(searcher, weighting=weighting) for q in subs] if len(subms) == 1: m = subms[0] elif q_weight_fn is None: m = make_binary_tree(matchercls, subms) else: w_subms = [(q_weight_fn(q), m) for q, m in zip(subs, subms)] m = make_weighted_tree(matchercls, w_subms) # If there were queries inside Not(), make a matcher for them and # wrap the matchers in an AndNotMatcher if nots: if len(nots) == 1: notm = nots[0].matcher(searcher) else: r = searcher.reader() notms = [(q.estimate_size(r), q.matcher(searcher)) for q in nots] notm = make_weighted_tree(matching.UnionMatcher, notms) if notm.is_active(): m = matching.AndNotMatcher(m, notm) # If this query had a boost, add a wrapping matcher to apply the boost if self.boost != 1.0: m = matching.WrappingMatcher(m, self.boost) return m
def matcher(self, searcher, context=None): scoredm = self.a.matcher(searcher, context) requiredm = self.b.matcher(searcher, searcher.boolean_context()) return matching.AndNotMatcher(scoredm, requiredm)