87cab44fb8
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()
516 lines
24 KiB
Python
516 lines
24 KiB
Python
import ast
|
|
from dataclasses import dataclass
|
|
|
|
import pytest
|
|
|
|
from core.builtin_concepts_ids import BuiltinConcepts
|
|
from core.concept import Concept
|
|
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules
|
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
|
from core.sheerka.services.SheerkaRuleManager import CompiledCondition
|
|
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 tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|
from tests.core.test_SheerkaRuleManager import PYTHON_EVALUATOR_NAME
|
|
|
|
|
|
@dataclass
|
|
class Obj:
|
|
value: object
|
|
|
|
def __eq__(self, other):
|
|
return isinstance(other, Obj) and self.value == other.value
|
|
|
|
def __hash__(self):
|
|
return hash(self.value)
|
|
|
|
|
|
cmap = {
|
|
"one": Concept("one", body="1"),
|
|
"two": Concept("two", body="2"),
|
|
"three": Concept("three", body="3"),
|
|
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit", body="20 + unit").def_var("unit"),
|
|
"equals": Concept("x equals y", pre="is_question()", body="x == y").def_var("x").def_var("y"),
|
|
"isa1": Concept("x is a y", pre="is_question()", body="isa(x, y)").def_var("x").def_var("y"),
|
|
"isa2": Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
|
"isan1": Concept("x is an y", pre="is_question()", body="isa(x , y)").def_var("x").def_var("y"),
|
|
"isan2": Concept("x is an y", body="set_isa(x, y)").def_var("x").def_var("y"),
|
|
"foo": Concept("foo"),
|
|
"bar": Concept("bar"),
|
|
"baz": Concept("baz"),
|
|
}
|
|
|
|
|
|
class TestExprToConditionsVisitor(TestUsingMemoryBasedSheerka):
|
|
shared_ontology = None
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
instance = cls()
|
|
init_test_helper = instance.init_test(cache_only=False, ontology="#TestExprToConditionsVisitor#")
|
|
sheerka, context, *updated = init_test_helper.with_concepts(*cmap.values(), create_new=True).unpack()
|
|
for i, concept_name in enumerate(cmap):
|
|
cmap[concept_name] = updated[i]
|
|
|
|
global_context = instance.get_context(sheerka, global_truth=True)
|
|
sheerka.set_isa(global_context, cmap["baz"], cmap["foo"])
|
|
|
|
cls.shared_ontology = sheerka.get_ontology(context)
|
|
sheerka.pop_ontology(context)
|
|
|
|
def initialize_test(self, concepts_map=None):
|
|
if concepts_map is None:
|
|
sheerka, context = self.init_test().unpack()
|
|
sheerka.add_ontology(context, self.shared_ontology)
|
|
else:
|
|
sheerka, context, *updated = super().init_test().with_concepts(*concepts_map.values(),
|
|
create_new=True).unpack()
|
|
for i, concept_name in enumerate(concepts_map):
|
|
concepts_map[concept_name] = updated[i]
|
|
|
|
return sheerka, context
|
|
|
|
@staticmethod
|
|
def evaluate_conditions(context, conditions, namespace):
|
|
with context.push(BuiltinConcepts.EXEC_CODE, None) 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.deactivate_push()
|
|
|
|
evaluation_service = sub_context.sheerka.services[SheerkaEvaluateRules.NAME]
|
|
return evaluation_service.evaluate_conditions(sub_context, conditions, namespace)
|
|
|
|
@staticmethod
|
|
def get_conditions_from_expression(context, expression, parser=None):
|
|
parser = parser or 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)
|
|
|
|
assert not error_sink.has_error
|
|
known_variables = parser.known_variables if hasattr(parser, "known_variables") else None
|
|
visitor = ExprToConditionsVisitor(context, known_variables=known_variables)
|
|
conditions = visitor.get_conditions(parsed)
|
|
return conditions
|
|
|
|
@staticmethod
|
|
def validate_condition(context, expression, condition, e_code, e_objects, e_variables, e_not_variables):
|
|
sheerka = context.sheerka
|
|
|
|
# check what was compiled
|
|
if e_code is None:
|
|
# manage cases where we only check for variable existence
|
|
assert condition.evaluator_type is None
|
|
assert condition.return_value is None
|
|
else:
|
|
ast_ = ast.parse(e_code, "<source>", 'exec' if "\n" in e_code else 'eval')
|
|
expected_python_node = PythonNode(e_code, ast_, expression)
|
|
assert condition.evaluator_type == PYTHON_EVALUATOR_NAME
|
|
assert sheerka.isinstance(condition.return_value, BuiltinConcepts.RETURN_VALUE)
|
|
assert sheerka.objvalue(condition.return_value) == expected_python_node
|
|
|
|
# check the objects
|
|
if e_objects is not None:
|
|
resolved_objects = {k: v.id for k, v in condition.objects.items()}
|
|
resolved_expected_objects = {k: cmap[v].id for k, v in e_objects.items()}
|
|
assert resolved_objects == resolved_expected_objects
|
|
|
|
# check that variables detected
|
|
if e_variables is not None:
|
|
assert condition.variables == e_variables
|
|
|
|
if e_not_variables is not None:
|
|
assert condition.not_variables == e_not_variables
|
|
|
|
def run_test_cases(self, context, conditions, test_suite):
|
|
sheerka = context.sheerka
|
|
|
|
for test_data in test_suite:
|
|
namespace, expected_value = test_data
|
|
for k, v in namespace.items():
|
|
if isinstance(v, str):
|
|
try:
|
|
namespace[k] = self.evaluate_from_source(context, v)
|
|
except:
|
|
pass
|
|
|
|
res = self.evaluate_conditions(context, conditions, namespace)
|
|
value = sheerka.objvalue(res[0].body) if res else False
|
|
assert value == expected_value
|
|
|
|
@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)
|
|
|
|
@pytest.mark.parametrize("expression, e_code, e_variables, e_not_variables, test_suite", [
|
|
("var", None, {"var"}, set(), [({"var": "value"}, True), ({}, False)]),
|
|
("True", "True", set(), set(), []),
|
|
("var.value", None, {"var.value"}, set(), []),
|
|
("not var", None, set(), {"var"}, [({"var": "value"}, False), ({}, True)]),
|
|
("not not var", None, {"var"}, set(), []),
|
|
("var and var2 and not var3", None, {"var", "var2"}, {"var3"}, []),
|
|
("var and var.value == 3", "var.value == 3", {"var"}, set(), [({"var": Obj(3)}, True)]),
|
|
("not v2 and v1.value == 3", "v1.value == 3", {"v1"}, {"v2"}, [({"v1": Obj(3)}, True), ({"v2": 0}, False)]),
|
|
("func(var)", "func(var)", {"var"}, set(), []),
|
|
("var in []", "var in []", {"var"}, set(), []),
|
|
("a + b", "a + b", {"a", "b"}, set(), []),
|
|
("foo x", "__o_00__", set(), set(), []), # foo is not a variable
|
|
("foo y", "evaluate_question(__o_00__, x=y)", {"y"}, set(), []), # foo is not a variable
|
|
("bar y", "call_concept(__o_00__, x=y)", {"y"}, set(), []), # bar is not a variable
|
|
])
|
|
def test_i_can_parse_and_manage_exists(self, expression, e_code, e_variables, e_not_variables, test_suite):
|
|
sheerka, context, foo, bar = self.init_test().with_concepts(
|
|
Concept("foo x", pre="is_question()").def_var("x"),
|
|
Concept("bar x").def_var("x"),
|
|
).unpack()
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert isinstance(conditions[0], CompiledCondition)
|
|
condition = conditions[0]
|
|
|
|
self.validate_condition(context, expression, condition, e_code, None, e_variables, e_not_variables)
|
|
self.run_test_cases(context, conditions, test_suite)
|
|
|
|
@pytest.mark.parametrize("expression, e_code, e_objects, e_variables, test_suite", [
|
|
# Concept
|
|
("1 equals 1", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, True)]),
|
|
("1 equals 2", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, False)]),
|
|
("one equals one", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, True)]),
|
|
("one equals two", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, False)]),
|
|
("one equals twenty one", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, False)]),
|
|
("self equals 1", "evaluate_question(__o_00__, x=self)", {"__o_00__": "equals"}, {"self"}, [
|
|
({"self": 1}, True),
|
|
({"self": 2}, False)]),
|
|
("x equals 1", "evaluate_question(__o_00__, x=x)", {"__o_00__": "equals"}, {"x"}, [
|
|
({"x": 1}, True),
|
|
({"x": 2}, False)]),
|
|
("one equals self", "evaluate_question(__o_00__, y=self)", {"__o_00__": "equals"}, {"self"}, [
|
|
({"self": "one"}, True),
|
|
({"self": "two"}, False)]),
|
|
("self equals twenty two", "evaluate_question(__o_00__, x=self)", {"__o_00__": "equals"}, {"self"}, [
|
|
({"self": "twenty two"}, True),
|
|
({"self": "two"}, False)]
|
|
),
|
|
("x equals 1 and y equals 2",
|
|
"evaluate_question(__o_00__, x=x) and evaluate_question(__o_01__, x=y)",
|
|
{"__o_00__": "equals", "__o_01__": "equals"},
|
|
{"x", "y"},
|
|
[({"x": 1, "y": 2}, True), ({"x": "0", "y": "0"}, False)]
|
|
),
|
|
("x equals y", "__o_00__", {"__o_00__": "equals"}, set(), []),
|
|
("func(self) equals twenty one",
|
|
"evaluate_question(__o_00__, x=func(self))",
|
|
{"__o_00__": "equals"},
|
|
{"self"},
|
|
[({"self": "twenty one", "func": lambda x: x}, True)]),
|
|
("func(self) equals twenty one + 1",
|
|
"evaluate_question(__o_01__, x=func(self), y=__o_00__ + 1)",
|
|
{"__o_01__": "equals", "__o_00__": "twenties"},
|
|
{"self"},
|
|
[({"self": "22", "func": lambda x: x}, True)]),
|
|
|
|
# equality
|
|
("a == 10", "a == 10", {}, {"a"}, [({"a": 10}, True), ({"a": 20}, False), ({}, False)]),
|
|
("__ret.status == True", "__ret.status == True", {}, {"__ret"}, []),
|
|
("self == sheerka", "is_sheerka(self)", {}, {"self"}, [
|
|
({"self": "sheerka"}, True),
|
|
({"self": "other"}, False),
|
|
]),
|
|
("self == BuiltinConcepts.TO_DICT", "self == BuiltinConcepts.TO_DICT", {}, {"self"}, [
|
|
({"self": "BuiltinConcepts.TO_DICT"}, True),
|
|
({"self": "other"}, False),
|
|
]),
|
|
|
|
# other Comparisons
|
|
("a + self > 10", "a + self > 10", {}, {"a", "self"}, [
|
|
({"a": 10, "self": 1}, True),
|
|
({"a": 10, "self": 0}, False),
|
|
]),
|
|
("10 < one + self", "10 < __o_00__ + self", {"__o_00__": "one"}, {"self"}, [
|
|
({"self": 10}, True),
|
|
({"self": 1}, False),
|
|
]),
|
|
("23 < twenty one + self", "23 < __o_00__ + self", {"__o_00__": "twenties"}, {"self"}, [
|
|
({"self": 10}, True),
|
|
({"self": 1}, False),
|
|
]),
|
|
("a equals b and c equals d",
|
|
"evaluate_question(__o_00__, x=a, y=b) and evaluate_question(__o_01__, x=c, y=d)",
|
|
{"__o_00__": "equals", "__o_01__": "equals"},
|
|
{"a", "b", "c", "d"},
|
|
[]),
|
|
|
|
# simple expressions
|
|
("True", "True", {}, set(), [({}, True)]),
|
|
("False", "False", {}, set(), [({}, False)]),
|
|
("10 + 5", "10 + 5", {}, set(), [({}, 15)]),
|
|
("a + self", "a + self", {}, {"a", "self"}, [({"a": 10, "self": 5}, 15)]),
|
|
("a + twenty one", "a + __o_00__", {"__o_00__": "twenties"}, {"a"}, [({"a": 10}, 31)]),
|
|
|
|
# functions
|
|
("isinstance('hello', str)", "isinstance('hello', str)", {}, set(), [({}, True)]),
|
|
("isinstance(a, str)", "isinstance(a, str)", {}, {"a"}, [({"a": "an_str"}, True), ({"a": 1}, False)]),
|
|
("f(BuiltinConcepts.TO_DICT)", "f(BuiltinConcepts.TO_DICT)", {}, set(), [({"f": lambda x: x}, "__TO_DICT")])
|
|
|
|
])
|
|
def test_i_can_parse(self, expression, e_code, e_objects, e_variables, test_suite):
|
|
sheerka, context = self.initialize_test()
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert isinstance(conditions[0], CompiledCondition)
|
|
condition = conditions[0]
|
|
|
|
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
|
self.run_test_cases(context, conditions, test_suite)
|
|
|
|
def test_i_can_force_variable(self):
|
|
sheerka, context = self.initialize_test()
|
|
parser = ExpressionParser(known_variables={"one"})
|
|
conditions = self.get_conditions_from_expression(context, "one < two", parser)
|
|
python_source = conditions[0].return_value.body.body.source
|
|
assert python_source == "one < __o_00__"
|
|
|
|
resolved_objects = {k: v.id for k, v in conditions[0].objects.items()}
|
|
resolved_expected_objects = {k: cmap[v].id for k, v in {"__o_00__": "two"}.items()}
|
|
assert resolved_objects == resolved_expected_objects
|
|
|
|
def test_i_can_manage_possible_variable_indication(self):
|
|
my_map = {
|
|
"isa": Concept("x is an int").def_var("x") # no pre condition
|
|
}
|
|
sheerka, context = self.initialize_test(my_map)
|
|
parser = ExpressionParser(known_variables={"x"})
|
|
conditions = self.get_conditions_from_expression(context, "x is an int", parser)
|
|
|
|
python_source = conditions[0].return_value.body.body.source
|
|
assert python_source == "call_concept(__o_00__, x=x)"
|
|
|
|
resolved_objects = {k: v.id for k, v in conditions[0].objects.items()}
|
|
resolved_expected_objects = {k: my_map[v].id for k, v in {"__o_00__": "isa"}.items()}
|
|
assert resolved_objects == resolved_expected_objects
|
|
|
|
def test_i_can_parse_when_variables_are_missing(self):
|
|
sheerka, context = self.initialize_test()
|
|
expression = "x equals 1"
|
|
e_code = "evaluate_question(__o_00__, x=x)"
|
|
e_objects = {"__o_00__": "equals"}
|
|
e_variables = {"x"}
|
|
test_suite = [({}, False), ({"y": 1}, False)]
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert isinstance(conditions[0], CompiledCondition)
|
|
condition = conditions[0]
|
|
|
|
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
|
self.run_test_cases(context, conditions, test_suite)
|
|
|
|
def test_question_concept_is_chosen_other_non_question_concept(self):
|
|
sheerka, context = self.initialize_test()
|
|
expression = "a is an b"
|
|
e_code = "evaluate_question(__o_00__, x=a, y=b)"
|
|
e_objects = {"__o_00__": "isan1"}
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert isinstance(conditions[0], CompiledCondition)
|
|
condition = conditions[0]
|
|
|
|
self.validate_condition(context, expression, condition, e_code, e_objects, None, None)
|
|
|
|
def test_i_can_manage_when_multiple_concepts(self):
|
|
sheerka, context = self.initialize_test()
|
|
expression = "a is a b"
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 2
|
|
|
|
condition = conditions[0]
|
|
assert isinstance(condition, CompiledCondition)
|
|
e_code = "evaluate_question(__o_00__, x=a, y=b)"
|
|
e_objects = {"__o_00__": "isa1"}
|
|
e_variables = {"a", "b"}
|
|
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
|
|
|
condition = conditions[1]
|
|
assert isinstance(condition, CompiledCondition)
|
|
e_code = "evaluate_question(__o_01__, x=a, y=b)"
|
|
e_objects = {"__o_01__": "isa2"}
|
|
e_variables = {"a", "b"}
|
|
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
|
|
|
# testing
|
|
|
|
namespace = {"a": sheerka.new("foo"), "b": sheerka.new("bar")}
|
|
res = self.evaluate_conditions(context, conditions, namespace)
|
|
assert len(res) == 2
|
|
assert isinstance(res[0].value, bool) and not res[0].value
|
|
assert isinstance(res[1].value, bool) and not res[1].value
|
|
|
|
namespace = {"a": sheerka.new("foo"), "b": sheerka.new("foo")}
|
|
res = self.evaluate_conditions(context, conditions, namespace)
|
|
assert len(res) == 1
|
|
assert isinstance(res[0].value, bool) and res[0].value
|
|
|
|
namespace = {"a": sheerka.new("baz"), "b": sheerka.new("foo")}
|
|
res = self.evaluate_conditions(context, conditions, namespace)
|
|
assert len(res) == 1
|
|
assert isinstance(res[0].value, bool) and res[0].value
|
|
|
|
def test_i_can_manage_or_expressions(self):
|
|
sheerka, context = self.initialize_test()
|
|
expression = "isinstance(self, foo) or self is a bar"
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 3
|
|
|
|
condition = conditions[0]
|
|
assert isinstance(condition, CompiledCondition)
|
|
e_code = "isinstance(self, __o_00__)"
|
|
e_objects = {"__o_00__": "foo"}
|
|
e_variables = {"self"}
|
|
self.validate_condition(context, "isinstance(self, foo)", condition, e_code, e_objects, e_variables, None)
|
|
|
|
condition = conditions[1]
|
|
assert isinstance(condition, CompiledCondition)
|
|
e_code = "evaluate_question(__o_01__, x=self)"
|
|
e_objects = {"__o_01__": "isa1"}
|
|
e_variables = {"self"}
|
|
self.validate_condition(context, "self is a bar", condition, e_code, e_objects, e_variables, None)
|
|
|
|
condition = conditions[2]
|
|
assert isinstance(condition, CompiledCondition)
|
|
e_code = "evaluate_question(__o_02__, x=self)"
|
|
e_objects = {"__o_02__": "isa2"}
|
|
e_variables = {"self"}
|
|
self.validate_condition(context, "self is a bar", condition, e_code, e_objects, e_variables, None)
|
|
|
|
def test_i_can_manage_multiple_concepts_melt_with_and_expressions(self):
|
|
sheerka, context = self.initialize_test()
|
|
expression = "isinstance(self, foo) and self is a bar"
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 2
|
|
|
|
condition = conditions[0]
|
|
assert isinstance(condition, CompiledCondition)
|
|
e_code = "isinstance(self, __o_00__) and evaluate_question(__o_01__, x=self)"
|
|
e_objects = {"__o_00__": "foo", "__o_01__": "isa1"}
|
|
e_variables = {"self"}
|
|
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
|
|
|
condition = conditions[1]
|
|
assert isinstance(condition, CompiledCondition)
|
|
e_code = "isinstance(self, __o_00__) and evaluate_question(__o_02__, x=self)"
|
|
e_objects = {"__o_00__": "foo", "__o_02__": "isa2"}
|
|
e_variables = {"self"}
|
|
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("self is a 'foo'", {"x is a y"}),
|
|
("set self is a 'foo'", set()),
|
|
])
|
|
def test_i_can_get_concept_to_reset(self, expression, expected):
|
|
"""
|
|
When compiled conditions, sometimes there are concepts to reset between two usages
|
|
:param expression:
|
|
:param expected:
|
|
:return:
|
|
"""
|
|
concepts_map = {
|
|
"isa": Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
|
|
"set_isa": Concept("set x is a y").def_var("x").def_var("y"),
|
|
}
|
|
sheerka, context = self.initialize_test(concepts_map)
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert {c.name for c in conditions[0].concepts_to_reset} == expected
|
|
|
|
def test_i_can_reset_concepts_when_multiple_levels(self):
|
|
"""
|
|
When compiled conditions, sometimes there are concepts to reset between two usages
|
|
:return:
|
|
"""
|
|
sheerka, context, is_instance, is_int, is_integer = self.init_concepts(
|
|
Concept("x is an instance of y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
|
Concept("x is a int", pre="is_question()", body="x is an instance of int").def_var("x"),
|
|
Concept("x is an integer", pre="is_question()", body="x is a int").def_var("x"),
|
|
)
|
|
|
|
expression = "self is an integer"
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert {c.name for c in conditions[0].concepts_to_reset} == {"x is an instance of y",
|
|
"x is a int",
|
|
"x is an integer"}
|
|
|
|
# So I can evaluate multiple times
|
|
res = self.evaluate_condition(context, expression, conditions[0], {'self': 10})
|
|
assert res.status
|
|
assert sheerka.objvalue(res.body)
|
|
|
|
res = self.evaluate_condition(context, expression, conditions[0], {'self': "string"})
|
|
assert res.status
|
|
assert not sheerka.objvalue(res.body)
|
|
|
|
def test_i_can_reset_concepts_when_multiple_levels_and_concept_node(self):
|
|
"""
|
|
When compiled conditions, sometimes there are concepts to reset between two usages
|
|
:return:
|
|
"""
|
|
# in this example, x + 2 is an int won't be parsed as an ExactNodeConcept, but as a ConceptNode
|
|
sheerka, context, is_int, is_integer = self.init_concepts(
|
|
Concept("x is a int", pre="is_question()", body="isinstance(x, int)").def_var("x"),
|
|
Concept("x is an integer", pre="is_question()", body="x + 2 is a int").def_var("x"),
|
|
create_new=True
|
|
)
|
|
|
|
expression = "self is an integer"
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert set(c.name for c in conditions[0].concepts_to_reset) == {"x is a int",
|
|
"x is an integer"}
|
|
|
|
# So I can evaluate multiple times
|
|
res = self.evaluate_condition(context, expression, conditions[0], {'self': 10})
|
|
assert res.status
|
|
assert sheerka.objvalue(res.body)
|
|
|
|
res = self.evaluate_condition(context, expression, conditions[0], {'self': "string"})
|
|
assert not res.status
|
|
|
|
def test_long_name_concepts_are_not_considered_as_variables(self):
|
|
sheerka, context, one, number = self.init_concepts(
|
|
"one",
|
|
"all numbers",
|
|
)
|
|
sheerka.set_isa(context, one, number)
|
|
|
|
expression = "all numbers < 5"
|
|
conditions = self.get_conditions_from_expression(context, expression)
|
|
|
|
assert len(conditions) == 1
|
|
assert conditions[0].return_value.body.body.source == '__o_00__ < 5'
|