def test_basic_traversal(self): tree = (AndOperation(Word("foo"), Word("bar"))) transformer = self.BasicTransformer() new_tree = transformer.visit(tree) self.assertEqual(new_tree, (AndOperation(Word("lol"), Word("lol"))))
def test_or_resolution(self): tree = (UnknownOperation(Word("a"), Word("b"), AndOperation(Word("c"), Word("d")))) expected = (OrOperation(Word("a"), Word("b"), AndOperation(Word("c"), Word("d")))) resolver = UnknownOperationResolver(resolve_to=OrOperation) self.assertEqual(resolver(tree), expected)
def test_lucene_resolution_simple(self): tree = (UnknownOperation(Word("a"), Word("b"), UnknownOperation(Word("c"), Word("d")))) expected = (AndOperation(Word("a"), Word("b"), AndOperation(Word("c"), Word("d")))) resolver = UnknownOperationResolver(resolve_to=None) self.assertEqual(resolver(tree), expected)
def test_basic_traversal(self): tree = (AndOperation(Word("foo"), Word("bar"))) visitor = self.BasicVisitor() nodes = list(visitor.visit(tree)) self.assertListEqual( [AndOperation(Word('foo'), Word('bar')), Word('foo'), Word('bar')], nodes)
def test_auto_name_nested(self): tree = AndOperation( OrOperation( SearchField("bar", Word("test")), AndOperation( Proximity(Phrase('"test"'), 2), SearchField("baz", Word("test")), ), ), Group(UnknownOperation( Fuzzy(Word("test")), Phrase('"test"'), ), ), ) names = auto_name(tree) self.assertEqual(sorted(names.keys()), list("abcdefgh")) # and and1 = tree self.assertEqual(get_name(and1), None) # - or or1 = and1.children[0] self.assertEqual(get_name(or1), "a") self.assertEqual(names["a"], (0, )) # -- search field sfield1 = or1.children[0] self.assertEqual(get_name(sfield1), "c") self.assertEqual(names["c"], (0, 0)) self.assertEqual(get_name(sfield1.expr), None) # -- and and2 = or1.children[1] self.assertEqual(get_name(and2), "d") self.assertEqual(names["d"], (0, 1)) # --- proximity phrase self.assertEqual(get_name(and2.children[0]), "e") self.assertEqual(names["e"], (0, 1, 0)) self.assertEqual(get_name(and2.children[0].term), None) # --- search field sfield2 = and2.children[1] self.assertEqual(get_name(sfield2), "f") self.assertEqual(names["f"], (0, 1, 1)) self.assertEqual(get_name(sfield2.expr), None) # - group group1 = and1.children[1] self.assertEqual(get_name(group1), "b") self.assertEqual(names["b"], (1, )) # -- unknown op unknownop1 = group1.children[0] self.assertEqual(get_name(unknownop1), None) # --- fuzzy word self.assertEqual(get_name(unknownop1.children[0]), "g") self.assertEqual(names["g"], (1, 0, 0)) self.assertEqual(get_name(unknownop1.children[0].term), None) # --- phrase self.assertEqual(get_name(unknownop1.children[1]), "h") self.assertEqual(names["h"], (1, 0, 1))
def test_removal(self): tree = AndOperation( OrOperation(Word("spam"), Word("ham")), AndOperation(Word("foo"), Phrase('"bar"')), AndOperation(Phrase('"baz"'), Phrase('"biz"')), ) transformer = self.BasicTransformer() new_tree = transformer.visit(tree) self.assertEqual( new_tree, AndOperation(OrOperation(Word("lol"), Word("lol")), Word("lol")), )
def test_silent_value_error(self): # in the case some attribute mislead the search for node do not raise tree = AndOperation(Word("a"), Word("b")) setattr(tree, "misleading1", ()) setattr(tree, "misleading2", []) # hackishly patch __dict__ to be sure we have operands in right order for test tree.__dict__ = collections.OrderedDict(tree.__dict__) tree.__dict__['operands'] = tree.__dict__.pop( 'operands') # operands are now last transformer = self.BasicTransformer() new_tree = transformer.visit(tree) self.assertEqual(new_tree, AndOperation(Word("lol"), Word("lol")))
def test_check_ok(self): query = (AndOperation( SearchField( "f", FieldGroup( AndOperation( Boost(Proximity(Phrase('"foo bar"'), 4), "4.2"), Prohibit(Range("100", "200"))))), Group(OrOperation(Fuzzy(Word("baz"), ".8"), Plus(Word("fizz")))))) check = LuceneCheck() self.assertTrue(check(query)) self.assertEqual(check.errors(query), []) check = LuceneCheck(zeal=1) self.assertTrue(check(query)) self.assertEqual(check.errors(query), [])
def test_lucene_resolution_last_op(self): tree = (OrOperation( Word("a"), Word("b"), UnknownOperation(Word("c"), Word("d")), AndOperation(Word("e"), UnknownOperation(Word("f"), Word("g"))), UnknownOperation(Word("i"), Word("j")), OrOperation(Word("k"), UnknownOperation(Word("l"), Word("m"))), UnknownOperation(Word("n"), Word("o")))) expected = (OrOperation( Word("a"), Word("b"), OrOperation(Word("c"), Word("d")), AndOperation(Word("e"), AndOperation(Word("f"), Word("g"))), AndOperation(Word("i"), Word("j")), OrOperation(Word("k"), OrOperation(Word("l"), Word("m"))), OrOperation(Word("n"), Word("o")))) resolver = UnknownOperationResolver(resolve_to=None) self.assertEqual(resolver(tree), expected)
def test_lucene_resolution_last_op_with_group(self): tree = (OrOperation( Word("a"), Word("b"), Group( AndOperation(Word("c"), UnknownOperation(Word("d"), Word("e")))), UnknownOperation(Word("f"), Word("g")), Group(UnknownOperation(Word("h"), Word("i"))))) expected = (OrOperation( Word("a"), Word("b"), Group(AndOperation(Word("c"), AndOperation(Word("d"), Word("e")))), OrOperation(Word("f"), Word("g")), Group(AndOperation(Word("h"), Word("i"))))) resolver = UnknownOperationResolver(resolve_to=None) self.assertEqual(resolver(tree), expected)
def test_unknown_item_type(self): check = LuceneCheck() query = AndOperation("foo", 2) self.assertFalse(check(query)) self.assertEqual(len(check.errors(query)), 2) self.assertIn("Unknown item type", check.errors(query)[0]) self.assertIn("Unknown item type", check.errors(query)[1])
def test_minus(self): tree = (AndOperation(Prohibit(Word("test", tail=" ")), Prohibit(Word("foo", tail=" "), head=" "), Not(Word("bar", head=" "), head=" "))) parsed = parser.parse("-test AND -foo AND NOT bar") self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_parents_tracking_no_tracking(self): tree = AndOperation(Word("foo"), Phrase('"bar"')) # no parents tracking ! visitor = self.TrackingParentsVisitor() nodes = visitor.visit(tree) self.assertListEqual([(tree, None), (Word("foo"), None), (Phrase('"bar"'), None)], nodes)
def test_and_operation(self): tree = AndOperation(Word("foo"), Phrase('"bar"'), Word("baz")) all_paths = {(0, ), (1, ), (2, )} matching = set() paths_ok, paths_ko = self.propagate_matching(tree, matching, all_paths - matching) self.assertEqual(paths_ok, set()) self.assertEqual(paths_ko, { (), (0, ), (1, ), (2, ), }) matching = {(2, )} paths_ok, paths_ko = self.propagate_matching(tree, matching, all_paths - matching) self.assertEqual(paths_ok, {(2, )}) self.assertEqual(paths_ko, {(), (0, ), (1, )}) matching = {(0, ), (2, )} paths_ok, paths_ko = self.propagate_matching(tree, matching, all_paths - matching) self.assertEqual(paths_ok, {(0, ), (2, )}) self.assertEqual(paths_ko, {(), (1, )}) matching = {(0, ), (1, ), (2, )} paths_ok, paths_ko = self.propagate_matching(tree, matching, all_paths - matching) self.assertEqual(paths_ok, {(), (0, ), (1, ), (2, )}) self.assertEqual(paths_ko, set())
def test_named_queries_and(self): tree = AndOperation(SearchField("text", Word("foo")), SearchField("spam", Word("bar"))) set_name(tree.operands[0], "a") set_name(tree.operands[1], "b") result = self.transformer(tree) self.assertEqual( result, { 'bool': { 'must': [{ 'term': { 'text': { '_name': 'a', 'value': 'foo' } } }, { 'match': { 'spam': { '_name': 'b', 'query': 'bar', 'zero_terms_query': 'all' } } }] } })
def test_plus(self): tree = (AndOperation(Plus(Word("test", tail=" ")), Word("foo", head=" ", tail=" "), Plus(Word("bar"), head=" "))) parsed = parser.parse("+test AND foo AND +bar") self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_auto_name_nested(self): tree = AndOperation( OrOperation( SearchField("bar", Word("test")), AndOperation( Proximity(Phrase('"test"'), 2), SearchField("baz", Word("test")), ), ), Group( UnknownOperation( Fuzzy(Word("test")), Phrase('"test"'), ), ), ) auto_name(tree) # and and1 = tree self.assertEqual(get_name(and1), "0") # - or or1 = and1.children[0] self.assertEqual(get_name(or1), "0_0") # --- search field word sfield1 = or1.children[0] self.assertFalse(get_name(sfield1)) self.assertEqual(get_name(sfield1.expr), "0_0_0") # --- and and2 = or1.children[1] self.assertEqual(get_name(and2), "0_0_1") # ----- proximity phrase self.assertEqual(get_name(and2.children[0].term), "0_0_1_0") # ----- search field word sfield2 = and2.children[1] self.assertFalse(get_name(sfield2)) self.assertEqual(get_name(sfield2.expr), "0_0_1_1") # - group group1 = and1.children[1] self.assertEqual(get_name(group1), None) # --- unknown op unknownop1 = group1.children[0] self.assertEqual(get_name(unknownop1), "0_1") # ----- fuzzy word self.assertEqual(get_name(unknownop1.children[0].term), "0_1_0") # ----- phrase self.assertEqual(get_name(unknownop1.children[1]), "0_1_1")
def test_regex(self): tree = (AndOperation( Regex('/a regex (with some.*match+ing)?/', tail=" "), Regex('/Another one/', head=" "))) parsed = parser.parse( '/a regex (with some.*match+ing)?/ AND /Another one/') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_generic_visit(self): tree = AndOperation(Word("foo"), Word("bar")) visitor = TreeVisitor() nodes = visitor.visit(tree) self.assertEqual(nodes, []) # with a context for coverage… nodes = visitor.visit(tree, context={}) self.assertEqual(nodes, [])
def test_phrase(self): tree = (AndOperation( Phrase('"a phrase (AND a complicated~ one)"', tail=" "), Phrase('"Another one"', head=" "))) parsed = parser.parse( '"a phrase (AND a complicated~ one)" AND "Another one"') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_repeating_expression(self): # non regression test tree = AndOperation( Group(OrOperation(Word('bar'), Word('foo'))), Group(OrOperation(Word('bar'), Word('foo'), Word('spam'))), ) # basic transformer should not change tree same_tree = TreeTransformer().visit(copy.deepcopy(tree)) self.assertEqual(same_tree, tree)
def test_mro(self): visitor = self.MROVisitor() tree = OrOperation(Word('a'), Word('b')) result = visitor.visit(tree) self.assertEquals(list(result), ['a OR b', 'a', 'b']) tree = AndOperation(Word('a'), Word('b')) result = visitor.visit(tree) self.assertEquals(list(result), ['a BASE_OP b', 'a', 'b'])
def test_mro(self): visitor = self.MROVisitor() tree = OrOperation(Word('a'), Word('b')) result = visitor.visit(tree) self.assertEquals(result, 'a OR b') tree = OrOperation(AndOperation(Word('a'), Word('b')), Word('c')) result = visitor.visit(tree) self.assertEquals(result, 'a BASE_OP b OR c')
def test_auto_head_tail_no_change_to_existing(self): tree = AndOperation( Range(Word("foo", tail="\t"), Word("bar", head="\n"), tail="\r"), Not(Word("baz", head="\t\t"), head="\n\n", tail="\r\r"), Word("spam", head="\t\n"), ) self.assertEqual(str(tree), "[foo\tTO\nbar]\rAND\n\nNOT\t\tbaz\r\rAND\t\nspam") self.assertEqual(str(auto_head_tail(tree)), "[foo\tTO\nbar]\rAND\n\nNOT\t\tbaz\r\rAND\t\nspam")
def test_visit_complex(self): tree = AndOperation( Group( OrOperation(Word("foo"), Word("bar"), Boost(Fuzzy(Word("baz")), force=2))), Proximity(Phrase('"spam ham"')), SearchField("fizz", Regex("/fuzz/")), ) transformed = self.transform(tree) expected = AndOperation( Group( OrOperation( Word("foo@0-0-0"), Word("bar@0-0-1"), Boost(Fuzzy(Word("baz@0-0-2-0-0")), force=2), )), Proximity(Phrase('"spam ham@1-0"')), SearchField("fizz", Regex("/fuzz@2-0/")), ) self.assertEqual(transformed, expected)
def test_boost(self): tree = (UnknownOperation( Boost(Phrase('"foo bar"'), Decimal("3.0"), tail=" "), Boost( Group( AndOperation(Word('baz', tail=" "), Word('bar', head=" "))), Decimal("2.1")))) parsed = parser.parse('"foo bar"^3 (baz AND bar)^2.1') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_mro(self): visitor = self.MROVisitor() tree = OrOperation(Word('a'), Word('b')) result = visitor.visit(tree) self.assertEquals(list(result), ['a OR b', 'a', 'b']) # AndOperation has no specific method, # but inherists BaseOperation, hence uses visit_base_operation tree = AndOperation(Word('a'), Word('b')) result = visitor.visit(tree) self.assertEquals(list(result), ['a BASE_OP b', 'a', 'b'])
def test_range(self): tree = (AndOperation( SearchField("foo", Range(Word("10", tail=" "), Word("100", head=" "), True, True), tail=" "), SearchField("bar", Range(Word("a*", tail=" "), Word("*", head=" "), True, False), head=" "))) parsed = parser.parse('foo:[10 TO 100] AND bar:[a* TO *}') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_parents_tracking(self): tree = AndOperation(Word("foo"), Proximity(Phrase('"bar"'), 2)) visitor = self.TrackingParentsVisitor(track_parents=True) nodes = visitor.visit(tree) self.assertListEqual( [ (tree, None), (Word("foo"), (tree, )), (Proximity(Phrase('"bar"'), degree=2), (tree, )), (Phrase('"bar"'), (tree, Proximity(Phrase('"bar"'), 2))), ], nodes, )
def test_nested_negation(self): for NegClass in (Prohibit, Not): with self.subTest("%r" % NegClass): tree = AndOperation( NegClass( OrOperation( NegClass( AndOperation( NegClass(Word("a")), Word("b"), )), Word("c"), )), Word("d"), ) a, b, c, d = (0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 1), (0, 0, 1), (1, ) not_a, ab, not_ab = (0, 0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0) abc, not_abc, abcd = (0, 0), (0, ), () paths_ok, paths_ko = self.propagate_matching( tree, set(), {a, b, c, d}) self.assertEqual(paths_ok, {not_a, not_ab, abc}) self.assertEqual(paths_ko, {a, b, ab, c, not_abc, d, abcd}) paths_ok, paths_ko = self.propagate_matching( tree, {b, d}, {a, c}) self.assertEqual(paths_ok, {not_a, b, ab, not_abc, d, abcd}) self.assertEqual(paths_ko, {a, not_ab, c, abc}) paths_ok, paths_ko = self.propagate_matching( tree, {a, b, c}, {d}) self.assertEqual(paths_ok, {a, b, not_ab, c, abc}) self.assertEqual(paths_ko, {not_a, ab, not_abc, d, abcd}) paths_ok, paths_ko = self.propagate_matching( tree, {a, b, c, d}, set()) self.assertEqual(paths_ok, {a, b, not_ab, c, abc, d}) self.assertEqual(paths_ko, {not_a, ab, not_abc, abcd})