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()
This commit is contained in:
2021-10-28 14:04:41 +02:00
parent 48ab72fd9c
commit 87cab44fb8
56 changed files with 1391 additions and 1286 deletions
+463
View File
@@ -0,0 +1,463 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, UnknownConcept
from core.builtin_concepts_ids import BuiltinConcepts
from core.concept import Concept
from core.sheerka.services.SheerkaConceptManager import ValueNotFound
from core.sheerka.services.SheerkaErrorManager import LAST_UNKNOWN_CONCEPTS, SheerkaErrorManager
from core.sheerka.services.SheerkaExecute import ParserInput
from core.sheerka.services.SheerkaRuleManager import NoConditionFound
from evaluators.PythonEvaluator import PythonEvaluator
from parsers.BaseParser import ParsingError, UnexpectedEofParsingError
from parsers.BnfNodeParser import BnfNodeParser
from parsers.ExactConceptParser import ExactConceptParser
from parsers.PythonParser import PythonErrorNode, PythonParser
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
def inner_errors(lst):
return [e.error for e in lst]
class TestSheerkaErrorManger(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("obj, expected", [
("a string", []),
(True, []),
(False, []),
(Concept("foo"), []),
(Concept("foo", body=False).auto_init(), []),
(UnknownConcept(), [UnknownConcept()]),
(Concept("foo", body=UnknownConcept()).auto_init(), [UnknownConcept()]),
(PythonErrorNode("msg", None), [PythonErrorNode("msg", None)])
])
def test_i_can_get_error_for_simple_objects(self, obj, expected):
sheerka, context = self.init_test().unpack()
assert sheerka.get_obj_errors(context, obj) == expected
def test_i_can_get_error_when_builtin_concept_in_error(self):
sheerka, context = self.init_test().unpack()
obj = sheerka.new(BuiltinConcepts.ONTOLOGY_ALREADY_DEFINED)
assert sheerka.get_obj_errors(context, obj) == [obj]
def test_i_can_get_error_when_return_value(self):
sheerka, context = self.init_test().unpack()
error = sheerka.err("an error")
ret_val = ReturnValueConcept("Test", False, sheerka.err("an error"))
assert sheerka.get_obj_errors(context, ret_val) == [error]
def test_i_can_get_inner_error(self):
sheerka, context = self.init_test().unpack()
error = sheerka.err("an error")
ret_val = ReturnValueConcept("Test", False, sheerka.err("an error"))
assert sheerka.get_obj_errors(context, ret_val) == [error]
def test_i_can_get_error_when_embedded_errors(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
not_an_error = sheerka.new(BuiltinConcepts.AUTO_EVAL)
error = sheerka.err([concept_eval_error, unknown_concept, not_an_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val)
assert errors_found == [error, concept_eval_error, unknown_concept]
def test_i_can_get_embedded_errors_from_get_error_method(self):
sheerka, context = self.init_test().unpack()
embedded_error = NotImplementedError()
error = sheerka.new(BuiltinConcepts.NOT_FOR_ME, body="some text", reason=embedded_error)
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val)
assert errors_found == [error, embedded_error]
def test_i_can_get_error_from_list(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
not_an_error = sheerka.new(BuiltinConcepts.AUTO_EVAL)
error = sheerka.err([concept_eval_error, unknown_concept, not_an_error])
ret_val_1 = ReturnValueConcept("Test", False, error)
python_error = PythonErrorNode("msg", Exception())
value_not_found = ValueNotFound("item", "value")
multiple_error = sheerka.new(BuiltinConcepts.MULTIPLE_ERRORS, body=[python_error, value_not_found])
ret_val_2 = ReturnValueConcept("Test", False, multiple_error)
errors_found = sheerka.get_obj_errors(context, [ret_val_1, ret_val_2])
assert errors_found == [error, concept_eval_error, unknown_concept,
multiple_error, python_error, value_not_found]
def test_i_can_filter_error_by_concept_key(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
python_error = PythonErrorNode("msg", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val, __type=BuiltinConcepts.CONCEPT_EVAL_ERROR)
assert errors_found == [concept_eval_error]
def test_i_can_filter_error_by_class_name(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
python_error = PythonErrorNode("msg", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val, __type="PythonErrorNode")
assert errors_found == [python_error]
def test_i_can_filter_error_by_concept_attribute(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, concept_ref="a_concept_ref")
python_error = PythonErrorNode("msg", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val, concept_ref="a_concept_ref")
assert errors_found == [unknown_concept]
def test_i_can_filter_error_by_class_attribute(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, concept_ref="a_concept_ref")
python_error = PythonErrorNode("error source", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val, source="error source")
assert errors_found == [python_error]
def test_i_can_filter_error_by_exception_name_and_type(self):
sheerka, context = self.init_test().unpack()
from evaluators.PythonEvaluator import PythonEvalError
name_error = NameError("foo")
python_eval_error = PythonEvalError(name_error, "foo", None, None)
error = sheerka.err([python_eval_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val, __type="NameError")
assert errors_found == [name_error]
errors_found = sheerka.get_obj_errors(context, ret_val, __type=NameError)
assert errors_found == [name_error]
def test_i_can_filter_error_on_multiple_criteria(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, concept_ref="a_concept_ref")
value_not_found = ValueNotFound("an_item", "a value")
error = sheerka.err([concept_eval_error, unknown_concept, value_not_found])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_obj_errors(context, ret_val, __type="ValueNotFound", item="an_item", value="a value")
assert errors_found == [value_not_found]
def test_i_cannot_get_error_when_return_value_s_status_is_true(self):
sheerka, context = self.init_test().unpack()
ret_val = ReturnValueConcept("Test", True, sheerka.err("an error"))
assert sheerka.get_obj_errors(context, ret_val) == []
def test_i_can_get_error_items(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
simple_error = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body=Concept("foo"))
ret1 = sheerka.ret("Test1", False, simple_error)
sub_error_is_an_exception = sheerka.new(BuiltinConcepts.NOT_FOR_ME, reason=NotImplementedError())
ret2 = sheerka.ret("Test2", False, sub_error_is_an_exception)
inner_error = sheerka.err([ParsingError(), UnexpectedEofParsingError("EOF", 0)])
sub_error_is_an_error = sheerka.new(BuiltinConcepts.NOT_FOR_ME, reason=inner_error)
ret3 = sheerka.ret("Test3", False, sub_error_is_an_error)
parsing_error = sheerka.new(BuiltinConcepts.PARSER_RESULT,
parser=PythonParser(),
source="not a valid source",
body="Not totally valid parsing")
ret4 = sheerka.ret("Test4", False, parsing_error)
multiple_level_errors1 = sheerka.err("Err1")
multiple_level_errors2 = sheerka.err(multiple_level_errors1)
multiple_level_errors3 = sheerka.err(multiple_level_errors2)
ret5 = sheerka.ret("Test5", False, multiple_level_errors3)
filtered = sheerka.new(BuiltinConcepts.FILTERED, reason="not really given")
ret6 = sheerka.ret("Test6", False, filtered)
ret7 = sheerka.ret("Test5", True, None)
error_items = list(service.get_errors_items([ret1, ret2, ret3, ret4, ret5, ret6, ret7]))
assert len(error_items) == 6
# ret1 : simple_error
assert len(error_items[0].children) == 0
# ret2 : sub_error_is_an_exception
assert len(error_items[1].children) == 1
assert len(error_items[1].children[0].children) == 0
# ret3 : inner_error
assert len(error_items[2].children) == 1
assert len(error_items[2].children[0].children) == 2
assert len(error_items[2].children[0].children[0].children) == 0
assert len(error_items[2].children[0].children[1].children) == 0
# ret4 : parsing_error
assert len(error_items[3].children) == 0
# ret5 : multiple_level_errors
assert len(error_items[4].children) == 1
assert len(error_items[4].children[0].children) == 1
assert len(error_items[4].children[0].children[0].children) == 0
# ret6 Filtered without a real reason
assert len(error_items[5].children) == 0
def test_i_can_get_all_error_items(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
simple_error = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body=Concept("foo"))
ret1 = sheerka.ret("Test1", False, simple_error)
inner_error = sheerka.err([ParsingError(), UnexpectedEofParsingError("EOF", 0)])
sub_error_is_an_error = sheerka.new(BuiltinConcepts.NOT_FOR_ME, reason=inner_error)
ret2 = sheerka.ret("Test3", False, sub_error_is_an_error)
multiple_level_errors1 = sheerka.err("Err1")
multiple_level_errors2 = sheerka.err(multiple_level_errors1)
multiple_level_errors3 = sheerka.err(multiple_level_errors2)
ret3 = sheerka.ret("Test5", False, multiple_level_errors3)
all_error_items = list(service.get_all_error_items([ret1, ret2, ret3]))
assert len(all_error_items) == 8
def test_i_can_keep_the_correct_error_source(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
simple_error = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body=Concept("foo"))
ret1 = sheerka.ret("Source1", False, simple_error)
sub_error_is_an_exception = sheerka.new(BuiltinConcepts.NOT_FOR_ME, reason=NotImplementedError())
ret2 = sheerka.ret("Source2", False, sub_error_is_an_exception)
multiple_errors = sheerka.new(BuiltinConcepts.MULTIPLE_ERRORS, body=[ret1, ret2])
ret3 = sheerka.ret("Source3", False, multiple_errors)
error_items = list(service.get_errors_items([ret3]))
assert len(error_items) == 1
assert error_items[0].source == "Source3"
assert error_items[0].children[0].source == "Source1"
assert error_items[0].children[1].source == "Source2"
def test_i_can_get_filtered_error_explanation(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
simple_error = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body=Concept("foo"))
ret1 = sheerka.ret("Test1", False, simple_error)
sub_error_is_an_exception = sheerka.new(BuiltinConcepts.NOT_FOR_ME, reason=NotImplementedError())
ret2 = sheerka.ret("Test2", False, sub_error_is_an_exception)
context.add_values(return_values=[ret1, ret2])
service.on_user_input_evaluated(context)
res = sheerka.get_last_errors(context)
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
assert len(res.body) == 3
res = sheerka.get_last_errors(context, __type=BuiltinConcepts.UNKNOWN_CONCEPT)
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
assert len(res.body) == 1
def test_i_cannot_recognize_error_when_no_error(self):
sheerka, context = self.init_test().unpack()
res = sheerka.recognize_error(context, "Some error")
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
def test_i_can_recognized_error_when_error_is_a_builtin_concept(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
simple_error = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body=Concept("foo"))
ret1 = sheerka.ret("Test1", False, simple_error)
context.add_values(return_values=[ret1])
service.on_user_input_evaluated(context)
assert sheerka.recognize_error(context, __type=BuiltinConcepts.UNKNOWN_CONCEPT)
assert sheerka.recognize_error(context, __type=UnknownConcept)
assert sheerka.recognize_error(context, __type="UnknownConcept")
assert sheerka.recognize_error(context, BuiltinConcepts.UNKNOWN_CONCEPT)
assert sheerka.recognize_error(context, UnknownConcept)
assert sheerka.recognize_error(context, "UnknownConcept")
assert sheerka.recognize_error(context, f"self.name == '{BuiltinConcepts.UNKNOWN_CONCEPT}'")
assert sheerka.recognize_error(context, f"get_type(self) == '{BuiltinConcepts.UNKNOWN_CONCEPT}'")
def test_i_can_recognized_error_when_error_is_a_error_ErrorObj(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
simple_error = sheerka.new(BuiltinConcepts.ERROR, body=NoConditionFound())
ret1 = sheerka.ret("Test1", False, simple_error)
context.add_values(return_values=[ret1])
service.on_user_input_evaluated(context)
assert sheerka.recognize_error(context, __type=NoConditionFound)
assert sheerka.recognize_error(context, __type="NoConditionFound")
def test_i_cannot_recognize_unknown_concept_when_no_error(self):
sheerka, context = self.init_test().unpack()
res = sheerka.has_unknown_concepts(context)
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
def test_i_can_manage_direct_unknown_concept(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
exact_concept_parser = ExactConceptParser()
# a simple unknown concept
ret = exact_concept_parser.parse(context, ParserInput("foo bar"))
context.add_values(return_values=[ret])
service.on_user_input_evaluated(context)
assert sheerka.has_unknown_concepts(context)
assert sheerka.get_from_memory(context, LAST_UNKNOWN_CONCEPTS).obj == "foo bar"
def test_i_can_manage_multiple_direct_unknown_concept(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
exact_concept_parser = ExactConceptParser()
# a simple unknown concept
ret1 = exact_concept_parser.parse(context, ParserInput("foo"))
ret2 = exact_concept_parser.parse(context, ParserInput("bar"))
context.add_values(return_values=[ret1, ret2])
service.on_user_input_evaluated(context)
assert sheerka.has_unknown_concepts(context)
assert sheerka.get_from_memory(context, LAST_UNKNOWN_CONCEPTS).obj == {"foo", "bar"}
@pytest.mark.parametrize("source, expected", [
("foo bar", "foo"),
("bar foo", "foo"),
("foo bar baz", {"foo", "baz"}),
("my foo bar my baz", {"my foo", "my baz"}),
])
def test_i_can_manage_unknown_concept_when_parts_are_recognized(self, source, expected):
sheerka, context, foo = self.init_concepts("bar")
service = sheerka.services[SheerkaErrorManager.NAME]
exact_concept_parser = ExactConceptParser()
ret1 = exact_concept_parser.parse(context, ParserInput(source))
context.add_values(return_values=[ret1])
service.on_user_input_evaluated(context)
assert sheerka.has_unknown_concepts(context)
assert sheerka.get_from_memory(context, LAST_UNKNOWN_CONCEPTS).obj == expected
def test_i_can_manage_multiple_unknown_concept_when_parts_are_recognized(self):
sheerka, context, foo = self.init_concepts("bar")
service = sheerka.services[SheerkaErrorManager.NAME]
exact_concept_parser = ExactConceptParser()
ret1 = exact_concept_parser.parse(context, ParserInput("foo bar"))
ret2 = exact_concept_parser.parse(context, ParserInput("my foo bar my baz"))
context.add_values(return_values=[ret1, ret2])
service.on_user_input_evaluated(context)
assert sheerka.has_unknown_concepts(context)
assert sheerka.get_from_memory(context, LAST_UNKNOWN_CONCEPTS).obj == {"foo", "my foo", "my baz"}
def test_i_can_manage_unknown_concept_from_name_error(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaErrorManager.NAME]
python_parser = PythonParser()
python_evaluator = PythonEvaluator()
#
ret = python_parser.parse(context, ParserInput("foo"))
ret = python_evaluator.eval(context, ret)
context.add_values(return_values=[ret])
service.on_user_input_evaluated(context)
assert sheerka.has_unknown_concepts(context)
assert sheerka.get_from_memory(context, LAST_UNKNOWN_CONCEPTS).obj == "foo"
def test_i_can_manage_unknown_concept_from_bnf_error(self):
sheerka, context, quantify_x = self.init_concepts(
Concept("quantify x", definition="('one' | 'two')=unit x").def_var("x"),
create_new=True
)
service = sheerka.services[SheerkaErrorManager.NAME]
bnf_node_parser = BnfNodeParser()
# a simple unknown concept
ret = bnf_node_parser.parse(context, ParserInput("one foo"))
context.add_values(return_values=[ret])
service.on_user_input_evaluated(context)
assert sheerka.has_unknown_concepts(context)
assert sheerka.get_from_memory(context, LAST_UNKNOWN_CONCEPTS).obj == "foo"
class TestFileBasedSheerkaErrorManger(TestUsingFileBasedSheerka):
def test_i_can_remember_last_error(self):
sheerka = self.get_sheerka()
context = self.get_context(message="TestingErrorManagement::get_last_errors()")
service = sheerka.services[SheerkaErrorManager.NAME]
simple_error = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body=Concept("foo"))
ret1 = sheerka.ret("Test1", False, simple_error)
sub_error_is_an_exception = sheerka.new(BuiltinConcepts.NOT_FOR_ME, reason=NotImplementedError())
ret2 = sheerka.ret("Test2", False, sub_error_is_an_exception)
context.add_values(return_values=[ret1, ret2])
service.on_user_input_evaluated(context)
new_context = self.get_context(sheerka)
explanations = sheerka.get_last_errors(new_context)
self.commit(context)
assert sheerka.isinstance(explanations, BuiltinConcepts.EXPLANATION)
assert len(explanations.body) == 3
assert service.last_detected_errors_event_id == context.event.get_digest()
assert service.last_detected_errors_event_message == context.event.message
assert service.current_errors_event_id == context.event.get_digest()
assert service.current_errors_event_message == context.event.message
sheerka = self.new_sheerka_instance()
service = sheerka.services[SheerkaErrorManager.NAME]
assert service.last_detected_errors_event_id == context.event.get_digest()
assert service.last_detected_errors_event_message == context.event.message
assert service.current_errors_event_id == context.event.get_digest()
assert service.current_errors_event_message == context.event.message
self.reset_hard_test_env()
+7 -3
View File
@@ -21,7 +21,9 @@ class TestSheerkaHistoryManager(TestUsingFileBasedSheerka):
sheerka.evaluate_user_input("five")
h = list(service.history(-1)) # all
assert h == [
transformed_h = [hist(item.event.message, item.status) for item in h]
assert transformed_h == [
hist("five", True),
hist("def concept five as 5", True),
hist("four", True),
@@ -37,13 +39,15 @@ class TestSheerkaHistoryManager(TestUsingFileBasedSheerka):
]
h = list(service.history(2))
assert h == [
transformed_h = [hist(item.event.message, item.status) for item in h]
assert transformed_h == [
hist("five", True),
hist("def concept five as 5", True)
]
h = list(service.history(2, 2))
assert h == [
transformed_h = [hist(item.event.message, item.status) for item in h]
assert transformed_h == [
hist("four", True),
hist("def concept four as 4", True),
]
+29 -3
View File
@@ -3,11 +3,10 @@ from core.builtin_helpers import ensure_evaluated
from core.concept import Concept
from core.global_symbols import NotFound
from core.sheerka.ExecutionContext import ExecutionContext
from core.sheerka.services.SheerkaMemory import SheerkaMemory, MemoryObject
from core.sheerka.services.SheerkaMemory import MemoryObject, SheerkaMemory
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import CV, compare_with_test_object, CB
from tests.parsers.parsers_utils import CB, CV, compare_with_test_object
class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
@@ -92,6 +91,33 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
foo)}
assert id(sheerka.get_from_memory(context, "a").obj) == id(foo)
# another object is appended
bar = Concept("bar")
sheerka.add_to_memory(context, "a", bar)
assert sheerka.om.copy(SheerkaMemory.OBJECTS_ENTRY) == {
"a": [
MemoryObject(context.event.get_digest(), context.event.date.timestamp(), foo),
MemoryObject(context.event.get_digest(), context.event.date.timestamp(), bar)
]}
def test_i_can_set_and_retrieve_from_memory(self):
sheerka, context = self.init_test().unpack()
assert sheerka.get_from_memory(context, "a") is NotFound
foo = Concept("foo")
sheerka.set_in_memory(context, "a", foo)
assert sheerka.om.copy(SheerkaMemory.OBJECTS_ENTRY) == {"a": MemoryObject(context.event.get_digest(),
context.event.date.timestamp(),
foo)}
assert id(sheerka.get_from_memory(context, "a").obj) == id(foo)
# another object replace the first one
sheerka.set_in_memory(context, "a", "foo")
assert sheerka.om.copy(SheerkaMemory.OBJECTS_ENTRY) == {"a": MemoryObject(context.event.get_digest(),
context.event.date.timestamp(),
"foo")}
def test_i_can_use_memory_with_a_string(self):
sheerka, context = self.init_test().unpack()
+23
View File
@@ -2,6 +2,7 @@ from dataclasses import dataclass
import pytest
from core.builtin_concepts import NotFoundConcept
from core.builtin_concepts_ids import BuiltinConcepts
from core.concept import Concept
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@@ -143,6 +144,28 @@ class TestSheerkaQueryManager(TestUsingMemoryBasedSheerka):
res = sheerka.filter_objects(context, lst, mapping=lambda o: o.prop1, predicate="self is a concept")
assert res == [lst[1], lst[3]]
def test_i_can_filter_objects_by_type(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", "a12"), Concept("foo"), NotImplementedError(), NotFoundConcept()]
assert sheerka.filter_objects(context, lst, __type="A") == [lst[0]]
assert sheerka.filter_objects(context, lst, __type="foo") == [lst[1]]
assert sheerka.filter_objects(context, lst, __type="NotImplementedError") == [lst[2]]
assert sheerka.filter_objects(context, lst, __type=NotImplementedError) == [lst[2]]
assert sheerka.filter_objects(context, lst, __type=BuiltinConcepts.NOT_FOUND) == [lst[3]]
assert sheerka.filter_objects(context, lst, __type=NotFoundConcept) == [lst[3]]
assert sheerka.filter_objects(context, lst, __type="NotFoundConcept") == [lst[3]]
def test_empty_list_is_returned_when_nothing_is_found(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", "a12")]
assert sheerka.filter_objects(context, lst, __type="foo") == []
assert sheerka.filter_objects(context, [], __type="foo") == []
assert sheerka.filter_objects(context, lst, predicate="self.name == 'bar'") == []
def test_i_must_select_object_property_using_string(self):
sheerka, context = self.init_test().unpack()
+10 -10
View File
@@ -345,23 +345,23 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
("not __ret.status", "__ret", [NEGCOND("#__x_00__|__name__|'__ret.status'")]),
("__ret and not __ret.status", "__ret",
["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__ret.status'")]),
("not recognize(__ret.body, hello sheerka)", "__ret", ["#__x_00__|__name__|'__ret'",
NCCOND(["#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'__sheerka__'"])]),
("__ret and not __error", "__ret", ["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__error'")]),
("not recognize(self, hello sheerka)", "__ret", ["#__x_00__|__name__|'self'",
NCCOND(["#__x_00__|__is_concept__|True",
"#__x_00__|key|'hello __var__0'",
"#__x_00__|a|'__sheerka__'"])]),
# ("not recognize(__ret.body, hello sheerka)", "__ret", ["#__x_00__|__name__|'__ret'",
# NCCOND(["#__x_00__|body|#__x_01__",
# "#__x_01__|__is_concept__|True",
# "#__x_01__|key|'hello __var__0'",
# "#__x_01__|a|'__sheerka__'"])]),
# ("not recognize(self, hello sheerka)", "__ret", ["#__x_00__|__name__|'self'",
# NCCOND(["#__x_00__|__is_concept__|True",
# "#__x_00__|key|'hello __var__0'",
# "#__x_00__|a|'__sheerka__'"])]),
])
def test_i_can_get_rete_using_not(self, expression, bag_key, expected):
sheerka, context, greetings, foo = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
).unpack()
parser = ExpressionParser(old_style=True)
parser = ExpressionParser()
expected_conditions = get_rete_conditions(*expected)
error_sink = ErrorSink()
@@ -25,7 +25,7 @@ class BaseTestSheerkaRuleManagerRulesCompilation(TestUsingMemoryBasedSheerka):
@staticmethod
def get_conditions(context, expression):
parser = ExpressionParser(old_style=True)
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
@@ -927,7 +927,7 @@ class TestSheerkaRuleManagerRulesCompilationRecognizeConcept(BaseTestSheerkaRule
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser(old_style=True)
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_str)
error_sink = ErrorSink()
+15 -156
View File
@@ -3,14 +3,13 @@ import os
import pytest
from conftest import SHEERKA_TEST_FOLDER
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UnknownConcept, UserInputConcept
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
from core.builtin_concepts_ids import AllBuiltinConcepts
from core.concept import Concept, ConceptParts, PROPERTIES_TO_SERIALIZE, get_concept_attrs
from core.global_symbols import NotInit
from core.sheerka.Sheerka import BASE_NODE_PARSER_CLASS, Sheerka
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager, ValueNotFound
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
from core.tokenizer import Token, TokenKind
from parsers.PythonParser import PythonErrorNode
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@@ -44,21 +43,25 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
def test_i_can_list_builtin_concepts(self):
sheerka = self.get_sheerka()
builtins = list(sheerka.get_builtins_classes_as_dict())
builtins, _ = sheerka.get_builtins_classes_as_dict()
assert str(BuiltinConcepts.ERROR) in builtins
assert str(BuiltinConcepts.RETURN_VALUE) in builtins
assert BuiltinConcepts.ERROR in builtins
assert BuiltinConcepts.RETURN_VALUE in builtins
def test_i_can_get_a_builtin_concept_by_their_enum_or_the_string(self):
"""
Checks that a concept can be found its name
even when there are variables in the name (ex 'hello + a' or 'a + b' )
Also returns the mapping between concept name and specific class name
:return:
"""
sheerka = self.get_sheerka()
for key in sheerka.get_builtins_classes_as_dict():
builtins_by_key, builtins_by_class_name = sheerka.get_builtins_classes_as_dict()
for key in builtins_by_key:
assert sheerka.get_by_key(key) is not None
assert sheerka.get_by_key(str(key)) is not None
for k, v in builtins_by_class_name.items():
assert type(sheerka.get_by_key(v)).__name__ == k
def test_i_cannot_get_when_key_is_none(self):
sheerka = self.get_sheerka()
@@ -98,7 +101,8 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
assert ret.value == "value"
# check the others
for key, concept_class in sheerka.get_builtins_classes_as_dict().items():
builtins_by_key, _ = sheerka.get_builtins_classes_as_dict()
for key, concept_class in builtins_by_key.items():
assert isinstance(sheerka.get_by_key(key), concept_class)
def test_i_can_instantiate_a_builtin_concept_when_no_specific_class(self):
@@ -426,151 +430,6 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.ONTOLOGY_ALREADY_DEFINED)
@pytest.mark.parametrize("obj, expected", [
("a string", []),
(True, []),
(False, []),
(Concept("foo"), []),
(Concept("foo", body=False).auto_init(), []),
(UnknownConcept(), [UnknownConcept()]),
(Concept("foo", body=UnknownConcept()).auto_init(), [UnknownConcept()]),
(PythonErrorNode("msg", None), [PythonErrorNode("msg", None)])
])
def test_i_can_get_error_for_simple_objects(self, obj, expected):
sheerka, context = self.init_test().unpack()
assert sheerka.get_errors(context, obj) == expected
def test_i_can_get_error_when_builtin_concept_in_error(self):
sheerka, context = self.init_test().unpack()
obj = sheerka.new(BuiltinConcepts.ONTOLOGY_ALREADY_DEFINED)
assert sheerka.get_errors(context, obj) == [obj]
def test_i_can_get_error_when_return_value(self):
sheerka, context = self.init_test().unpack()
error = sheerka.err("an error")
ret_val = ReturnValueConcept("Test", False, sheerka.err("an error"))
assert sheerka.get_errors(context, ret_val) == [error]
def test_i_can_get_inner_error(self):
sheerka, context = self.init_test().unpack()
error = sheerka.err("an error")
ret_val = ReturnValueConcept("Test", False, sheerka.err("an error"))
assert sheerka.get_errors(context, ret_val) == [error]
def test_i_can_get_error_when_embedded_errors(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
not_an_error = sheerka.new(BuiltinConcepts.AUTO_EVAL)
error = sheerka.err([concept_eval_error, unknown_concept, not_an_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(context, ret_val)
assert errors_found == [error, concept_eval_error, unknown_concept]
def test_i_can_get_error_from_list(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
not_an_error = sheerka.new(BuiltinConcepts.AUTO_EVAL)
error = sheerka.err([concept_eval_error, unknown_concept, not_an_error])
ret_val_1 = ReturnValueConcept("Test", False, error)
python_error = PythonErrorNode("msg", Exception())
value_not_found = ValueNotFound("item", "value")
multiple_error = sheerka.new(BuiltinConcepts.MULTIPLE_ERRORS, body=[python_error, value_not_found])
ret_val_2 = ReturnValueConcept("Test", False, multiple_error)
errors_found = sheerka.get_errors(context, [ret_val_1, ret_val_2])
assert errors_found == [error, concept_eval_error, unknown_concept,
multiple_error, python_error, value_not_found]
def test_i_can_filter_error_by_concept_key(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
python_error = PythonErrorNode("msg", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(context, ret_val, __type=BuiltinConcepts.CONCEPT_EVAL_ERROR)
assert errors_found == [concept_eval_error]
def test_i_can_filter_error_by_class_name(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
python_error = PythonErrorNode("msg", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(context, ret_val, __type="PythonErrorNode")
assert errors_found == [python_error]
def test_i_can_filter_error_by_concept_attribute(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, concept_ref="a_concept_ref")
python_error = PythonErrorNode("msg", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(context, ret_val, concept_ref="a_concept_ref")
assert errors_found == [unknown_concept]
def test_i_can_filter_error_by_class_attribute(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, concept_ref="a_concept_ref")
python_error = PythonErrorNode("error source", Exception())
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(context, ret_val, source="error source")
assert errors_found == [python_error]
def test_i_can_filter_error_by_exception_name(self):
sheerka, context = self.init_test().unpack()
from evaluators.PythonEvaluator import PythonEvalError
name_error = NameError("foo")
python_eval_error = PythonEvalError(name_error, "foo", None, None)
error = sheerka.err([python_eval_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(context, ret_val, __type="NameError")
assert errors_found == [name_error]
def test_i_can_filter_error_on_multiple_criteria(self):
sheerka, context = self.init_test().unpack()
concept_eval_error = sheerka.new(BuiltinConcepts.CONCEPT_EVAL_ERROR)
unknown_concept = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, concept_ref="a_concept_ref")
value_not_found = ValueNotFound("an_item", "a value")
error = sheerka.err([concept_eval_error, unknown_concept, value_not_found])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(context, ret_val, __type="ValueNotFound", item="an_item", value="a value")
assert errors_found == [value_not_found]
def test_i_cannot_get_error_when_return_value_s_status_is_true(self):
sheerka, context = self.init_test().unpack()
ret_val = ReturnValueConcept("Test", True, sheerka.err("an error"))
assert sheerka.get_errors(context, ret_val) == []
def test_i_can_add_and_remove_global_context_hints(self):
sheerka, context = self.init_test().unpack()
@@ -592,7 +451,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
).unpack()
res = sheerka.evaluate_user_input("eval foo", "testing_user")
assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONDITION_FAILED) # sanity check
assert sheerka.isinstance(res[0].value.value, BuiltinConcepts.CONDITION_FAILED) # sanity check
sheerka.add_to_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
res = sheerka.evaluate_user_input("eval foo", "testing_user")
@@ -600,7 +459,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
sheerka.remove_fom_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
res = sheerka.evaluate_user_input("eval foo", "testing_user")
assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONDITION_FAILED)
assert sheerka.isinstance(res[0].value.value, BuiltinConcepts.CONDITION_FAILED)
class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
+6 -6
View File
@@ -1316,11 +1316,11 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
sheerka.create_new_rule(context, Rule(ACTION_TYPE_EXEC, "rule3", "id3.attr3 == 'value'", "True"))
sheerka.pop_ontology(context)
assert rules_by_ontology_from_cache() == {'#unit_test#': {'10'}}
assert ontologies_from_cache() == {'10': '#unit_test#'}
assert rules_by_ontology_from_cache() == {'#unit_test#': {'11'}}
assert ontologies_from_cache() == {'11': '#unit_test#'}
# check that the 'rule is deleted' events are raised
assert events_raised == {'11', '12'}
assert events_raised == {'12', '13'}
# def test_i_can_list_by_key_when_dictionaries(self):
# sheerka = self.get_sheerka(cache_only=False)
@@ -1664,6 +1664,6 @@ class TestSheerkaOntologyWithFileBasedSheerka(TestUsingFileBasedSheerka):
rules_from_db = sheerka.om.self_cache_manager.sdp.get(SheerkaOntologyManager.RULES_BY_ONTOLOGY_ENTRY)
del rules_from_db["__default__"]
assert rules_from_db == {
'#unit_test#': {'10'},
'another ontology': {'13'},
'new ontology': {'12'}}
'#unit_test#': {'11'},
'another ontology': {'14'},
'new ontology': {'13'}}