Files
Sheerka-Old/tests/core/test_SheerkaRuleManagerRulesCompilation.py
T
kodjo 87cab44fb8 Fixed #125: SheerkaErrorManager
Fixed #135: Change services service priorities
Fixed #136: ErrorManager: Implement recognize_error
Fixed #137: BNFNodeParser : Error when parsing regex with sub parsers
Fixed #138: get_last_errors(): real errors sources are lost
Fixed #139: OneError return value removes the origin of the error
Fixed #140: Concept variables are not correctly handled when parsing sub expression
Fixed #143: Implement has_unknown_concepts()
2021-10-28 14:04:41 +02:00

1481 lines
58 KiB
Python

import ast
import pytest
from core.builtin_concepts import ReturnValueConcept
from core.builtin_concepts_ids import BuiltinConcepts
from core.concept import Concept, DEFINITION_TYPE_DEF
from core.rule import Rule
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules
from core.sheerka.services.SheerkaExecute import ParserInput
from core.sheerka.services.SheerkaRuleManager import CompiledCondition, ReteConditionExprVisitor
from core.sheerka.services.sheerka_service import FailedToCompileError
from evaluators.PythonEvaluator import PythonEvaluator
from parsers.BaseParser import ErrorSink
from parsers.ExpressionParser import ExpressionParser
from parsers.PythonParser import PythonNode
from sheerkapython.ExprToConditions import ExprToConditionsVisitor
from sheerkarete.network import ReteNetwork
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.core.test_SheerkaRuleManager import PYTHON_EVALUATOR_NAME
from tests.parsers.parsers_utils import NEGCOND, get_rete_conditions
class BaseTestSheerkaRuleManagerRulesCompilation(TestUsingMemoryBasedSheerka):
@staticmethod
def get_conditions(context, expression):
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ExprToConditionsVisitor(context)
conditions = visitor.get_conditions(parsed)
return conditions
@staticmethod
def check_against_rete(rule_expression, rule_conditions, objects):
"""
:param rule_expression:
:param rule_conditions:
:param objects: list of tuple(name, obj)
:return:
"""
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", rule_expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = rule_conditions
network.add_rule(rule)
for name, value in objects.items():
network.add_obj(name, value)
matches = list(network.matches)
assert len(matches) == 1
@staticmethod
def check_against_python(context, rule_expression, rule_conditions, objects, expected_result=True):
bag = {}
for name, value in objects.items():
bag[name] = value
evaluate_rules_service = context.sheerka.services[SheerkaEvaluateRules.NAME]
rule = Rule(name="test", predicate=rule_expression)
rule.compiled_conditions = rule_conditions
rule.metadata.is_enabled = True
rule.metadata.is_compiled = True
evaluation = evaluate_rules_service.evaluate_rules(context, [rule], bag, set())
assert expected_result in evaluation and len(evaluation[expected_result]) == 1
@staticmethod
def evaluate_condition(context, expression, condition, objects):
with context.push("Testing conditions SheerkaRuleManagerRulesCompilation", expression) as sub_context:
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
sub_context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
sub_context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
sub_context.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
sub_context.sheerka.add_many_to_short_term_memory(sub_context, objects)
evaluator = PythonEvaluator()
for c in condition.concepts_to_reset:
c.get_hints().is_evaluated = False
return evaluator.eval(sub_context, condition.return_value)
@classmethod
def get_testing_objects(cls, context, objects_names, objects_mappings=None):
if objects_names is None:
return {}
result = {}
for name in objects_names:
if isinstance(name, tuple):
name, value = name
if value == "sheerka":
value = context.sheerka
else:
value = None
if objects_mappings and value in objects_mappings:
value = objects_mappings[value]
if name == "__ret":
return_value = ReturnValueConcept("Test", True, value)
result["__ret"] = return_value
elif name == "__ret.status":
return_value = ReturnValueConcept("Test", True, value)
result["__ret.status"] = return_value.status
elif name == "body":
return_value = ReturnValueConcept("Test", True, value)
result["body"] = return_value.body
elif name == "a_string":
result["a_string"] = value or "hello world!"
elif name == "an_int":
result["an_int"] = value or 10
else:
result[name] = value
return result
@staticmethod
def get_variables_names_from_expected_variables(expected_variables):
return {v[0] if isinstance(v, tuple) else v for v in expected_variables}
@staticmethod
def func_true(*args, **kwargs):
return True
@staticmethod
def func_identity(x):
return x
def validate_python_test(self,
context,
expression,
expected_compiled,
expected_text,
expected_variables,
expected_not_variables,
expected_objects):
sheerka = context.sheerka
conditions = BaseTestSheerkaRuleManagerRulesCompilation.get_conditions(context, expression)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled is None:
# manage cases where we only check for variable existence
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
else:
# check what was compiled
ast_ = ast.parse(expected_compiled, "<source>", 'exec' if "\n" in expected_compiled else 'eval')
expected_python_node = PythonNode(expected_compiled, ast_, expected_text)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
# check that variables detected
assert conditions[0].variables == self.get_variables_names_from_expected_variables(expected_variables)
# check that variables that MUST not be present
assert conditions[0].not_variables == expected_not_variables
# check the objects returned
assert len(expected_objects) == len(conditions[0].objects)
for obj in expected_objects:
if isinstance(obj, tuple):
assert conditions[0].objects[obj[0]] == obj[1]
else:
assert obj in conditions[0].objects
return conditions
class TestSheerkaRuleManagerRulesCompilationExists(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing variable existence:
__ret (exists)
__ret.status (exists)
body (exists)
__ret and __ret.status (both exist)
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str, expected_variables", [
(
"__ret", ["#__x_00__|__name__|'__ret'"], {"__ret"}
),
(
"__ret.status", ["#__x_00__|__name__|'__ret.status'"], {"__ret.status"}
),
(
"body", ["#__x_00__|__name__|'body'"], {"body"}
),
(
"__ret and __ret.status",
["#__x_00__|__name__|'__ret'", "#__x_01__|__name__|'__ret.status'"],
{"__ret", "__ret.status"}
),
])
def test_rete(self, expression, expected_as_list_of_str, expected_variables):
sheerka, context = self.init_test().unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
objects = self.get_testing_objects(context, expected_variables)
self.check_against_rete(expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationNotExists(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing NOT existence
not __ret
not not __ret
not __ret.status
not body
not __ret and not __ret.status
__ret and not ret.status
__ret and not __error
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str", [
("not __ret", [NEGCOND("#__x_00__|__name__|'__ret'")]),
("not not __ret", ["#__x_00__|__name__|'__ret'"]),
("not __ret.status", [NEGCOND("#__x_00__|__name__|'__ret.status'")]),
("not body", [NEGCOND("#__x_00__|__name__|'body'")]),
(
"not __ret and not __ret.status",
[NEGCOND("#__x_00__|__name__|'__ret'"), NEGCOND("#__x_01__|__name__|'__ret.status'")]
),
(
"__ret and not __ret.status",
["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__ret.status'")]
),
(
"__ret and not __error",
["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__error'")]
),
])
def test_rete(self, expression, expected_as_list_of_str):
sheerka, context = self.init_test().unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# # check against a Rete network
# objects = self.get_testing_objects(context, expected_variables)
# self.check_against_rete(expression, conditions, objects)
# @pytest.mark.parametrize("expression, expected_variables, expected_not_variables", [
# ("not __ret", set(), {"__ret"}),
# ("not not __ret", {"__ret"}, set()),
# ("not __ret.status", set(), {"__ret.status"}),
# ("not body", set(), {"body"}),
# ("not __ret and not __ret.status", set(), {"__ret", "__ret.status"}),
# ("__ret and not __ret.status", {"__ret"}, {"__ret.status"}),
# ("__ret and not __error", {"__ret"}, {"__error"}),
# ])
# def test_python(self, expression, expected_variables, expected_not_variables):
# sheerka, context = self.init_test().unpack()
#
# conditions = self.validate_python_test(context,
# expression,
# None,
# None,
# expected_variables,
# expected_not_variables,
# set())
#
# # check against SheerkaEvaluateRules
# objects = self.get_testing_objects(context, expected_variables)
# self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationSimplePython(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing Python
True
False
10 + 5
'hello world'
a + self
a + 10
a + " world !"
a + foo
a + twenty one
a + my friend
a + b
"""
# @pytest.mark.parametrize("expression, e_compiled, e_text, e_variables, e_objects, e_result", [
# (
# "True",
# "True",
# "True",
# set(),
# set(),
# True
# ),
# (
# "False",
# "False",
# "False",
# set(),
# set(),
# False
# ),
# (
# "10 + 5",
# "__o_00__",
# "10 + 5",
# set(),
# {("__o_00__", 15)},
# 15
# ),
# (
# "'hello world'",
# "__o_00__",
# "'hello world'",
# set(),
# {("__o_00__", 'hello world')},
# 'hello world'
# ),
# (
# "a + self",
# "a + self",
# "a + self",
# {("a", 10), ("self", "foo")},
# set(),
# 15
# ),
# (
# "a + 10",
# "a + 10",
# "a + 10",
# {("a", 10)},
# set(),
# 20
# ),
# (
# "a + 'world !'",
# "a + 'world !'",
# "a + 'world !'",
# {("a", "hello ")},
# set(),
# "hello world !"
# ),
# (
# "a + foo",
# "a + foo",
# "a + foo",
# {("a", 10), ("foo", "foo")},
# set(),
# 15
# ),
# (
# "a + twenty one",
# "a + __C__twenties__1004__C__",
# "a + twenty one",
# {("a", 10)},
# {"__C__twenties__1004__C__"},
# 31
# ),
# (
# "a + my friend",
# "a + __C__my0friend__1005__C__",
# "a + my friend",
# {("a", "hello ")},
# {'__C__my0friend__1005__C__'},
# "hello my friend"
# ),
# (
# "a + b",
# "a + b",
# "a + b",
# {("a", 10), ("b", 1)},
# {},
# 11
# ),
# ])
# def test_python(self, expression, e_compiled, e_text, e_variables, e_objects, e_result):
# sheerka, context, foo, one, two, twenties, my_friend = self.init_concepts(
# Concept("foo", body="5"),
# Concept("one", body="1"),
# Concept("two", body="2"),
# Concept("twenties", definition="'twenty' (one|two)=n", body='20 + n').def_var("n"),
# Concept("my friend", body="'my friend'"),
# create_new=True
# )
# ensure_evaluated(context, foo, eval_body=True)
# ensure_evaluated(context, my_friend, eval_body=True)
# conditions = self.validate_python_test(context,
# expression,
# e_compiled,
# e_text,
# e_variables,
# set(),
# e_objects)
#
# # check against SheerkaEvaluateRules
# variables_mapping = {
# "foo": foo,
# }
# namespace = self.get_testing_objects(context, e_variables, variables_mapping)
# res = self.evaluate_condition(context, expression, conditions[0], namespace)
# assert res.status
# assert sheerka.objvalue(res) == e_result
class TestSheerkaRuleManagerRulesCompilationEquality(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing simple equality:
a == 10
__ret.status == True
self == 'a'
self == sheerka
self == BuiltinConcepts.TO_DICT
self == hello 'my friend'
a == b
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str, expected_variables", [
("a == 10", ["#__x_00__|__name__|'a'", "#__x_00__|__self__|10"], {("a", 10)}),
("__ret.status == True", ["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"], {"__ret"}),
("self == 'a'", ["#__x_00__|__name__|'self'", "#__x_00__|__self__|'a'"], {("self", 'a')}),
("self == sheerka", ["#__x_00__|__name__|'self'", "#__x_00__|__self__|'__sheerka__'"], {("self", "sheerka")}),
(
"self == BuiltinConcepts.TO_DICT",
["#__x_00__|__name__|'self'", "#__x_00__|__self__|BuiltinConcepts.TO_DICT"],
{("self", BuiltinConcepts.TO_DICT)}
),
("self == hello 'my friend'",
["#__x_00__|__name__|'self'",
"#__x_00__|__is_concept__|True",
"#__x_00__|key|'hello __var__0'",
"#__x_00__|a|'my friend'"],
{("self", "hello_my_friend")}
),
# ("a == b",
# ["#__x_00__|__name__|'a'",
# "#__x_01__|__name__|'b'",
# "#__x_00__|__self__|#__x_01__"],
# {("a", 10), ("b", 10)}),
])
def test_rete(self, expression, expected_as_list_of_str, expected_variables):
sheerka, context, greetings = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
create_new=True
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
objects_mappings = {"hello_my_friend": sheerka.new(greetings, a='my friend')}
objects = self.get_testing_objects(context, expected_variables, objects_mappings)
self.check_against_rete(expression, conditions, objects)
# KSI: 2021-05-06 The last test done not produce any match because the WME (b, __self__, 10)
# is not added to memory.
# @pytest.mark.parametrize("expression, expected_compiled, expected_variables, expected_objects", [
# ("a == 10", "a == __o_00__", {("a", 10)}, {("__o_00__", 10)}),
# ("__ret.status == True", "__ret.status == True", {"__ret"}, set()),
# ("self == 'a'", "self == __o_00__", {("self", 'a')}, {("__o_00__", 'a')}),
# ("self == sheerka", "is_sheerka(self)", {("self", "sheerka")}, {}),
# (
# "self == BuiltinConcepts.TO_DICT",
# "self == BuiltinConcepts.TO_DICT",
# {("self", BuiltinConcepts.TO_DICT)},
# set()
# ),
# (
# "self == hello 'my friend'",
# """isinstance(self, Concept) and self.key == 'hello __var__0' and self.a == __o_01__""",
# {("self", "hello_my_friend")},
# {("__o_01__", "my friend")}
# ),
# ("a == b", "a == b", {("a", 10), ("b", 10)}, {}),
# ])
# def test_python(self, expression, expected_compiled, expected_variables, expected_objects):
# sheerka, context, greetings = self.init_test().with_concepts(
# Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
# create_new=True
# ).unpack()
#
# conditions = self.validate_python_test(context,
# expression,
# expected_compiled,
# expression,
# expected_variables,
# set(),
# expected_objects)
#
# # check against SheerkaEvaluateRules
# objects_mappings = {"hello_my_friend": sheerka.new(greetings, a='my friend')}
# objects = self.get_testing_objects(context, expected_variables, objects_mappings)
# self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationOtherConditions(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing other conditions than equality
a > 10
a >= 10
a < 10
a <= 10
a != 10
a > 10 and b <= 5
__ret.value > 10
10 > __ret.value
a + self > 10
a + 10 > 10
a + " world !" == "hello world !"
a + foo > 10
a + twenty one > 21
a + my friend == 'hello my friend'
10 < a + self
10 < a + 10
'hello world !' == a + ' world !'
10 < a + foo
10 > a + twenty one
'hello my friend' == a + my friend
"""
# @pytest.mark.parametrize("expression, e_compiled, e_variables, e_objects, e_result", [
# ("a > 10", "a > __o_00__", {("a", 10)}, {("__o_00__", 10)}, False),
# ("a >= 10", "a >= __o_00__", {("a", 10)}, {("__o_00__", 10)}, True),
# ("a < 10", "a < __o_00__", {("a", 10)}, {("__o_00__", 10)}, False),
# ("a <= 10", "a <= __o_00__", {("a", 10)}, {("__o_00__", 10)}, True),
# ("a != 10", "a != __o_00__", {("a", 10)}, {("__o_00__", 10)}, False),
# (
# "a > 10 and b <= 5",
# "a > __o_00__ and b <= __o_01__",
# {("a", 11), ("b", 4)},
# {("__o_00__", 10), ("__o_01__", 5)},
# True
# ),
# (
# "__ret.value > 10",
# "__ret.value > __o_00__",
# {("__ret", 15)},
# {("__o_00__", 10)},
# True
# ),
# (
# "10 > __ret.value",
# "__o_00__ > __ret.value",
# {("__ret", 15)},
# {("__o_00__", 10)},
# False
# ),
# (
# "a + self > 10",
# "a + self > __o_00__",
# {("a", 6), ("self", "foo")},
# {("__o_00__", 10)},
# True
# ),
# (
# "a + 10 > 10",
# "a + 10 > __o_00__",
# {("a", 5)},
# {("__o_00__", 10)},
# True
# ),
# (
# "a + 'world !' == 'hello world !'",
# "a + 'world !' == __o_00__",
# {("a", "hello ")},
# {("__o_00__", 'hello world !')},
# True
# ),
# (
# "a + foo > 10",
# "a + foo > __o_00__",
# {("a", 6), ("foo", "foo")},
# {("__o_00__", 10)},
# True
# ),
# (
# "a + twenty one > 21",
# "a + __C__twenties__1004__C__ > __o_00__",
# {("a", 5)},
# {"__C__twenties__1004__C__", ("__o_00__", 21)},
# True
# ),
# (
# "a + my friend == 'hello my friend'",
# "a + __C__my0friend__1005__C__ == __o_00__",
# {("a", "hello ")},
# {"__C__my0friend__1005__C__", ("__o_00__", 'hello my friend')},
# True
# ),
#
# (
# "10 < a + self",
# "__o_00__ < a + self",
# {("a", 6), ("self", "foo")},
# {("__o_00__", 10)},
# True
# ),
# (
# "10 > a + 10",
# "__o_00__ > a + 10",
# {("a", 5)},
# {("__o_00__", 10)},
# False
# ),
# (
# "'hello world !' != a + 'world !'",
# "__o_00__ != a + 'world !'",
# {("a", "hello ")},
# {("__o_00__", 'hello world !')},
# False
# ),
# (
# "10 < a + foo",
# "__o_00__ < a + foo",
# {("a", 6), ("foo", "foo")},
# {("__o_00__", 10)},
# True
# ),
# (
# "21 > a + twenty one",
# "__o_00__ > a + __C__twenties__1004__C__",
# {("a", 5)},
# {"__C__twenties__1004__C__", ("__o_00__", 21)},
# False
# ),
# (
# "'hello my friend' == a + my friend",
# "__o_00__ == a + __C__my0friend__1005__C__",
# {("a", "hello ")},
# {"__C__my0friend__1005__C__", ("__o_00__", 'hello my friend')},
# True
# ),
#
# ])
# def test_python(self, expression, e_compiled, e_variables, e_objects, e_result):
# sheerka, context, foo, one, two, twenties, my_friend = self.init_concepts(
# Concept("foo", body="5"),
# Concept("one", body="1"),
# Concept("two", body="2"),
# Concept("twenties", definition="'twenty' (one|two)=n", body='20 + n').def_var("n"),
# Concept("my friend", body="'my friend'"),
# create_new=True
# )
# ensure_evaluated(context, foo, eval_body=True)
# ensure_evaluated(context, my_friend, eval_body=True)
#
# conditions = self.validate_python_test(context,
# expression,
# e_compiled,
# expression,
# e_variables,
# set(),
# e_objects)
#
# # check against SheerkaEvaluateRules
# variables_mapping = {
# "foo": foo,
# }
# objects = self.get_testing_objects(context, e_variables, variables_mapping)
# self.check_against_python(context, expression, conditions, objects, expected_result=e_result)
class TestSheerkaRuleManagerRulesCompilationFunctionsCall(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing functions
no var : isinstance('hello', str)
with var: isinstance(a_string, str)
with and : isinstance(a_string, str) and isinstance(an_int, int)
function with concept: isinstance(self, girl)
function with concept: isinstance(self, a little boy)
function with enum: func_true(self, BuiltinConcepts.TO_DICT)
"""
def test_rete(self):
pass
# @pytest.mark.parametrize("expression, e_compiled, e_text, e_variables, e_objects", [
# (
# "isinstance('hello', str)",
# "isinstance(__o_00__, str)",
# "isinstance('hello', str)",
# set(),
# {"__o_00__"}
# ),
# (
# "isinstance(a_string, str)",
# "isinstance(a_string, str)",
# "isinstance(a_string, str)",
# {"a_string"},
# {}
# ),
# (
# "not isinstance(an_int, str)",
# "not (isinstance(an_int, str))",
# "not (isinstance(an_int, str))",
# {"an_int"},
# {}
# ),
# (
# "isinstance(a_string, str) and isinstance(an_int, int)",
# "isinstance(a_string, str) and isinstance(an_int, int)",
# "isinstance(a_string, str) and isinstance(an_int, int)",
# {"an_int", "a_string"},
# {}
# ),
# (
# "isinstance(self, girl)",
# "isinstance(self, __o_00__)",
# "isinstance(self, girl)",
# {("self", "girl")},
# {"__o_00__"}
# ),
# (
# "isinstance(self, a little boy)",
# "isinstance(self, __o_00__)",
# "isinstance(self, a little boy)",
# {("self", "a little boy")},
# {"__o_00__"}
# ),
# (
# "func_true(self, BuiltinConcepts.TO_DICT)",
# "func_true(self, BuiltinConcepts.TO_DICT)",
# "func_true(self, BuiltinConcepts.TO_DICT)",
# {("self", BuiltinConcepts.TO_DICT)},
# {}
# ),
# ])
# def test_python(self, expression, e_compiled, e_text, e_variables, e_objects):
# sheerka, context, girl, little_boy = self.init_test().with_concepts(
# Concept("girl"),
# Concept("a little boy"),
# create_new=True
# ).unpack()
#
# conditions = self.validate_python_test(context,
# expression,
# e_compiled,
# e_text,
# e_variables,
# set(),
# e_objects)
#
# # check against SheerkaEvaluateRules
# objects_mappings = {"girl": girl, "a little boy": little_boy}
# objects = self.get_testing_objects(context, e_variables, objects_mappings)
# objects["func_true"] = self.func_true
# self.check_against_python(context, expression, conditions, objects)
@pytest.mark.skip("too lazy to understand why it does not work anymore")
class TestSheerkaRuleManagerRulesCompilationRecognizeConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing recognize(path, concept)
recognize by name : recognize(__ret.body, greetings)
recognize by id : recognize(__ret.body, c:|1001:)
recognize by name using c_str : recognize(__ret.body, c:greetings:)
recognize by name + str condition : recognize(__ret.body, greetings) and __ret.body.a == 'my friend'
recognize by name + sheerka condition : recognize(__ret.body, greetings) and __ret.body.a == sheerka
recognize by name + concept condition : recognize(__ret.body, greetings) and __ret.body.a == foo
recognize by instance using sheerka : recognize(__ret.body, hello sheerka)
recognize by instance using a string : recognize(__ret.body, hello 'my friend')
recognize by instance using a concept : recognize(__ret.body, hello foo)
recognize by instance using long concept : recognize(__ret.body, hello my best friend)
recognize self : recognize(self, greetings)
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str, expected_variable, greeting_var", [
(
"recognize(__ret.body, greetings)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"],
"__ret",
None
),
(
"recognize(__ret.body, c:|1001:)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|id|'1001'"],
"__ret",
None
),
(
"recognize(__ret.body, c:greetings:)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"],
"__ret",
None
),
(
"recognize(__ret.body, greetings) and __ret.body.a == 'my friend'",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|'my friend'"],
"__ret",
"my friend",
),
(
"recognize(__ret.body, greetings) and __ret.body.a == sheerka",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|'__sheerka__'"],
"__ret",
"sheerka",
),
(
"recognize(__ret.body, greetings) and __ret.body.a == foo",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'"],
"__ret",
"foo",
),
(
"recognize(__ret.body, hello sheerka)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'__sheerka__'"],
"__ret",
"sheerka",
),
(
"recognize(__ret.body, hello 'my friend')",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'my friend'"],
"__ret",
"my friend",
),
(
"recognize(__ret.body, hello foo)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'"],
"__ret",
"foo",
),
(
"recognize(__ret.body, hello my best friend)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'my best friend'"],
"__ret",
"my best friend",
),
(
"recognize(self, greetings)",
["#__x_00__|__name__|'self'",
"#__x_00__|__is_concept__|True",
"#__x_00__|name|'greetings'"],
"self",
None,
)
])
def test_rete(self, expression, expected_as_list_of_str, expected_variable, greeting_var):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": sheerka
}
variable = variable_map.get(greeting_var, greeting_var)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
objects = self.get_testing_objects(context, [(expected_variable, to_recognize)])
self.check_against_rete(expression, conditions, objects)
# @pytest.mark.parametrize("expression, e_compiled, e_text, e_variables, greeting_var, e_objects", [
# (
# "recognize(__ret.body, greetings)",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
# {"__ret"},
# None,
# set()
# ),
# (
# "recognize(__ret.body, c:|1001:)",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'",
# {"__ret"},
# None,
# set()
# ),
# (
# "recognize(__ret.body, c:greetings:)",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
# {"__ret"},
# None,
# set()
# ),
# (
# "recognize(__ret.body, greetings) and __ret.body.a == 'my friend'",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __x_00__.a == __o_00__",
# "__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __ret.body.a == 'my friend'",
# {"__ret"},
# "my friend",
# {("__o_00__", "my friend")}
# ),
# (
# "recognize(__ret.body, greetings) and __ret.body.a == sheerka",
# """__x_00__ = __ret.body
# isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and is_sheerka(__x_00__.a)""",
# """__x_00__ = __ret.body
# isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __ret.body.a == sheerka""",
# {"__ret"},
# "sheerka",
# set()
# ),
# (
# "recognize(__ret.body, greetings) and __ret.body.a == foo",
# """__x_00__ = __ret.body
# __x_01__ = __x_00__.a
# isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'""",
# """__x_00__ = __ret.body
# __x_01__ = __x_00__.a
# isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __ret.body.a == foo""",
# {"__ret"},
# "foo",
# set()
# ),
# (
# "recognize(__ret.body, hello sheerka)",
# """__x_00__ = __ret.body
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and is_sheerka(__x_00__.a)""",
# """__x_00__ = __ret.body
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == sheerka""",
# {"__ret"},
# "sheerka",
# set()
# ),
# (
# "recognize(__ret.body, hello 'my friend')",
# """__x_00__ = __ret.body
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == __o_00__""",
# """__x_00__ = __ret.body
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == 'my friend'""",
# {"__ret"},
# "my friend",
# {('__o_00__', 'my friend')}
# ),
# (
# "recognize(__ret.body, hello foo)",
# """__x_00__ = __ret.body
# __x_01__ = __x_00__.a
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'""",
# """__x_00__ = __ret.body
# __x_01__ = __x_00__.a
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == c:foo|1002:""",
# {"__ret"},
# "foo",
# {'__o_00__'}
# ),
# (
# "recognize(__ret.body, hello my best friend)",
# """__x_00__ = __ret.body
# __x_01__ = __x_00__.a
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'my best friend'""",
# """__x_00__ = __ret.body
# __x_01__ = __x_00__.a
# isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == c:my best friend|1003:""",
# {"__ret"},
# "my best friend",
# {'__o_00__'}
# ),
# (
# "recognize(self, greetings)",
# "isinstance(self, Concept) and self.name == 'greetings'",
# "isinstance(self, Concept) and self.name == 'greetings'",
# {"self"},
# None,
# set()
# )
# ])
# def test_python(self, expression, e_compiled, e_text, e_variables, greeting_var, e_objects):
# sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
# Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
# Concept("foo"),
# Concept("my best friend"),
# create_new=True
# ).unpack()
#
# conditions = self.validate_python_test(context,
# expression,
# e_compiled,
# e_text,
# e_variables,
# set(),
# e_objects)
#
# # check against SheerkaEvaluateRules
# variable_map = {
# "foo": foo,
# "my best friend": my_best_friend,
# "sheerka": Expando("sheerka", {})
# }
# variable = variable_map.get(greeting_var, greeting_var)
# to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
# expected_variable = next(iter(e_variables))
# objects = self.get_testing_objects(context, [(expected_variable, to_recognize)])
# self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationEvalQuestionConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing question using concepts
with no variable : girl is a human
with variable : self is a human
with long concept : the little boy is a human being
with long concept + variable : the little boy is a self
with long concept + variable : self is a human being
with a special symbol : self is a 'human'
with a special symbol : the little boy is a 'human'
with a function : func(self) is a human
"""
def test_rete(self):
pass # I don't know yet what to do
# @pytest.mark.parametrize("expression, expected_compiled, expected_variables", [
# (
# "girl is a human",
# "evaluate_question(__o_00__)",
# set(),
# ),
# (
# "self is a human",
# "evaluate_question(__o_00__)",
# {"self"},
# ),
# (
# "the little boy is a human being",
# "evaluate_question(__o_00__)",
# set(),
# ),
# (
# "the little boy is a self",
# "evaluate_question(__o_00__)",
# {"self"},
# ),
# (
# "self is a human being",
# "evaluate_question(__o_00__)",
# {"self"},
# ),
# (
# "self is a 'human'",
# "evaluate_question(__o_00__)",
# {"self"},
# ),
# (
# "the little boy is a 'human'",
# "evaluate_question(__o_00__)",
# set(),
# ),
# (
# "func(self) is a human",
# "evaluate_question(__o_00__)",
# set(),
# ),
# ])
# def test_python(self, expression, expected_compiled, expected_variables):
# sheerka, context, girl, human, little_boy, human_being, isa = self.init_test().with_concepts(
# Concept("girl"),
# Concept("human"),
# Concept("the little boy"),
# Concept("human being"),
# Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
# create_new=True
# ).unpack()
#
# parser = ExpressionParser()
# error_sink = ErrorSink()
# parser_input = ParserInput(expression)
# parser.reset_parser_input(parser_input, error_sink)
# parsed = parser.parse_input(context, parser_input, error_sink)
#
# visitor = ExprToConditionsVisitor(context)
# conditions = visitor.get_conditions(parsed)
#
# assert len(conditions) == 1
# assert isinstance(conditions[0], CompiledCondition)
#
# ast_ = ast.parse(expected_compiled, "<source>", 'exec' if "\n" in expected_compiled else 'eval')
# expected_python_node = PythonNode(expected_compiled, ast_, expression)
# assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
# assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
# assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
#
# assert "__o_00__" in conditions[0].objects
# assert conditions[0].variables == expected_variables
#
# assert len(conditions[0].concepts_to_reset) == 1
# assert sheerka.isinstance(next(iter(conditions[0].concepts_to_reset)), isa)
#
# # check against SheerkaEvaluateRules
# self.check_against_python(context, expression, conditions,
# self.get_testing_objects(context, expected_variables))
class TestSheerkaRuleManagerRulesCompilationEvalQuestionConceptWithNot(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing question using concepts mixed with others conditions
using not : not girl is a human
using not : not self is a human
"""
def test_rete(self):
pass
# @pytest.mark.parametrize(
# "expression, expected_compiled, expected_text, expected_variables", [
# (
# "not girl is a human",
# "not (evaluate_question(__o_00__))",
# "not (girl is a human)",
# set(),
# ),
# (
# "not self is a human",
# "not (evaluate_question(__o_00__))",
# "not (self is a human)",
# {"self"},
# ),
# ])
# def test_python(self, expression, expected_compiled, expected_text, expected_variables):
# sheerka, context, girl, human, little_boy, human_being, isa = self.init_test().with_concepts(
# Concept("girl"),
# Concept("human"),
# Concept("the little boy"),
# Concept("human being"),
# Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
# create_new=True
# ).unpack()
#
# conditions = self.validate_python_test(context,
# expression,
# expected_compiled,
# expected_text,
# expected_variables,
# set(),
# {"__o_00__"})
#
# # check against SheerkaEvaluateRules
# self.check_against_python(context,
# expression,
# conditions,
# self.get_testing_objects(context, expected_variables),
# False)
class TestSheerkaRuleManagerRulesCompilationEvalConceptMixedWithOther(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing question using concepts mixed with others conditions
using and with python : girl is a human being and isinstance(a_string, str)
using and with another concept : self is a human being and isinstance(self, girl)
starting with python : isinstance(x, str) and girl is a human being
starting with python : isinstance(self, girl) and self is a human being
multiple python + same variable : self is a human being and isinstance(self, girl) and isinstance(self, girl)
"""
def test_rete(self):
pass # I don't know yet what to do
# @pytest.mark.parametrize(
# "expression, expected_compiled, expected_variables, expected_objects", [
# (
# "girl is a human being and isinstance(a_string, str)",
# "evaluate_question(__o_00__) and isinstance(a_string, str)",
# {"a_string"},
# {"__o_00__"}
# ),
# (
# "self is a human being and isinstance(self, girl)",
# "evaluate_question(__o_00__) and isinstance(self, __o_01__)",
# {("self", "girl")},
# {"__o_00__", "__o_01__"}
# ),
# (
# "isinstance(a_string, str) and girl is a human being",
# "isinstance(a_string, str) and evaluate_question(__o_00__)",
# {"a_string"},
# {"__o_00__"}
# ),
# (
# "isinstance(self, girl) and self is a human being",
# "isinstance(self, __o_00__) and evaluate_question(__o_01__)",
# {("self", "girl")},
# {"__o_00__", "__o_01__"}
# ),
# (
# "self is a human being and isinstance(self, girl) and isinstance(self, girl)",
# "evaluate_question(__o_00__) and isinstance(self, __o_01__) and isinstance(self, __o_02__)",
# {("self", "girl")},
# {"__o_00__", "__o_01__", "__o_02__"}
# ),
# ])
# def test_python(self, expression, expected_compiled, expected_variables, expected_objects):
# sheerka, context, girl, human_being, isa = self.init_test().with_concepts(
# Concept("girl"),
# Concept("human being"),
# Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
# create_new=True
# ).unpack()
#
# conditions = self.validate_python_test(context,
# expression,
# expected_compiled,
# expression,
# expected_variables,
# set(),
# expected_objects)
#
# # check against SheerkaEvaluateRules
# variables_mapping = {
# "girl": girl,
# "human being": human_being
# }
# testing_objects = self.get_testing_objects(context, expected_variables, variables_mapping)
# self.check_against_python(context,
# expression,
# conditions,
# testing_objects,
# True)
class TestSheerkaRuleManagerRulesCompilationEvalNonQuestionConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing complex concepts composition
with BNF : twenty two
additions : twenty two + one
additions : twenty two + twenty one
additions : twenty two plus one
additions : twenty two plus twenty one
with function: func_identity(twenty two)
with function: func_identity(twenty two + one)
with function: func_identity(twenty two + twenty one)
with function: func_identity(twenty two plus one)
with function: func_identity(twenty two plus twenty one)
with special char : 'one' plus 'two'
with special char : twenty two plus 2
"""
def test_rete(self):
pass # I don't know yet what to do
# @pytest.mark.parametrize("expression, e_compiled, e_text, e_objects, e_result", [
# (
# "twenty two",
# "__o_00__",
# "twenty two",
# {"__o_00__"},
# 22
# ),
# (
# "twenty two + one",
# "__o_00__",
# "twenty two + one",
# {("__o_00__", 23)},
# 23
# ),
# (
# "twenty two + twenty one",
# "__o_00__",
# "twenty two + twenty one",
# {("__o_00__", 43)},
# 43
# ),
# (
# "twenty two plus one",
# "__o_00__",
# "twenty two plus one",
# {"__o_00__"},
# 23
# ),
# (
# "twenty two plus twenty one",
# "__o_00__",
# "twenty two plus twenty one",
# {"__o_00__"},
# 43
# ),
# (
# "func_identity(twenty two)",
# "func_identity(__o_00__)",
# "func_identity(twenty two)",
# {"__o_00__"},
# 22
# ),
# (
# "func_identity(twenty two + one)",
# "func_identity(__o_00__)",
# "func_identity(twenty two + one)",
# {("__o_00__", 23)},
# 23
# ),
# (
# "func_identity(twenty two + twenty one)",
# "func_identity(__o_00__)",
# "func_identity(twenty two + twenty one)",
# {("__o_00__", 43)},
# 43
# ),
# (
# "func_identity(twenty two plus one)",
# "func_identity(__o_00__)",
# "func_identity(twenty two plus one)",
# {"__o_00__"},
# 23
# ),
# (
# "func_identity(twenty two plus twenty one)",
# "func_identity(__o_00__)",
# "func_identity(twenty two plus twenty one)",
# {"__o_00__"},
# 43
# ),
# (
# "'one' plus 'two'",
# "__o_00__",
# "'one' plus 'two'",
# {"__o_00__"},
# 'onetwo'
# ),
# (
# "twenty two plus 2",
# "__o_00__",
# "twenty two plus 2",
# {"__o_00__"},
# 24
# ),
# ])
# def test_python(self, expression, e_compiled, e_text, e_objects, e_result):
# sheerka, context, one, two, twenties, plus = self.init_test().with_concepts(
# Concept("one", body="1"),
# Concept("two", body="2"),
# Concept("twenties", definition="'twenty' (one|two)=n", body='20 + n').def_var("n"),
# Concept("a plus b", body="a + b").def_var("a").def_var("b"),
# create_new=True
# ).unpack()
#
# conditions = self.validate_python_test(context,
# expression,
# e_compiled,
# e_text,
# set(),
# set(),
# e_objects)
#
# # check against SheerkaEvaluateRules
# namespace = {"func_identity": self.func_identity}
# res = self.evaluate_condition(context, expression, conditions[0], namespace)
# assert res.status
# assert sheerka.objvalue(res) == e_result
class TestSheerkaRuleManagerRulesCompilationMultipleSameConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Test when a concept returns multiple results
The compilation should fail : No need to execute a condition if we are not sure of the meaning
self is a bar
"""
def test_rete(self):
sheerka, context, bar, isa_1, isa_2 = self.init_test().with_concepts(
Concept("bar"),
Concept("x is a y").def_var("x").def_var("y"),
Concept("u is a v").def_var("u").def_var("v"),
create_new=True
).unpack()
with pytest.raises(FailedToCompileError):
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput("self is a bar")
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
visitor.get_conditions(parsed)
class TestSheerkaRuleManagerRulesCompilationNot(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing not
not __ret.status == True
not recognize(__ret.body, hello sheerka)
not a cat is a pet and not bird is an animal # where x is a y is a concept
not a cat is a pet and not x > 5 # concept mixed with python
"""
pass