Refactored sheerka execution flow + Enhanced log management
This commit is contained in:
@@ -41,7 +41,7 @@ def get_concept_part(part):
|
||||
if isinstance(part, str):
|
||||
node = PythonNode(part, ast.parse(part, mode="eval"))
|
||||
return ReturnValueConcept(
|
||||
who="Parsers:DefaultParser",
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part,
|
||||
@@ -50,7 +50,7 @@ def get_concept_part(part):
|
||||
|
||||
if isinstance(part, PythonNode):
|
||||
return ReturnValueConcept(
|
||||
who="Parsers:DefaultParser",
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part.source,
|
||||
|
||||
@@ -729,6 +729,18 @@ def test_i_can_detect_indirect_infinite_recursion_with_sequence_or_ordered_choic
|
||||
assert bar not in parser.concepts_grammars # removed because of the infinite recursion
|
||||
|
||||
|
||||
def test_infinite_recursion_does_not_fail_if_a_concept_is_missing():
|
||||
foo = Concept(name="foo")
|
||||
bar = Concept(name="bar")
|
||||
|
||||
concepts = {
|
||||
foo: bar
|
||||
}
|
||||
parser = ConceptLexerParser()
|
||||
parser.initialize(get_context(), concepts)
|
||||
|
||||
assert foo in parser.concepts_grammars
|
||||
|
||||
def test_i_can_detect_indirect_infinite_recursion_with_optional():
|
||||
# TODO infinite recursion with optional
|
||||
pass
|
||||
|
||||
@@ -6,7 +6,7 @@ from core.sheerka import Sheerka, ExecutionContext
|
||||
from parsers.ConceptLexerParser import OrderedChoice, StrMatch, ConceptMatch
|
||||
from parsers.PythonParser import PythonParser, PythonNode
|
||||
from core.tokenizer import Keywords, Tokenizer
|
||||
from parsers.DefaultParser import DefaultParser, NameNode, SyntaxErrorNode
|
||||
from parsers.DefaultParser import DefaultParser, NameNode, SyntaxErrorNode, CannotHandleErrorNode
|
||||
from parsers.DefaultParser import UnexpectedTokenErrorNode, DefConceptNode
|
||||
from parsers.BnfParser import BnfParser
|
||||
|
||||
@@ -68,7 +68,7 @@ def get_concept(name, where=None, pre=None, post=None, body=None, definition=Non
|
||||
concept.post = get_concept_part(post)
|
||||
if definition:
|
||||
concept.definition = ReturnValueConcept(
|
||||
"Parsers:RegexParser",
|
||||
"parsers.Bnf",
|
||||
True,
|
||||
definition)
|
||||
|
||||
@@ -85,7 +85,7 @@ def get_concept_part(part):
|
||||
if isinstance(part, str):
|
||||
node = PythonNode(part, ast.parse(part, mode="eval"))
|
||||
return ReturnValueConcept(
|
||||
who="Parsers:DefaultParser",
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part,
|
||||
@@ -94,7 +94,7 @@ def get_concept_part(part):
|
||||
|
||||
if isinstance(part, PythonNode):
|
||||
return ReturnValueConcept(
|
||||
who="Parsers:DefaultParser",
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part.source,
|
||||
@@ -359,3 +359,14 @@ def test_i_can_detect_empty_bnf_declaration():
|
||||
|
||||
assert not res.status
|
||||
assert res.value.value[0] == SyntaxErrorNode([], "Empty declaration")
|
||||
|
||||
|
||||
def test_i_can_detect_not_for_me():
|
||||
text = "hello world"
|
||||
context = get_context()
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.NOT_FOR_ME)
|
||||
assert isinstance(res.value.body[0], CannotHandleErrorNode)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import ExecutionContext
|
||||
|
||||
|
||||
def test_id_is_incremented_by_event_digest():
|
||||
a = ExecutionContext("foo", "event_1", None)
|
||||
b = ExecutionContext("foo", "event_1", None)
|
||||
c = ExecutionContext("foo", "event_2", None)
|
||||
d = b.push()
|
||||
e = c.push()
|
||||
|
||||
assert a.id == 0
|
||||
assert b.id == 1
|
||||
assert c.id == 0
|
||||
assert d.id == 2
|
||||
assert e.id == 1
|
||||
|
||||
|
||||
def test_some_properties_are_given_to_the_child():
|
||||
a = ExecutionContext("foo", "event_1", "fake_sheerka",
|
||||
desc="some description",
|
||||
obj=Concept("foo"),
|
||||
step=BuiltinConcepts.EVALUATION,
|
||||
iteration=15,
|
||||
concepts={"bar": Concept("bar")})
|
||||
|
||||
b = a.push()
|
||||
|
||||
assert b.who == a.who
|
||||
assert b.event_digest == a.event_digest
|
||||
assert b.sheerka == a.sheerka
|
||||
assert b.desc == ""
|
||||
assert b.obj == a.obj
|
||||
assert b.step == a.step
|
||||
assert b.iteration == a.iteration
|
||||
assert b.concepts == a.concepts
|
||||
assert b.id == a.id + 1
|
||||
assert b._tab == a._tab + " "
|
||||
+53
-29
@@ -61,12 +61,12 @@ def test_builtin_concepts_are_initialized():
|
||||
|
||||
|
||||
def test_builtin_concepts_can_be_updated():
|
||||
sheerka = get_sheerka(False, skip_builtins_in_db=False)
|
||||
sheerka = get_sheerka(False, False)
|
||||
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
||||
loaded_sheerka.metadata.desc = "I have a description"
|
||||
sheerka.sdp.modify("Test", sheerka.CONCEPTS_ENTRY, loaded_sheerka.key, loaded_sheerka)
|
||||
|
||||
sheerka = get_sheerka(False)
|
||||
sheerka = get_sheerka(False, False)
|
||||
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
||||
|
||||
assert loaded_sheerka.metadata.desc == "I have a description"
|
||||
@@ -313,6 +313,12 @@ def test_i_cannot_get_value_when_no_body_and_allow_none_body_is_false():
|
||||
body=concept)
|
||||
|
||||
|
||||
def test_list_of_concept_is_sorted_by_id():
|
||||
sheerka = get_sheerka(False, False)
|
||||
concepts = sheerka.concepts()
|
||||
|
||||
assert concepts[0].id < concepts[-1].id
|
||||
|
||||
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
#
|
||||
# E V A L U A T I O N S
|
||||
@@ -326,7 +332,7 @@ def test_i_cannot_get_value_when_no_body_and_allow_none_body_is_false():
|
||||
def test_i_can_eval_python_expressions_with_no_variable(text, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
res = sheerka.eval(text)
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
@@ -339,7 +345,7 @@ def test_i_can_eval_concept_with_python_body():
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.eval(text)
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == 1
|
||||
@@ -352,7 +358,7 @@ def test_i_can_eval_concept_with_concept_body():
|
||||
sheerka.add_in_cache(concept_one)
|
||||
sheerka.add_in_cache(concept_un)
|
||||
|
||||
res = sheerka.eval("un")
|
||||
res = sheerka.evaluate_user_input("un")
|
||||
return_value = res[0].value
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
@@ -365,7 +371,7 @@ def test_i_can_eval_concept_with_no_body():
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.eval(text)
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == concept
|
||||
@@ -378,7 +384,7 @@ def test_is_unique_property_is_used_when_evaluating():
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.eval(text)
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == concept
|
||||
@@ -403,7 +409,7 @@ as:
|
||||
expected.init_key()
|
||||
|
||||
sheerka = get_sheerka()
|
||||
res = sheerka.eval(text)
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
@@ -431,7 +437,7 @@ def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept()
|
||||
concept_a_plus_b = Concept(name="a plus b").set_prop("a").set_prop("b")
|
||||
sheerka.add_in_cache(concept_a_plus_b)
|
||||
|
||||
res = sheerka.eval("def concept a xx b as a plus b")
|
||||
res = sheerka.evaluate_user_input("def concept a xx b as a plus b")
|
||||
expected = Concept(name="a xx b", body="a plus b").set_prop("a").set_prop("b").init_key()
|
||||
expected.metadata.id = "1001"
|
||||
|
||||
@@ -462,14 +468,31 @@ as:
|
||||
"""
|
||||
|
||||
sheerka = get_sheerka()
|
||||
sheerka.eval(text)
|
||||
res = sheerka.eval(text)
|
||||
sheerka.evaluate_user_input(text)
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert not res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
|
||||
|
||||
|
||||
def test_i_can_disable_an_evaluator():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept(name="one", body="1")
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
p = next(e for e in sheerka.evaluators if e.__name__ == "PythonEvaluator")
|
||||
p.enabled = False # not that you disable the class, not the instance
|
||||
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.PARSER_RESULT)
|
||||
|
||||
p.enabled = True # put back for the remaining unit tests
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"",
|
||||
" ",
|
||||
@@ -478,7 +501,7 @@ as:
|
||||
def test_i_can_eval_a_empty_input(text):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
res = sheerka.eval(text)
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
@@ -492,7 +515,7 @@ def test_i_can_eval_concept_with_variable():
|
||||
sheerka.add_in_cache(concept_hello)
|
||||
sheerka.add_in_cache(concept_foo)
|
||||
|
||||
res = sheerka.eval("hello foo")
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
return_value = res[0].value
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
@@ -505,7 +528,7 @@ def test_i_can_eval_concept_with_variable_and_python_as_body():
|
||||
sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").set_prop("a"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
|
||||
|
||||
res = sheerka.eval("hello foo")
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value, "hello foo"
|
||||
@@ -518,7 +541,7 @@ def test_i_can_eval_duplicate_concepts_with_same_value():
|
||||
sheerka.add_in_cache(Concept(name="hello foo", body="'hello foo'"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
|
||||
|
||||
res = sheerka.eval("hello foo")
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value, "hello foo"
|
||||
@@ -532,7 +555,7 @@ def test_i_cannot_manage_duplicate_concepts_when_the_values_are_different():
|
||||
sheerka.add_in_cache(Concept(name="hello foo", body="'hello foo'"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'another value'"))
|
||||
|
||||
res = sheerka.eval("hello foo")
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
assert len(res) == 1
|
||||
assert not res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||
@@ -551,7 +574,7 @@ def test_i_can_manage_concepts_with_the_same_key_when_values_are_the_same():
|
||||
sheerka.create_new_concept(context, Concept(name="hello a", body="'hello ' + a").set_prop("a"))
|
||||
sheerka.create_new_concept(context, Concept(name="hello b", body="'hello ' + b").set_prop("b"))
|
||||
|
||||
res = sheerka.eval("hello 'foo'")
|
||||
res = sheerka.evaluate_user_input("hello 'foo'")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == "hello foo"
|
||||
@@ -563,7 +586,7 @@ def test_i_can_create_concepts_with_python_code_as_body():
|
||||
context = get_context(sheerka)
|
||||
|
||||
sheerka.create_new_concept(context, Concept(name="concepts", body="sheerka.concepts()"))
|
||||
res = sheerka.eval("concepts")
|
||||
res = sheerka.evaluate_user_input("concepts")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
@@ -571,14 +594,14 @@ def test_i_can_create_concepts_with_python_code_as_body():
|
||||
|
||||
|
||||
def test_i_can_create_concept_with_bnf_definition():
|
||||
sheerka = get_sheerka()
|
||||
sheerka = get_sheerka(False, False)
|
||||
a = Concept("a")
|
||||
sheerka.add_in_cache(a)
|
||||
sheerka.concepts_grammars = ConceptLexerParser().initialize(
|
||||
get_context(sheerka),
|
||||
{a: OrderedChoice("one", "two")}).body
|
||||
|
||||
res = sheerka.eval("def concept plus from bnf a ('plus' plus)?")
|
||||
res = sheerka.evaluate_user_input("def concept plus from bnf a ('plus' plus)?")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT)
|
||||
@@ -605,21 +628,22 @@ def test_i_can_create_concept_with_bnf_definition():
|
||||
|
||||
def test_i_can_eval_bnf_definitions():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.eval("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
|
||||
res = sheerka.eval("one")
|
||||
res = sheerka.evaluate_user_input("one")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
|
||||
|
||||
def test_i_can_eval_bnf_definitions_with_variables():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.eval("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
concept_b = sheerka.eval("def concept b from bnf a 'three'")[0].body.body
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body
|
||||
|
||||
res = sheerka.eval("one three")
|
||||
res = sheerka.evaluate_user_input("one three")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
@@ -635,14 +659,14 @@ def test_i_can_eval_bnf_definitions_from_separate_instances():
|
||||
but make sure that the BNF are correctly persisted and loaded
|
||||
"""
|
||||
sheerka = get_sheerka(False)
|
||||
concept_a = sheerka.eval("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
|
||||
res = get_sheerka(False).eval("one")
|
||||
res = get_sheerka(False).evaluate_user_input("one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
res = get_sheerka(False).eval("two")
|
||||
res = get_sheerka(False).evaluate_user_input("two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
@@ -650,7 +674,7 @@ def test_i_can_eval_bnf_definitions_from_separate_instances():
|
||||
|
||||
def get_sheerka(use_dict=True, skip_builtins_in_db=True):
|
||||
root = "mem://" if use_dict else root_folder
|
||||
sheerka = Sheerka(skip_builtins_in_db)
|
||||
sheerka = Sheerka(skip_builtins_in_db=skip_builtins_in_db)
|
||||
sheerka.initialize(root)
|
||||
|
||||
return sheerka
|
||||
|
||||
@@ -22,6 +22,11 @@ def read_json_file(sdp, file_name):
|
||||
|
||||
|
||||
class ObjWithKey:
|
||||
"""
|
||||
Object where the key can be resolved using get_key()
|
||||
Not suitable for Json dump as there is no to_dict() method
|
||||
"""
|
||||
|
||||
def __init__(self, a, b):
|
||||
self.a = a
|
||||
self.b = b
|
||||
@@ -39,6 +44,11 @@ class ObjWithKey:
|
||||
|
||||
|
||||
class ObjSetKey:
|
||||
"""
|
||||
Object where the key can be be automatically set thanks to set_key()
|
||||
Not suitable for Json dump as there is no to_dict() method
|
||||
"""
|
||||
|
||||
def __init__(self, value, key=None):
|
||||
self.value = value
|
||||
self.key = key
|
||||
@@ -56,6 +66,11 @@ class ObjSetKey:
|
||||
|
||||
|
||||
class ObjNoKey:
|
||||
"""
|
||||
Object with no key, they won't be ordered
|
||||
Not suitable for Json dump as there is no to_dict() method
|
||||
"""
|
||||
|
||||
def __init__(self, a, b):
|
||||
self.a = a
|
||||
self.b = b
|
||||
@@ -73,6 +88,11 @@ class ObjNoKey:
|
||||
|
||||
|
||||
class ObjDumpJson:
|
||||
"""
|
||||
Object where the key can be resolved using get_key()
|
||||
that can be used to dump as Json
|
||||
"""
|
||||
|
||||
def __init__(self, key=None, value=None):
|
||||
self.key = key
|
||||
self.value = value
|
||||
@@ -104,6 +124,12 @@ class ObjDumpJson:
|
||||
|
||||
|
||||
class ObjWithDigestNoKey:
|
||||
"""
|
||||
Object that can compute its digest.
|
||||
It can be used to test objects sharing the same entry (but that are different)
|
||||
Not suitable for Json dump as there is no to_dict() method
|
||||
"""
|
||||
|
||||
def __init__(self, a, b):
|
||||
self.a = a
|
||||
self.b = b
|
||||
@@ -124,6 +150,12 @@ class ObjWithDigestNoKey:
|
||||
|
||||
|
||||
class ObjWithDigestWithKey:
|
||||
"""
|
||||
Object with a key that can compute its digest.
|
||||
It can be used to test objects sharing the same key (but that are different)
|
||||
Not suitable for Json dump as there is no to_dict() method
|
||||
"""
|
||||
|
||||
def __init__(self, a, b):
|
||||
self.a = a
|
||||
self.b = b
|
||||
@@ -908,6 +940,62 @@ def test_i_can_list_when_one_element(root):
|
||||
assert list(result) == ["foo"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
])
|
||||
def test_i_can_list_when_multiple_entries_under_the_same_key(root):
|
||||
sdp = SheerkaDataProvider(root)
|
||||
sdp.add(evt_digest, "entry", ObjWithKey("a", "b"))
|
||||
sdp.add(evt_digest, "entry", ObjWithKey("a", "c"))
|
||||
|
||||
result = sdp.list("entry")
|
||||
assert list(result) == [[ObjWithKey("a", "b"), ObjWithKey("a", "c")]]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
])
|
||||
def test_i_can_list_when_multiple_entries_under_the_same_key_when_reference(root):
|
||||
sdp = SheerkaDataProvider(root)
|
||||
sdp.serializer.register(PickleSerializer(lambda obj: isinstance(obj, ObjWithKey)))
|
||||
|
||||
sdp.add(evt_digest, "entry", ObjWithKey("a", "b"), use_ref=True)
|
||||
sdp.add(evt_digest, "entry", ObjWithKey("a", "c"), use_ref=True)
|
||||
|
||||
result = sdp.list("entry")
|
||||
assert list(result) == [[ObjWithKey("a", "b"), ObjWithKey("a", "c")]]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
])
|
||||
def test_i_can_list_when_multiple_entries_under_the_same_entry(root):
|
||||
sdp = SheerkaDataProvider(root)
|
||||
sdp.add(evt_digest, "entry", ObjNoKey("a", "b"))
|
||||
sdp.add(evt_digest, "entry", ObjNoKey("a", "c"))
|
||||
|
||||
result = sdp.list("entry")
|
||||
assert list(result) == [ObjNoKey("a", "b"), ObjNoKey("a", "c")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
])
|
||||
def test_i_can_list_when_multiple_entries_under_the_same_entry_when_reference(root):
|
||||
sdp = SheerkaDataProvider(root)
|
||||
sdp.serializer.register(PickleSerializer(lambda obj: isinstance(obj, ObjNoKey)))
|
||||
|
||||
sdp.add(evt_digest, "entry", ObjNoKey("a", "b"), use_ref=True)
|
||||
sdp.add(evt_digest, "entry", ObjNoKey("a", "c"), use_ref=True)
|
||||
|
||||
result = sdp.list("entry")
|
||||
assert list(result) == [ObjNoKey("a", "b"), ObjNoKey("a", "c")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
# Make sure that the evaluators works as expected
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator, BaseEvaluator
|
||||
|
||||
|
||||
def get_sheerka():
|
||||
sheerka = Sheerka()
|
||||
sheerka.initialize("mem://")
|
||||
return sheerka
|
||||
|
||||
|
||||
def get_context(sheerka):
|
||||
return ExecutionContext("test", "xxx", sheerka)
|
||||
|
||||
|
||||
def get_ret_val(sheerka, concept, who="who"):
|
||||
concept.init_key()
|
||||
if concept.key not in sheerka.concepts_cache:
|
||||
sheerka.concepts_cache[concept.key] = concept
|
||||
return sheerka.ret(who, True, sheerka.new(concept.key))
|
||||
|
||||
|
||||
class EvaluatorWithPriority(OneReturnValueEvaluator):
|
||||
out = []
|
||||
|
||||
def __init__(self, name, priority):
|
||||
super().__init__(name, priority)
|
||||
|
||||
def matches(self, context, return_value):
|
||||
target = str(return_value.body.key)
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
text += f"{self.name[len(BaseEvaluator.PREFIX):]} - matches - target={target}"
|
||||
self.out.append(text)
|
||||
return True
|
||||
|
||||
def eval(self, context, return_value):
|
||||
target = str(return_value.body.key)
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
text += f"{self.name[len(BaseEvaluator.PREFIX):]} - eval - target={target}"
|
||||
self.out.append(text)
|
||||
|
||||
|
||||
class EvaluatorWithPriority10(EvaluatorWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority10", 10)
|
||||
|
||||
|
||||
class EvaluatorWithPriority15(EvaluatorWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority15", 15)
|
||||
|
||||
|
||||
class EvaluatorWithPriority20(EvaluatorWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority20", 20)
|
||||
|
||||
|
||||
class EvaluatorModifyFoo(EvaluatorWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("modifyFoo", 10)
|
||||
|
||||
def matches(self, context, return_value):
|
||||
super().matches(context, return_value)
|
||||
return context.sheerka.isinstance(return_value.body, "foo")
|
||||
|
||||
def eval(self, context, return_value):
|
||||
super().eval(context, return_value)
|
||||
return get_ret_val(context.sheerka, Concept("bar"))
|
||||
|
||||
|
||||
class EvaluatorModifyBar(EvaluatorWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("modifyBar", 10)
|
||||
|
||||
def matches(self, context, return_value):
|
||||
super().matches(context, return_value)
|
||||
return context.sheerka.isinstance(return_value.body, "bar")
|
||||
|
||||
def eval(self, context, return_value):
|
||||
super().eval(context, return_value)
|
||||
return get_ret_val(context.sheerka, Concept("baz"))
|
||||
|
||||
|
||||
def test_that_return_values_is_unchanged_when_no_evaluator():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = []
|
||||
|
||||
entries = get_ret_val(sheerka, Concept("foo"))
|
||||
return_values = sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert return_values == [entries]
|
||||
|
||||
|
||||
def test_i_can_use_a_list_as_input():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = []
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo"))]
|
||||
return_values = sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert return_values == entries
|
||||
|
||||
|
||||
def test_step_concept_is_removed_after_processing_if_not_reduced():
|
||||
"""
|
||||
The entry is not modified by an evaluator
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorWithPriority10]
|
||||
|
||||
entry = get_ret_val(sheerka, Concept("foo"))
|
||||
return_values = sheerka.execute(get_context(sheerka), entry, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert BuiltinConcepts.EVALUATION not in [r.body.key for r in return_values]
|
||||
|
||||
|
||||
def test_step_concept_is_removed_after_processing_if_not_reduced_2():
|
||||
"""
|
||||
This time the entry is modified by an evaluator,
|
||||
nevertheless, step concept is removed
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorModifyFoo]
|
||||
|
||||
entry = get_ret_val(sheerka, Concept("foo"))
|
||||
return_values = sheerka.execute(get_context(sheerka), entry, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert BuiltinConcepts.EVALUATION not in [r.body.key for r in return_values]
|
||||
|
||||
|
||||
def test_that_higher_priority_evaluators_are_evaluated_first():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorWithPriority20, EvaluatorWithPriority10, EvaluatorWithPriority15]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo"))]
|
||||
EvaluatorWithPriority.out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert EvaluatorWithPriority.out == [
|
||||
'__EVALUATION [0] priority20 - matches - target=foo',
|
||||
'__EVALUATION [0] priority20 - eval - target=foo',
|
||||
'__EVALUATION [0] priority20 - matches - target=__EVALUATION',
|
||||
'__EVALUATION [0] priority20 - eval - target=__EVALUATION',
|
||||
'__EVALUATION [0] priority15 - matches - target=foo',
|
||||
'__EVALUATION [0] priority15 - eval - target=foo',
|
||||
'__EVALUATION [0] priority15 - matches - target=__EVALUATION',
|
||||
'__EVALUATION [0] priority15 - eval - target=__EVALUATION',
|
||||
'__EVALUATION [0] priority10 - matches - target=foo',
|
||||
'__EVALUATION [0] priority10 - eval - target=foo',
|
||||
'__EVALUATION [0] priority10 - matches - target=__EVALUATION',
|
||||
'__EVALUATION [0] priority10 - eval - target=__EVALUATION']
|
||||
|
||||
|
||||
def test_that_predicate_is_checked_before_evaluation():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorModifyFoo]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo")), get_ret_val(sheerka, Concept("baz"))]
|
||||
EvaluatorWithPriority.out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert EvaluatorWithPriority.out == [
|
||||
'__EVALUATION [0] modifyFoo - matches - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - eval - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - matches - target=baz',
|
||||
'__EVALUATION [0] modifyFoo - matches - target=__EVALUATION',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=bar',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=baz',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=__EVALUATION'
|
||||
]
|
||||
|
||||
|
||||
def test_evaluation_continue_until_no_more_modification():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorModifyFoo, EvaluatorModifyBar]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo")), get_ret_val(sheerka, Concept("baz"))]
|
||||
EvaluatorWithPriority.out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert EvaluatorWithPriority.out == [
|
||||
'__EVALUATION [0] modifyFoo - matches - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - eval - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - matches - target=baz',
|
||||
'__EVALUATION [0] modifyFoo - matches - target=__EVALUATION',
|
||||
'__EVALUATION [0] modifyBar - matches - target=foo',
|
||||
'__EVALUATION [0] modifyBar - matches - target=baz',
|
||||
'__EVALUATION [0] modifyBar - matches - target=__EVALUATION',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=bar',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=baz',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=__EVALUATION',
|
||||
'__EVALUATION [1] modifyBar - matches - target=bar',
|
||||
'__EVALUATION [1] modifyBar - eval - target=bar',
|
||||
'__EVALUATION [1] modifyBar - matches - target=baz',
|
||||
'__EVALUATION [1] modifyBar - matches - target=__EVALUATION',
|
||||
'__EVALUATION [2] modifyFoo - matches - target=baz',
|
||||
'__EVALUATION [2] modifyFoo - matches - target=baz',
|
||||
'__EVALUATION [2] modifyFoo - matches - target=__EVALUATION',
|
||||
'__EVALUATION [2] modifyBar - matches - target=baz',
|
||||
'__EVALUATION [2] modifyBar - matches - target=baz',
|
||||
'__EVALUATION [2] modifyBar - matches - target=__EVALUATION'
|
||||
]
|
||||
Reference in New Issue
Block a user