54e5681c5a
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
540 lines
25 KiB
Python
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
|