Files
Sheerka-Old/tests/parsers/test_LogicalOperatorParser.py
T
kodjo 54e5681c5a Fixed #109 : Mix python and concept. List comprehension
Fixed #110 : SheerkaDebugManager: add list_debug_settings
Fixed #111 : SheerkaDebugManager: Implement ListDebugLogger
Fixed #112 : SyaNodeParser: rewrite this parser
Fixed #113 : Sheerka.: Add enable_parser_caching to disable parsers caching
Fixed #114 : SyaNodeParser : Implement fast cache to resolve unrecognized tokens requests
Fixed #115 : BnfNodeParser : Implement fast cache to resolve unrecognized tokens requests
Fixed #116 : SequenceNodeParser : Implement fast cache to resolve unrecognized tokens requests
Fixed #117 : ResolveMultiplePluralAmbiguityEvaluator: Resolve Multiple plural ambiguity
2021-09-06 11:51:50 +02:00

540 lines
25 KiB
Python

import pytest
from core.builtin_concepts import BuiltinConcepts
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import TokenKind
from parsers.BaseExpressionParser import TrueifyVisitor, IsAQuestionVisitor, LeftPartNotFoundError, \
ParenthesisMismatchError, compile_disjunctions, NotNode, AndNode, OrNode
from parsers.BaseParser import UnexpectedEofParsingError, UnexpectedTokenParsingError
from parsers.LogicalOperatorParser import LogicalOperatorParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import EXPR, OR, AND, NOT, \
get_expr_node_from_test_node
class DoNotCompareStartStopContextManager:
def __init__(self):
self.original_not_eq = None
self.original_and_eq = None
self.original_or_eq = None
@staticmethod
def not_eq(self, other):
if not isinstance(other, NotNode):
return False
return self.node == other.node
@staticmethod
def and_eq(self, other):
if not isinstance(other, AndNode):
return False
return self.parts == other.parts
@staticmethod
def or_eq(self, other):
if not isinstance(other, OrNode):
return False
return self.parts == other.parts
def __enter__(self):
self.original_not_eq = NotNode.__eq__
self.original_and_eq = AndNode.__eq__
self.original_or_eq = OrNode.__eq__
NotNode.__eq__ = self.not_eq
AndNode.__eq__ = self.and_eq
OrNode.__eq__ = self.or_eq
def __exit__(self, *args):
NotNode.__eq__ = self.original_not_eq
AndNode.__eq__ = self.original_and_eq
OrNode.__eq__ = self.original_or_eq
class TestLogicalOperatorParser(TestUsingMemoryBasedSheerka):
def init_parser(self):
sheerka, context = self.init_concepts()
parser = LogicalOperatorParser()
return sheerka, context, parser
@pytest.mark.parametrize("expression, expected", [
("one complicated expression", EXPR("one complicated expression")),
("function_call(a,b,c)", EXPR("function_call(a,b,c)")),
("one expression or another expression", OR(EXPR("one expression"), EXPR("another expression"))),
("one expression and another expression", AND(EXPR("one expression"), EXPR("another expression"))),
("not one", NOT(EXPR("one"))),
("one and not two", AND(EXPR("one"), NOT(EXPR("two")))),
("not one and two", AND(NOT(EXPR("one")), EXPR("two"))),
("one or not two", OR(EXPR("one"), NOT(EXPR("two")))),
("not one or two", OR(NOT(EXPR("one")), EXPR("two"))),
("one or two or three", OR(EXPR("one"), EXPR("two"), EXPR("three"))),
("one and two and three", AND(EXPR("one"), EXPR("two"), EXPR("three"))),
("one or two and three", OR(EXPR("one"), AND(EXPR("two"), EXPR("three")))),
("one and two or three", OR(AND(EXPR("one"), EXPR("two")), EXPR("three"))),
("one and (two or three)", AND(EXPR("one"), OR(EXPR("two"), EXPR("three")), source="one and (two or three)")),
("not not one", NOT(NOT(EXPR("one")))),
("not (one and two)", NOT(AND(EXPR("one"), EXPR("two")), source="not (one and two)")),
("one 'and' two or three", OR(EXPR("one 'and' two"), EXPR("three"))),
("not ((a or b) and (c or d))", NOT(AND(OR(EXPR("a"), EXPR("b")), OR(EXPR("c"), EXPR("d")),
source="(a or b) and (c or d)"),
source="not ((a or b) and (c or d))")),
("not ((a and b) or (c and d))", NOT(OR(AND(EXPR("a"), EXPR("b")), AND(EXPR("c"), EXPR("d")),
source="(a and b) or (c and d)"),
source="not ((a and b) or (c and d))")),
("(one and two)", AND(EXPR("one"), EXPR("two"))),
("(one or two)", OR(EXPR("one"), EXPR("two"))),
("(not one)", NOT(EXPR("one"))),
])
def test_i_can_parse_expression(self, expression, expected):
sheerka, context, parser = self.init_parser()
expected = get_expr_node_from_test_node(expression, expected)
res = parser.parse(context, ParserInput(expression))
wrapper = res.body
expressions = res.body.body
assert res.status
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert expressions == expected
@pytest.mark.parametrize("expression, expected_errors", [
("one or", [UnexpectedEofParsingError("while parsing 'or'")]),
("one and", [UnexpectedEofParsingError("while parsing 'and'")]),
("and one", [LeftPartNotFoundError("and", 0)]),
("or one", [LeftPartNotFoundError("or", 0)]),
("or", [LeftPartNotFoundError("or", 0), UnexpectedEofParsingError("while parsing 'or'")]),
("and", [LeftPartNotFoundError("and", 0), UnexpectedEofParsingError("while parsing 'and'")]),
])
def test_i_can_detect_error(self, expression, expected_errors):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput(expression))
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
assert res.body.body == expected_errors
def test_i_can_detect_unexpected_not_error(self):
sheerka, context, parser = self.init_parser()
expression = "a cat is not a human"
res = parser.parse(context, ParserInput(expression))
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
assert isinstance(res.body.body[0], UnexpectedTokenParsingError)
@pytest.mark.parametrize("expression, expected_error, parenthesis_type, index", [
("(", BuiltinConcepts.NOT_FOR_ME, TokenKind.LPAR, 0),
(")", BuiltinConcepts.NOT_FOR_ME, TokenKind.RPAR, 0),
("one and two(", BuiltinConcepts.ERROR, TokenKind.LPAR, 11),
("one (", BuiltinConcepts.NOT_FOR_ME, TokenKind.LPAR, 4),
("one (and", BuiltinConcepts.NOT_FOR_ME, TokenKind.LPAR, 4),
("one and two)", BuiltinConcepts.ERROR, TokenKind.RPAR, 11),
("one )", BuiltinConcepts.ERROR, TokenKind.RPAR, 4),
("one ) and", BuiltinConcepts.ERROR, TokenKind.RPAR, 4),
])
def test_i_can_detect_unbalanced_parenthesis(self, expression, expected_error, parenthesis_type, index):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput(expression))
assert not res.status
if expected_error == BuiltinConcepts.NOT_FOR_ME:
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
assert isinstance(res.body.reason[0], ParenthesisMismatchError)
assert res.body.reason[0].token.type == parenthesis_type
assert res.body.reason[0].token.index == index
else:
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
assert isinstance(res.body.body[0], ParenthesisMismatchError)
assert res.body.body[0].token.type == parenthesis_type
assert res.body.body[0].token.index == index
def test_i_can_detect_empty_expression(self):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput(""))
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
@pytest.mark.parametrize("expression, to_trueify, to_skip, expected", [
("a", ["b"], ["a"], "a"),
("b", ["b"], ["a"], "True"),
("a and b", ["b"], ["a"], "a and True"),
("b or a", ["b"], ["a"], "True or a"),
("isinstance(b, str)", ["b"], ["a"], "True"),
("isinstance(b, str) or instance(a, str)", ["b"], ["a"], "True or instance(a, str)"),
("a and b or c", ["b", "c"], ["a"], "a and True or True"),
("a + b or a + c", ["b", "c"], ["a"], "a + b or a + c"),
])
def test_i_can_trueify(self, expression, to_trueify, to_skip, expected):
sheerka, context, parser = self.init_parser()
expr_node = parser.parse(context, ParserInput(expression)).body.body
translated_node = TrueifyVisitor(to_trueify, to_skip).visit(expr_node)
assert str(translated_node) == expected
@pytest.mark.parametrize("expression, expected", [
("foo", None),
("", None),
("is_question()", True),
(" is_question() ", True),
("is_question ( ) ", True),
("is _question()", None),
("is_ question()", None),
("is _ question()", None),
("context.in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", True),
("not is_question()", False),
("not context.in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", False),
("not foo", None),
("not is_question() and not is_question()", False),
("not is_question() and is_question()", False),
("not is_question() and foo", False),
("is_question() and not is_question()", False),
("is_question() and is_question()", True),
("is_question() and foo", True),
("foo and not is_question()", False),
("foo and is_question()", True),
("foo and bar", None),
("not is_question() or not is_question()", False),
("not is_question() or is_question()", True),
("not is_question() or foo", False),
("is_question() or not is_question()", True),
("is_question() or is_question()", True),
("is_question() or foo", True),
("foo or not is_question()", False),
("foo or is_question()", True),
("foo or bar", None),
])
def test_is_a_question(self, expression, expected):
sheerka, context, parser = self.init_parser()
expr_node = parser.parse(context, ParserInput(expression)).body.body
assert IsAQuestionVisitor().visit(expr_node) == expected
@pytest.mark.parametrize("expression, expected", [
("a", [EXPR("a")]),
("a and b and c", [AND(EXPR("a"), EXPR("b"), EXPR("c"))]),
("a or b or c", [EXPR("a"),
EXPR("b"),
EXPR("c")]),
("a and b or c", [AND(EXPR("a"), EXPR("b")), EXPR("c")]),
("a or b and c", [EXPR("a"),
AND(EXPR("b"), EXPR("c"))]),
("(a or b) and c", [AND(EXPR("a"), EXPR("c")),
AND(EXPR("b"), EXPR("c"))]),
("a or (b or c) and d", [EXPR("a"),
AND(EXPR("b"), EXPR("d")),
AND(EXPR("c"), EXPR("d"))]),
("not a", [NOT(EXPR("a"))]),
("not (a and b)", [NOT(AND(EXPR("a"), EXPR("b")))]),
("not (a or b)", [AND(NOT(EXPR("a")), NOT(EXPR("b")))]),
("(a or b) and not (c or d)", [AND(EXPR("a"), NOT(EXPR("c")), NOT(EXPR("d"))),
AND(EXPR("b"), NOT(EXPR("c")), NOT(EXPR("d")))]),
("(a or b) or not (c or d)", [EXPR("a"),
EXPR("b"),
AND(NOT(EXPR("c")), NOT(EXPR("d")))]),
("(a and b) and not (c or d)", [AND(EXPR("a"), EXPR("b"), NOT(EXPR("c")), NOT(EXPR("d")))]),
("(a and b) or not (c or d)", [AND(EXPR("a"), EXPR("b")),
AND(NOT(EXPR("c")), NOT(EXPR("d")))]),
("a and (b and c)", [AND(EXPR("a"), EXPR("b"), EXPR("c"))]),
("a or (b or c)", [EXPR("a"),
EXPR("b"),
EXPR("c")]),
])
def test_i_can_compile_disjunction(self, expression, expected):
sheerka, context, parser = self.init_parser()
resolved_expected = [get_expr_node_from_test_node(expression, e) for e in expected]
expr_node = parser.parse(context, ParserInput(expression)).body.body
with DoNotCompareStartStopContextManager():
res = compile_disjunctions(expr_node)
assert res == resolved_expected
# @pytest.mark.parametrize("expression, expected", [
# ("foo", "foo"),
# ("one two", "one two"),
# ("foo is a bar", CMV("is a", x='foo', y='bar')),
# ("one two is a bar", [CNC("is a", "one two is a bar", x="one two", y="bar")]),
# ("foo is an foo bar",
# [CNC("is an", "foo is an foo bar", x=DoNotResolve(value='foo'), exclude_body=True)]),
# ])
# def test_i_can_get_compiled_expr_from_simple_concepts_expressions(self, expression, expected):
# concepts_map = {
# "foo": Concept("foo"),
# "bar": Concept("bar"),
# "one two": Concept("one two"),
# "is a": Concept("x is a y").def_var("x").def_var("y"),
# "is an": Concept("x is an y", definition="('foo'|'bar')=x 'is an' 'foo bar'").def_var("x"),
# }
# sheerka, context, *concepts = self.init_test().with_concepts(*concepts_map.values(), create_new=True).unpack()
#
# parser = LogicalOperatorParser()
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, [expr_node], "test")
#
# assert len(return_values) == 1
# ret = return_values[0]
#
# if isinstance(expected, list):
# expected_nodes = compute_expected_array(concepts_map, expression, expected)
# compare_with_test_object(ret.body.body, expected_nodes)
# else:
# expected_concept = resolve_test_concept(concepts_map, expected)
# compare_with_test_object(ret.body.body, expected_concept)
# @pytest.mark.parametrize("expression", [
# "a == 5",
# "foo > 5",
# "func() == 5",
# "not a == 5",
# "not foo > 5",
# "not func() == 5",
# "isinstance(a, int)",
# "func()",
# "not isinstance(a, int)",
# "not func()"
# ])
# def test_i_can_get_compiled_expr_from_simple_python_expressions(self, expression):
# sheerka, context, = self.init_test().unpack()
#
# parser = LogicalOperatorParser()
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, [expr_node], "test")
#
# assert len(return_values) == 1
# ret = return_values[0]
#
# assert ret.status
# python_node = ret.body.body.get_python_node()
# _ast = ast.parse(expression, mode="eval")
# expected_python_node = PythonNode(expression, _ast)
# assert python_node == expected_python_node
#
# @pytest.mark.parametrize("expression", [
# "a and not b",
# "not b and a",
# "__ret and not __ret.status",
# ])
# def test_i_can_compile_negative_conjunctions_when_pure_python(self, expression):
# sheerka, context, *concepts = self.init_concepts("foo")
#
# parser = LogicalOperatorParser()
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, expr_node.parts, "test")
#
# ast_ = ast.parse(expression, "<source>", 'eval')
# expected_python_node = PythonNode(expression, ast_)
#
# assert len(return_values) == 1
# ret = return_values[0]
#
# assert sheerka.objvalue(ret) == expected_python_node
#
# @pytest.mark.parametrize("expression, text_to_compile", [
# ("foo bar == 5", "__C__foo0bar__1001__C__ == 5"),
# ("not foo bar == 5", "not __C__foo0bar__1001__C__ == 5"),
# ])
# def test_i_can_get_compiled_expr_from_python_and_concept(self, expression, text_to_compile):
# sheerka, context, *concepts = self.init_test().with_concepts(Concept("foo bar"), create_new=True).unpack()
#
# parser = LogicalOperatorParser()
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, [expr_node], "test")
#
# assert len(return_values) == 1
# ret = return_values[0]
#
# assert ret.status
# python_node = ret.body.body.get_python_node()
# _ast = ast.parse(text_to_compile, mode="eval")
# expected_python_node = PythonNode(text_to_compile, _ast, expression)
# assert python_node == expected_python_node
#
# def test_i_can_get_compiled_expr_from__mix_of_concepts_and_python(self):
# sheerka, context, animal, cat, dog, pet, is_a, is_an = self.init_test().with_concepts(
# Concept("animal"),
# Concept("a cat"),
# Concept("dog"),
# Concept("pet"),
# Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
# Concept("x is an y", pre="is_question()", definition="('cat'|'bird')=x 'is an' animal").def_var("x"),
# create_new=True
# ).unpack()
#
# parser = LogicalOperatorParser()
# expression = "not a cat is a pet and not bird is an animal and not x > 5 and not dog is a pet"
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, expr_node.parts, "test")
#
# to_compile = 'not __C__00var0000is0a000var001__1005__C__'
# to_compile += ' and not __C__00var0000is0an0y__1006__C__'
# to_compile += ' and not x > 5'
# to_compile += ' and not __C__00var0000is0a000var001__1005_1__C__'
# ast_ = ast.parse(to_compile, "<source>", 'eval')
# expected_python_node = PythonNode(to_compile, ast_, expression)
#
# assert len(return_values) == 1
# ret = return_values[0]
# python_node = ret.body.body
# assert python_node == expected_python_node
# compare_with_test_object(python_node.objects, {
# "__C__00var0000is0a000var001__1005__C__": CC(is_a, x=cat, y=pet),
# "__C__00var0000is0an0y__1006__C__": CC(is_an, exclude_body=True, x=DoNotResolve("bird"), animal=animal),
# "__C__00var0000is0a000var001__1005_1__C__": CMV(is_a, x="dog", y="pet"),
# })
#
# def test_i_can_get_compiled_expr_from_mix(self):
# sheerka, context, animal, cat, dog, pet, is_a, is_an = self.init_test().with_concepts(
# Concept("animal"),
# Concept("a cat"),
# Concept("dog"),
# Concept("pet"),
# Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
# Concept("x is an y", pre="is_question()", definition="('cat'|'bird')=x 'is an' animal").def_var("x"),
# create_new=True
# ).unpack()
#
# expression = "a cat is a pet and bird is an animal and x > 5 and dog is a pet"
# parser = LogicalOperatorParser()
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, expr_node.parts, "test")
#
# assert len(return_values) == 1
# ret = return_values[0]
#
# to_compile = '__C__00var0000is0a000var001__1005__C__ and __C__00var0000is0an0y__1006__C__ and x > 5 and __C__00var0000is0a000var001__1005_1__C__'
# ast_ = ast.parse(to_compile, "<source>", 'eval')
# expected_python_node = PythonNode(to_compile, ast_, expression)
#
# python_node = ret.body.body
# assert python_node == expected_python_node
# compare_with_test_object(python_node.objects, {
# "__C__00var0000is0a000var001__1005__C__": CC(is_a, x=cat, y=pet),
# "__C__00var0000is0an0y__1006__C__": CC(is_an, exclude_body=True, x=DoNotResolve("bird"), animal=animal),
# "__C__00var0000is0a000var001__1005_1__C__": CMV(is_a, x="dog", y="pet"),
# })
#
# def test_i_can_get_compiled_expr_when_multiple_choices(self):
# sheerka, context, *concepts = self.init_test().with_concepts(
# Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
# Concept("x is a y", pre="is_question()", body="isa(x, y)").def_var("x").def_var("y"),
# create_new=True
# ).unpack()
#
# parser = LogicalOperatorParser()
# expression = "a is a b"
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, [expr_node], "test")
#
# assert len(return_values) == 2
#
# ret = return_values[0]
# compare_with_test_object(sheerka.objvalue(ret)[0].concept, CMV(concepts[0], x="a", y="b"))
#
# ret = return_values[1]
# compare_with_test_object(sheerka.objvalue(ret)[0].concept, CMV(concepts[1], x="a", y="b"))
#
# def test_i_can_get_compiled_expr_from_mix_when_multiple_choices(self):
# sheerka, context, *concepts = self.init_test().with_concepts(
# Concept("animal"),
# Concept("a cat"),
# Concept("dog"),
# Concept("pet"),
# Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
# Concept("x is a y", pre="is_question()", body="isa(x, y)").def_var("x").def_var("y"),
# Concept("x is an y", pre="is_question()", definition="('cat'|'bird')=x 'is an' animal").def_var("x"),
# create_new=True
# ).unpack()
#
# expression = "a cat is a pet and bird is an animal and x > 5 and dog is a pet"
# parser = LogicalOperatorParser()
# expr_node = parser.parse(context, ParserInput(expression)).body.body
# return_values, _ = parser.compile_conjunctions(context, expr_node.parts, "test")
#
# assert len(return_values) == 4
# trimmed_source = "a cat is a pet and bird is an animal and x > 5 and dog is a pet"
#
# current_ret = return_values[0]
# python_source = "__C__00var0000is0a000var001__1005__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1005_1__C__"
# ast_ = ast.parse(python_source, "<source>", 'eval')
# resolved_expected = PythonNode(python_source, ast_, trimmed_source)
# assert sheerka.objvalue(current_ret) == resolved_expected
#
# current_ret = return_values[1]
# assert sheerka.isinstance(current_ret, BuiltinConcepts.RETURN_VALUE)
# python_source = "__C__00var0000is0a000var001__1005__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1006__C__"
# ast_ = ast.parse(python_source, "<source>", 'eval')
# resolved_expected = PythonNode(python_source, ast_, trimmed_source)
# assert sheerka.objvalue(current_ret) == resolved_expected
#
# current_ret = return_values[2]
# assert sheerka.isinstance(current_ret, BuiltinConcepts.RETURN_VALUE)
# python_source = "__C__00var0000is0a000var001__1006__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1005__C__"
# ast_ = ast.parse(python_source, "<source>", 'eval')
# resolved_expected = PythonNode(python_source, ast_, trimmed_source)
# assert sheerka.objvalue(current_ret) == resolved_expected
#
# current_ret = return_values[3]
# python_source = "__C__00var0000is0a000var001__1006__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1006_1__C__"
# ast_ = ast.parse(python_source, "<source>", 'eval')
# resolved_expected = PythonNode(python_source, ast_, trimmed_source)
# assert sheerka.objvalue(current_ret) == resolved_expected
#
# @pytest.mark.skip
# @pytest.mark.parametrize("expression, expected_conditions, test_obj", [
# (
# "__ret",
# ["#__x_00__|__name__|'__ret'"],
# ReturnValueConcept("Test", True, None)
# ),
# (
# "__ret.status == True",
# ["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
# ReturnValueConcept("Test", True, None)
# ),
# (
# "__ret.status",
# ["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
# ReturnValueConcept("Test", True, None)
# ),
# (
# "__ret and __ret.status",
# ["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
# ReturnValueConcept("Test", True, None)
# ),
# ])
# def test_i_can_get_rete_condition_from_python(self, expression, expected_conditions, test_obj):
# sheerka, context, = self.init_test().unpack()
# expected_full_condition = get_rete_conditions(*expected_conditions)
#
# parser = LogicalOperatorParser()
# expr_node = parser.parse(context, ParserInput(expression)).body.body
#
# nodes = expr_node.parts if isinstance(expr_node, AndNode) else [expr_node]
# _, rete_disjunctions = parser.compile_conjunctions(context, nodes, "test")
#
# assert len(rete_disjunctions) == 1
# assert rete_disjunctions == [expected_full_condition]
#
# # check against a Rete network
# network = ReteNetwork()
# rule = Rule("test", expression, None)
# rule.metadata.id = 9999
# rule.metadata.is_compiled = True
# rule.metadata.is_enabled = True
# rule.rete_disjunctions = rete_disjunctions
# network.add_rule(rule)
#
# network.add_obj("__ret", test_obj)
# matches = list(network.matches)
# assert len(matches) > 0