Refactored sheerka class: splitted to use sub handlers. Refactored unit tests to use classes.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import ast
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
class BaseTest:
|
||||
def get_sheerka(self):
|
||||
pass
|
||||
|
||||
def get_context(self, sheerka=None):
|
||||
return ExecutionContext("test", Event(), sheerka or self.get_sheerka())
|
||||
|
||||
def get_default_concept(self):
|
||||
concept = Concept(
|
||||
name="a + b",
|
||||
where="isinstance(a, int) and isinstance(b, int)",
|
||||
pre="isinstance(a, int) and isinstance(b, int)",
|
||||
post="isinstance(res, int)",
|
||||
body="def func(x,y):\n return x+y\nfunc(a,b)",
|
||||
desc="specific description")
|
||||
concept.def_prop("a", "value1")
|
||||
concept.def_prop("b", "value2")
|
||||
|
||||
return concept
|
||||
|
||||
def dump_ast(self, node):
|
||||
dump = ast.dump(node)
|
||||
for to_remove in [", ctx=Load()", ", kind=None", ", type_ignores=[]"]:
|
||||
dump = dump.replace(to_remove, "")
|
||||
return dump
|
||||
|
||||
@staticmethod
|
||||
def retval(obj, who="who", status=True):
|
||||
"""ret_val"""
|
||||
return ReturnValueConcept.ret(who, status, obj)
|
||||
|
||||
@staticmethod
|
||||
def tretval(sheerka, obj, who="who"):
|
||||
"""True ret_val + add concept in cache"""
|
||||
if isinstance(obj, Concept):
|
||||
obj.init_key()
|
||||
if obj.key not in sheerka.cache_by_key:
|
||||
sheerka.cache_by_key[obj.key] = obj
|
||||
return sheerka.ret(who, True, obj)
|
||||
|
||||
@staticmethod
|
||||
def pretval(concept, source=None, parser="parsers.name"):
|
||||
"""ParserResult ret_val"""
|
||||
return ReturnValueConcept(
|
||||
"some_name",
|
||||
True,
|
||||
ParserResultConcept(parser=parser,
|
||||
source=source or concept.name,
|
||||
value=concept,
|
||||
try_parsed=concept))
|
||||
@@ -0,0 +1,34 @@
|
||||
import os
|
||||
import shutil
|
||||
from os import path
|
||||
|
||||
import pytest
|
||||
from core.sheerka.Sheerka import Sheerka
|
||||
from tests.BaseTest import BaseTest
|
||||
|
||||
|
||||
class TestUsingFileBasedSheerka(BaseTest):
|
||||
|
||||
tests_root = path.abspath("../../build/tests")
|
||||
root_folder = "init_folder"
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def init_test(self):
|
||||
if path.exists(self.tests_root):
|
||||
shutil.rmtree(self.tests_root)
|
||||
|
||||
if not path.exists(self.tests_root):
|
||||
os.makedirs(self.tests_root)
|
||||
current_pwd = os.getcwd()
|
||||
os.chdir(self.tests_root)
|
||||
|
||||
yield None
|
||||
|
||||
os.chdir(current_pwd)
|
||||
|
||||
def get_sheerka(self, use_dict=True, skip_builtins_in_db=True):
|
||||
root = "mem://" if use_dict else self.root_folder
|
||||
sheerka = Sheerka(skip_builtins_in_db=skip_builtins_in_db)
|
||||
sheerka.initialize(root)
|
||||
|
||||
return sheerka
|
||||
@@ -0,0 +1,10 @@
|
||||
from core.sheerka.Sheerka import Sheerka
|
||||
from tests.BaseTest import BaseTest
|
||||
|
||||
|
||||
class TestUsingMemoryBasedSheerka(BaseTest):
|
||||
|
||||
def get_sheerka(self, skip_builtins_in_db=True):
|
||||
sheerka = Sheerka(skip_builtins_in_db=skip_builtins_in_db)
|
||||
sheerka.initialize("mem://")
|
||||
return sheerka
|
||||
@@ -2,7 +2,7 @@ import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import ExecutionContext
|
||||
from core.sheerka.Sheerka import ExecutionContext
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import PROPERTIES_TO_SERIALIZE
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_add_a_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
|
||||
res = sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
concept_found = res.value.body
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_found.metadata, prop) == getattr(concept.metadata, prop)
|
||||
|
||||
assert concept_found.key == "__var__0 + __var__1"
|
||||
assert concept_found.id == "1001"
|
||||
|
||||
assert concept.key in sheerka.cache_by_key
|
||||
assert concept.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_found.get_digest()))
|
||||
|
||||
def test_i_cannot_add_the_same_concept_twice(self):
|
||||
"""
|
||||
Checks that duplicated concepts are managed by sheerka, not by sheerka.sdp
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
res = sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
|
||||
assert res.value.body == concept
|
||||
|
||||
def test_i_can_get_a_newly_created_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
from_cache = sheerka.get(concept.key)
|
||||
assert from_cache is not None
|
||||
assert from_cache == concept
|
||||
|
||||
from_cache = sheerka.get_by_id(concept.id)
|
||||
assert from_cache is not None
|
||||
assert from_cache == concept
|
||||
|
||||
def test_i_first_look_in_local_cache(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
sheerka.cache_by_key[concept.key].pre = "I have modified the concept in cache"
|
||||
|
||||
from_cache = sheerka.get(concept.key)
|
||||
assert from_cache is not None
|
||||
assert from_cache.key == concept.key
|
||||
assert from_cache.pre == "I have modified the concept in cache"
|
||||
|
||||
def test_i_can_get_a_known_concept_when_not_in_cache(self):
|
||||
"""
|
||||
When not in cache, uses sdp
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
loaded = sheerka.get(concept.key)
|
||||
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
# I can also get it by its id
|
||||
loaded = sheerka.sdp.get(sheerka.CONCEPTS_BY_ID_ENTRY, concept.id)
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
def test_i_can_get_a_concept_by_its_id(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
loaded = sheerka.get_by_id(concept.id)
|
||||
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
def test_i_can_get_list_of_concept_when_same_key_when_no_cache(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept1 = self.get_default_concept()
|
||||
concept2 = self.get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(self.get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(self.get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
|
||||
result = sheerka.get(concept1.key)
|
||||
assert len(result) == 2
|
||||
assert result[0] == concept1
|
||||
assert result[1] == concept2
|
||||
|
||||
def test_i_can_get_list_of_concept_when_same_key_when_cache(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept1 = self.get_default_concept()
|
||||
concept2 = self.get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(self.get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(self.get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
# sheerka.cache_by_key = {} # Do not reset the cache
|
||||
|
||||
result = sheerka.get(concept1.key)
|
||||
assert len(result) == 2
|
||||
assert result[0] == concept1
|
||||
assert result[1] == concept2
|
||||
|
||||
def test_i_can_get_the_correct_concept_using_the_id_when_same_key_when_no_cache(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept1 = self.get_default_concept()
|
||||
concept2 = self.get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(self.get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(self.get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
result = sheerka.get(concept1.key, res2.body.body.id)
|
||||
assert result.name == "a + b"
|
||||
assert result.metadata.body == "a+b"
|
||||
|
||||
def test_i_can_get_the_correct_concept_using_the_id__when_same_key_when_cache(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept1 = self.get_default_concept()
|
||||
concept2 = self.get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(self.get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(self.get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
result = sheerka.get(concept1.key, res2.body.body.id)
|
||||
assert result.name == "a + b"
|
||||
assert result.metadata.body == "a+b"
|
||||
|
||||
def test_i_cannot_get_the_correct_concept_id_the_id_is_wrong(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept1 = self.get_default_concept()
|
||||
concept2 = self.get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(self.get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(self.get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
result = sheerka.get(concept1.key, "wrong id")
|
||||
assert sheerka.isinstance(result, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
@@ -0,0 +1,332 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, ParserResultConcept
|
||||
from core.concept import Concept, simplec, DoNotResolve, ConceptParts, Property
|
||||
from parsers.PythonParser import PythonNode
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("body, expected", [
|
||||
# (None, None),
|
||||
# ("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
("'one'", "one"),
|
||||
("'one' + 'two'", "onetwo"),
|
||||
("True", True),
|
||||
("1 > 2", False),
|
||||
])
|
||||
def test_i_can_evaluate_a_concept_with_simple_body(self,body, expected):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept("foo", body=body)
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == expected
|
||||
assert evaluated.metadata.body == body
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.props == {}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert len(evaluated.values) == 0 if body is None else 1
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
("'one'", "one"),
|
||||
("'one' + 'two'", "onetwo"),
|
||||
("True", True),
|
||||
("1 > 2", False),
|
||||
])
|
||||
def test_i_can_evaluate_the_other_metadata(self,expr, expected):
|
||||
"""
|
||||
I only test WHERE, it's the same for the others
|
||||
:param expr:
|
||||
:param expected:
|
||||
:return:
|
||||
"""
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept("foo", where=expr)
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.metadata.body is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where == expr
|
||||
assert evaluated.get_metadata_value(ConceptParts.WHERE) == expected
|
||||
assert evaluated.props == {}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert len(evaluated.values) == 0 if expr is None else 1
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
(None, None),
|
||||
("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
("'one'", "one"),
|
||||
("'one' + 'two'", "onetwo"),
|
||||
("True", True),
|
||||
("1 > 2", False),
|
||||
])
|
||||
def test_i_can_evaluate_a_concept_with_prop(self, expr, expected):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept("foo").def_prop("a", expr)
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.props == {"a": Property("a", expected)}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
def test_i_can_evaluate_metadata_using_do_not_resolve(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept("foo")
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
def test_i_can_evaluate_property_using_do_not_resolve(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept("foo").def_prop("a")
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.get_prop("a") == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
def test_original_value_is_overridden_when_using_do_no_resolve(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept("foo", body="original value").set_prop("a", "original value")
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.get_prop("a") == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
def test_props_are_evaluated_before_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept("foo", body="a+1").def_prop("a", "10").init_key()
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 11
|
||||
|
||||
def test_i_can_evaluate_when_another_concept_is_referenced(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = Concept("a")
|
||||
sheerka.add_in_cache(concept_a)
|
||||
|
||||
concept = Concept("foo", body="a").init_key()
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated == simplec("foo", simplec("a", None))
|
||||
assert id(evaluated.body) != id(concept_a)
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.body.metadata.is_evaluated
|
||||
|
||||
def test_i_can_evaluate_when_the_referenced_concept_has_a_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = Concept("a", body="1")
|
||||
sheerka.add_in_cache(concept_a)
|
||||
|
||||
concept = Concept("foo", body="a")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == simplec("a", 1)
|
||||
assert not concept_a.metadata.is_evaluated
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
def test_i_can_evaluate_concept_of_concept_when_the_leaf_has_a_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="'a'"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="a"))
|
||||
sheerka.add_in_cache(Concept(name="c", body="b"))
|
||||
concept_d = sheerka.add_in_cache(Concept(name="d", body="c"))
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d)
|
||||
|
||||
assert evaluated.key == concept_d.key
|
||||
expected = simplec("c", simplec("b", simplec("a", "a")))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.value(evaluated) == 'a'
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
def test_i_can_evaluate_concept_of_concept_does_not_have_a_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="a"))
|
||||
sheerka.add_in_cache(Concept(name="c", body="b"))
|
||||
concept_d = sheerka.add_in_cache(Concept(name="d", body="c"))
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d)
|
||||
|
||||
assert evaluated.key == concept_d.key
|
||||
expected = simplec("c", simplec("b", simplec("a", None)))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.value(evaluated) == Concept(name="a").init_key()
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_reference_others_concepts(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a").init_key())
|
||||
|
||||
concept = Concept("foo", body="a").def_prop("a", "a").init_key()
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
# first prop a is evaluated to concept_a
|
||||
# then body is evaluated to prop a -> concept_a
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == concept_a
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_reference_others_concepts_2(self):
|
||||
"""
|
||||
Same test,
|
||||
but the name of the property and the name of the concept are different
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a"))
|
||||
|
||||
concept = Concept("foo", body="concept_a").def_prop("concept_a", "a")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == concept_a
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_reference_others_concepts_with_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="1"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="2"))
|
||||
|
||||
concept = Concept("foo", body="propA + propB").def_prop("propA", "a").def_prop("propB", "b")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_is_a_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a", body="'a'").init_key())
|
||||
|
||||
concept = Concept("foo").def_prop("a")
|
||||
concept.compiled["a"] = concept_a
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.get_prop("a") == simplec("a", "a")
|
||||
|
||||
def test_i_can_evaluate_when_property_asts_is_a_list(self):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Concept("foo", body="1")
|
||||
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = [foo, DoNotResolve("1")]
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
props = evaluated.get_prop("prop")
|
||||
assert len(props) == 2
|
||||
assert props[0] == simplec("foo", 1)
|
||||
assert props[1] == "1"
|
||||
|
||||
def test_i_can_evaluate_when_compiled_is_set_up_with_return_value(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
python_node = PythonNode("1 +1 ")
|
||||
parser_result = ParserResultConcept(parser="who", value=python_node)
|
||||
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = [ReturnValueConcept("who", True, parser_result)]
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert evaluated.get_prop("prop") == 2
|
||||
|
||||
# also works when only one return value
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = ReturnValueConcept("who", True, parser_result)
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert evaluated.get_prop("prop") == 2
|
||||
|
||||
def test_i_can_reference_sheerka(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept("foo", body="sheerka.test()").init_key()
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == sheerka.test()
|
||||
|
||||
def test_properties_values_takes_precedence_over_the_outside_world(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="'concept_a'"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="'concept_b'"))
|
||||
|
||||
concept = Concept("foo", body="a")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == simplec("a", "concept_a") # this test was already done
|
||||
|
||||
# so check this one.
|
||||
concept = Concept("foo", body="a").def_prop("a", "'property_a'")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 'property_a'
|
||||
|
||||
# or this one.
|
||||
concept = Concept("foo", body="a").def_prop("a", "b")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == simplec(name="b", body="concept_b")
|
||||
|
||||
def test_properties_values_takes_precedence(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="'concept_a'"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="'concept_b'"))
|
||||
|
||||
concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 'prop_aconcept_b'
|
||||
|
||||
def test_i_can_reference_sub_property_of_a_property(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="concept_a").def_prop("subProp", "'sub_a'"))
|
||||
|
||||
concept = Concept("foo", body="a.props['subProp'].value").def_prop("a", "concept_a")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert evaluated == simplec(concept.key, "sub_a")
|
||||
|
||||
def test_i_cannot_evaluate_concept_if_property_is_in_error(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept(name="concept_a").def_prop("subProp", "undef_concept")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
|
||||
def test_key_is_initialized_by_evaluation(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept("foo")
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.init_key().key
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
import os
|
||||
import shutil
|
||||
from os import path
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import ConceptAlreadyInSet, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
|
||||
|
||||
|
||||
|
||||
def test_i_can_add_concept_to_set(self):
|
||||
sheerka = self.get_sheerka(False, False)
|
||||
|
||||
foo = Concept("foo")
|
||||
sheerka.set_id_if_needed(foo, False)
|
||||
|
||||
all_foos = Concept("all_foos")
|
||||
sheerka.set_id_if_needed(all_foos, False)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
res = sheerka.add_concept_to_set(context, foo, all_foos)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
all_entries = self.get_sheerka(False, False).sdp.get("All_" + all_foos.id, None, False)
|
||||
assert len(all_entries) == 1
|
||||
assert foo.id in all_entries
|
||||
|
||||
def test_i_can_add_several_concepts_to_set(self):
|
||||
sheerka = self.get_sheerka(False, False)
|
||||
|
||||
foo1 = Concept("foo1")
|
||||
sheerka.set_id_if_needed(foo1, False)
|
||||
|
||||
foo2 = Concept("foo1")
|
||||
sheerka.set_id_if_needed(foo2, False)
|
||||
|
||||
all_foos = Concept("all_foos")
|
||||
sheerka.set_id_if_needed(all_foos, False)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
sheerka.add_concept_to_set(context, foo1, all_foos)
|
||||
res = sheerka.add_concept_to_set(context, foo2, all_foos)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
all_entries = self.get_sheerka(False, False).sdp.get("All_" + all_foos.id, None, False)
|
||||
assert len(all_entries) == 2
|
||||
assert foo1.id in all_entries
|
||||
assert foo2.id in all_entries
|
||||
|
||||
def test_i_cannot_add_the_same_concept_twice_in_a_set(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
foo = Concept("foo")
|
||||
sheerka.set_id_if_needed(foo, False)
|
||||
|
||||
all_foos = Concept("all_foos")
|
||||
sheerka.set_id_if_needed(all_foos, False)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
sheerka.add_concept_to_set(context, foo, all_foos)
|
||||
res = sheerka.add_concept_to_set(context, foo, all_foos)
|
||||
|
||||
assert not res.status
|
||||
assert res.body == ConceptAlreadyInSet(foo, all_foos)
|
||||
|
||||
all_entries = sheerka.sdp.get("All_" + all_foos.id, None, False)
|
||||
assert len(all_entries) == 1
|
||||
assert foo.id in all_entries
|
||||
|
||||
def test_i_get_elements_from_a_set(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
one = Concept("one")
|
||||
two = Concept("two")
|
||||
three = Concept("three")
|
||||
number = Concept("number")
|
||||
|
||||
for c in [one, two, three, number]:
|
||||
sheerka.set_id_if_needed(c, False)
|
||||
sheerka.add_in_cache(c)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
for c in [one, two, three]:
|
||||
sheerka.add_concept_to_set(context, c, number)
|
||||
|
||||
elements = sheerka.get_set_elements(number)
|
||||
|
||||
assert set(elements) == {one, two, three}
|
||||
|
||||
def test_i_cannot_get_elements_if_not_a_set(self):
|
||||
sheerka = self.get_sheerka()
|
||||
one = Concept("one")
|
||||
sheerka.set_id_if_needed(one, False)
|
||||
sheerka.add_in_cache(one)
|
||||
|
||||
error = sheerka.get_set_elements(one)
|
||||
|
||||
assert sheerka.isinstance(error, BuiltinConcepts.NOT_A_SET)
|
||||
assert error.body == one
|
||||
|
||||
def test_isa_and_isa_group(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
group = Concept("group").init_key()
|
||||
group.metadata.id = "1001"
|
||||
assert not sheerka.isagroup(group)
|
||||
|
||||
foo = Concept("foo").init_key()
|
||||
foo.metadata.id = "1002"
|
||||
assert not sheerka.isa(foo, group)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
sheerka.add_concept_to_set(context, foo, group)
|
||||
assert sheerka.isagroup(group)
|
||||
assert sheerka.isa(foo, group)
|
||||
@@ -6,7 +6,7 @@ from core.ast.nodes import NodeParent, GenericNodeConcept
|
||||
import core.ast.nodes
|
||||
from core.ast.visitors import ConceptNodeVisitor, UnreferencedNamesVisitor
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.sheerka import Sheerka
|
||||
from core.sheerka.Sheerka import Sheerka
|
||||
|
||||
|
||||
def get_sheerka():
|
||||
@@ -0,0 +1,145 @@
|
||||
import ast
|
||||
import pytest
|
||||
import core.builtin_helpers
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestBuiltinHelpers(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_use_expect_one_when_empty(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), [])
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.IS_EMPTY)
|
||||
|
||||
def test_i_can_use_expect_one_when_too_many_success(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", True, "value1"),
|
||||
ReturnValueConcept("who", True, "value2"),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), items)
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||
assert res.value.body == items
|
||||
assert res.parents == items
|
||||
|
||||
def test_i_can_use_expect_one_when_same_success(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", True, "value"),
|
||||
ReturnValueConcept("who", True, "value"),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), items)
|
||||
assert res.status
|
||||
assert res.value == items[0].value
|
||||
assert res.parents == items
|
||||
|
||||
def test_i_can_use_expect_when_only_errors_1(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", False, sheerka.new(BuiltinConcepts.ERROR)),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), items)
|
||||
assert not res.status
|
||||
assert res.value, items[0]
|
||||
assert res.parents == items
|
||||
|
||||
def test_i_can_use_expect_when_only_errors_2(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", False, None),
|
||||
ReturnValueConcept("who", False, None),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), items)
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
assert res.value.body == items
|
||||
assert res.parents == items
|
||||
|
||||
def test_i_can_use_expect_one_when_one_success_1(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", True, None),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), items)
|
||||
assert res.status
|
||||
assert res.body == items[0].body
|
||||
assert res.parents == items
|
||||
|
||||
def test_i_can_use_expect_one_when_one_success_2(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", False, None),
|
||||
ReturnValueConcept("who", True, None),
|
||||
ReturnValueConcept("who", False, None),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), items)
|
||||
assert res.status
|
||||
assert res.body == items[1].body
|
||||
assert res.parents == items
|
||||
|
||||
def test_i_can_use_expect_one_when_not_a_list_true(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
item = ReturnValueConcept("who", True, None)
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), item)
|
||||
assert res.status
|
||||
assert res == item
|
||||
|
||||
def test_i_can_use_expect_one_when_not_a_list_false(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
item = ReturnValueConcept("who", False, None)
|
||||
res = core.builtin_helpers.expect_one(self.get_context(sheerka), item)
|
||||
|
||||
assert not res.status
|
||||
assert res == item
|
||||
|
||||
@pytest.mark.parametrize("expression, vars_to_include, vars_to_exclude, expected_expr", [
|
||||
("a == 1", [], [], []),
|
||||
("a == 1", ["a"], [], ["a == 1"]),
|
||||
("a == 1", [], ["a"], []),
|
||||
("predicate(a)", [], [], []),
|
||||
("predicate(a)", ["a"], [], ["predicate(a)"]),
|
||||
("predicate(a, b)", ["a"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["b"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["a", "b"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["a"], ["b"], []),
|
||||
("a + b == 1", [], [], []),
|
||||
("a + b == 1", ["a"], [], ["a + b == 1"]),
|
||||
("a + b == 1", ["a"], ["b"], []),
|
||||
("a + b == 1", ["b"], [], ["a + b == 1"]),
|
||||
("a + b == 1", ["a", "b"], [], ["a + b == 1"]),
|
||||
("a == 1 and b == 2", [], [], []),
|
||||
("a == 1 and b == 2", ["a"], [], ["a == 1"]),
|
||||
("a == 1 and b == 2", ["b"], [], ["b == 2"]),
|
||||
("a == 1 and b == 2", ["a"], ["b"], ["a == 1"]),
|
||||
("a == 1 and b == 2", ["a", "b"], [], ["a == 1 and b == 2"]),
|
||||
("predicate(a,c) and predicate(b,c)", ["a", "b"], [], ["predicate(a,c) and predicate(b,c)"]),
|
||||
("not(a == 1)", [], [], []),
|
||||
("not(a == 1)", ["a"], [], ["not(a==1)"]),
|
||||
("a == 1 or b == 2", [], [], []),
|
||||
("a == 1 or b == 2", ["a"], [], ["a == 1"]),
|
||||
("a == 1 or b == 2", ["b"], [], ["b == 2"]),
|
||||
("a == 1 or b == 2", ["a", "b"], [], ["a == 1 or b == 2"]),
|
||||
("predicate(a,c) or predicate(b,c)", ["a", "b"], [], ["predicate(a,c) or predicate(b,c)"]),
|
||||
])
|
||||
def test_i_can_extract_predicates(self, expression, vars_to_include, vars_to_exclude, expected_expr):
|
||||
sheerka = self.get_sheerka()
|
||||
expected = [ast.parse(expr, mode="eval") for expr in expected_expr]
|
||||
|
||||
actual = core.builtin_helpers.extract_predicates(sheerka, expression, vars_to_include, vars_to_exclude)
|
||||
assert len(actual) == len(expected)
|
||||
for i in range(len(actual)):
|
||||
assert self.dump_ast(actual[i]) == self.dump_ast(expected[i])
|
||||
@@ -0,0 +1,244 @@
|
||||
import pytest
|
||||
import os
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE
|
||||
from core.sheerka.Sheerka import Sheerka
|
||||
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
|
||||
|
||||
class ConceptWithGetValue(Concept):
|
||||
def get_value(self):
|
||||
return self.get_prop("my_prop")
|
||||
|
||||
|
||||
class TestSheerka(TestUsingFileBasedSheerka):
|
||||
|
||||
def test_root_folder_is_created_after_initialization(self):
|
||||
return_value = Sheerka().initialize(self.root_folder)
|
||||
assert return_value.status, "initialisation should be successful"
|
||||
assert os.path.exists(self.root_folder), "init folder should be created"
|
||||
|
||||
def test_i_can_list_builtin_concepts(self):
|
||||
sheerka = self.get_sheerka()
|
||||
builtins = list(sheerka.get_builtins_classes_as_dict())
|
||||
|
||||
assert str(BuiltinConcepts.ERROR) in builtins
|
||||
assert str(BuiltinConcepts.RETURN_VALUE) in builtins
|
||||
|
||||
def test_builtin_concepts_are_initialized(self):
|
||||
sheerka = self.get_sheerka(skip_builtins_in_db=False)
|
||||
assert len(sheerka.cache_by_key) == len(BuiltinConcepts)
|
||||
for concept_name in BuiltinConcepts:
|
||||
assert str(concept_name) in sheerka.cache_by_key
|
||||
assert sheerka.sdp.get_safe(sheerka.CONCEPTS_ENTRY, str(concept_name)) is not None
|
||||
|
||||
for key, concept_class in sheerka.get_builtins_classes_as_dict().items():
|
||||
assert isinstance(sheerka.cache_by_key[key], concept_class)
|
||||
|
||||
def test_builtin_concepts_can_be_updated(self):
|
||||
sheerka = self.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 = self.get_sheerka(False, False)
|
||||
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
||||
|
||||
assert loaded_sheerka.metadata.desc == "I have a description"
|
||||
|
||||
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' )
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
for key in sheerka.get_builtins_classes_as_dict():
|
||||
assert sheerka.get(key) is not None
|
||||
assert sheerka.get(str(key)) is not None
|
||||
|
||||
def test_i_cannot_get_when_key_is_none(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
res = sheerka.get(None)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.ERROR)
|
||||
assert res.body == "Concept key is undefined."
|
||||
|
||||
def test_unknown_concept_is_return_when_the_concept_key_is_not_found(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
loaded = sheerka.get("key_that_does_not_exist")
|
||||
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == ("key", "key_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
|
||||
def test_unknown_concept_is_return_when_the_concept_id_is_not_found(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
loaded = sheerka.get_by_id("id_that_does_not_exist")
|
||||
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == ("id", "id_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
|
||||
def test_i_can_instantiate_a_builtin_concept_when_it_has_its_own_class(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ret = sheerka.new(BuiltinConcepts.RETURN_VALUE, who="who", status="status", value="value", message="message")
|
||||
|
||||
assert isinstance(ret, ReturnValueConcept)
|
||||
assert ret.key == str(BuiltinConcepts.RETURN_VALUE)
|
||||
assert ret.who == "who"
|
||||
assert ret.status == "status"
|
||||
assert ret.value == "value"
|
||||
assert ret.message == "message"
|
||||
|
||||
def test_i_can_instantiate_a_builtin_concept_when_no_specific_class(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ret = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body="fake_concept")
|
||||
|
||||
assert isinstance(ret, Concept)
|
||||
assert ret.key == str(BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert ret.body == "fake_concept"
|
||||
|
||||
def test_i_can_instantiate_a_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
new = sheerka.new(concept.key, a=10, b="value")
|
||||
|
||||
assert sheerka.isinstance(new, concept)
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(new.metadata, prop) == getattr(concept.metadata, prop)
|
||||
|
||||
assert new.props["a"].value == 10
|
||||
assert new.props["b"].value == "value"
|
||||
|
||||
def test_i_can_instantiate_with_the_name_and_the_id(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
||||
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo2"))
|
||||
|
||||
concepts = sheerka.new("foo")
|
||||
assert len(concepts) == 2
|
||||
|
||||
foo1 = sheerka.new(("foo", "1001"))
|
||||
assert foo1.metadata.body == "foo1"
|
||||
|
||||
foo2 = sheerka.new(("foo", "1002"))
|
||||
assert foo2.metadata.body == "foo2"
|
||||
|
||||
def test_instances_are_different_when_asking_for_new(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
new1 = sheerka.new(concept.key, a=10, b="value")
|
||||
new2 = sheerka.new(concept.key, a=10, b="value")
|
||||
|
||||
assert new1 == new2
|
||||
assert id(new1) != id(new2)
|
||||
|
||||
def test_i_get_the_same_instance_when_is_unique_is_true(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept(name="unique", is_unique=True)
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
new1 = sheerka.new(concept.key, a=10, b="value")
|
||||
new2 = sheerka.new(concept.key, a=10, b="value")
|
||||
|
||||
assert new1 == new2
|
||||
assert id(new1) == id(new2)
|
||||
|
||||
def test_i_cannot_instantiate_an_unknown_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
new = sheerka.new("fake_concept")
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == ('key', 'fake_concept')
|
||||
|
||||
def test_i_cannot_instantiate_with_invalid_id(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
||||
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo2"))
|
||||
|
||||
new = sheerka.new(("foo", "invalid_id"))
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == [('key', 'foo'), ('id', 'invalid_id')]
|
||||
|
||||
def test_i_cannot_instantiate_with_invalid_key(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
||||
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo2"))
|
||||
|
||||
new = sheerka.new(("invalid_key", "1001"))
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == [('key', 'invalid_key'), ('id', '1001')]
|
||||
|
||||
def test_concept_id_is_irrelevant_when_only_one_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
||||
|
||||
new = sheerka.new(("foo", "invalid_id"))
|
||||
|
||||
assert sheerka.isinstance(new, "foo")
|
||||
assert new.metadata.body == "foo1"
|
||||
|
||||
def test_i_cannot_instantiate_when_properties_are_not_recognized(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = self.get_default_concept()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
new = sheerka.new(concept.key, a=10, c="value")
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_PROPERTY)
|
||||
assert new.property_name == "c"
|
||||
assert sheerka.isinstance(new.concept, concept)
|
||||
|
||||
@pytest.mark.parametrize("concept, reduce_simple_list, expected", [
|
||||
(None, False, None),
|
||||
(3.14, False, 3.14),
|
||||
("foo", False, "foo"),
|
||||
(True, False, True),
|
||||
(Concept("name", body="foo"), False, "foo"),
|
||||
(Concept("name"), False, Concept("name")),
|
||||
(ConceptWithGetValue("name").set_prop("my_prop", "my_value"), False, "my_value"),
|
||||
(ReturnValueConcept(value="return_value"), False, "return_value"),
|
||||
(ReturnValueConcept(value=Concept(key=BuiltinConcepts.USER_INPUT, body="text"), status=True), False, "text"),
|
||||
(ReturnValueConcept(value=UserInputConcept("text"), status=True), False, "text"),
|
||||
(Concept("name", body=["foo", "bar"]), False, ["foo", "bar"]),
|
||||
(Concept("name", body=["foo"]), True, "foo"),
|
||||
(Concept("name", body=Concept("foo")), False, Concept("foo")),
|
||||
(Concept("name", body=Concept("foo", body="value")), False, "value"),
|
||||
(Concept("name", body=Concept("foo", body=Concept("bar", body="value"))), False, "value"),
|
||||
(Concept("name", body=Concept("foo", body=ReturnValueConcept(value="return_value"))), False, "return_value"),
|
||||
])
|
||||
def test_i_can_get_value(self, concept, reduce_simple_list, expected):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
# I use auto_init() instead of evaluate_concept() to be quicker
|
||||
c = concept
|
||||
while isinstance(c, Concept):
|
||||
c.auto_init()
|
||||
c = c.body
|
||||
|
||||
assert sheerka.value(concept, reduce_simple_list) == expected
|
||||
|
||||
def test_list_of_concept_is_sorted_by_id(self):
|
||||
sheerka = self.get_sheerka(False, False)
|
||||
concepts = sheerka.concepts()
|
||||
|
||||
assert concepts[0].id < concepts[-1].id
|
||||
|
||||
def test_builtin_error_concept_are_errors(self):
|
||||
# only test a random one, it will be the same for the others
|
||||
sheerka = self.get_sheerka()
|
||||
assert not sheerka.is_success(sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS))
|
||||
@@ -0,0 +1,375 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator, BaseEvaluator, AllReturnValuesEvaluator
|
||||
|
||||
from tests.BaseTest import BaseTest
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class Out:
|
||||
debug_out = []
|
||||
|
||||
def out(self, method, name, context, return_value):
|
||||
name = name[len(BaseEvaluator.PREFIX):]
|
||||
if isinstance(return_value, list):
|
||||
target = [str(r.body.key) for r in return_value]
|
||||
else:
|
||||
target = str(return_value.body.key)
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
text += f"{name} - {method} - target={target}"
|
||||
self.debug_out.append(text)
|
||||
|
||||
def out_all(self, method, name, context, return_values):
|
||||
name = name[len(BaseEvaluator.PREFIX):]
|
||||
target = [str(r.body.key) for r in return_values]
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
text += f"{name} - {method} - target={target}"
|
||||
self.debug_out.append(text)
|
||||
|
||||
|
||||
class OneReturnValueEvaluatorForTestingPurpose(OneReturnValueEvaluator, Out):
|
||||
def __init__(self, name, steps, priority):
|
||||
super().__init__(name, steps, priority)
|
||||
|
||||
def matches(self, context, return_value):
|
||||
self.out("matches", self.name, context, return_value)
|
||||
return True
|
||||
|
||||
def eval(self, context, return_value):
|
||||
self.out("eval", self.name, context, return_value)
|
||||
|
||||
|
||||
class AllReturnValueEvaluatorForTestingPurpose(AllReturnValuesEvaluator, Out):
|
||||
def __init__(self, name, steps, priority):
|
||||
super().__init__(name, steps, priority)
|
||||
|
||||
def matches(self, context, return_values):
|
||||
self.out("matches", self.name, context, return_values)
|
||||
return True
|
||||
|
||||
def eval(self, context, return_values):
|
||||
self.out("eval", self.name, context, return_values)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority(OneReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self, name, priority):
|
||||
super().__init__(name, [BuiltinConcepts.EVALUATION], priority)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority10(EvaluatorOneWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority10", 10)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority15(EvaluatorOneWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority15", 15)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority20(EvaluatorOneWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority20", 20)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority(AllReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self, name, priority):
|
||||
super().__init__(name, [BuiltinConcepts.EVALUATION], priority)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority10(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_priority10", 10)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority15(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_priority15", 15)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority20(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_priority20", 20)
|
||||
|
||||
|
||||
class EvaluatorOneModifyFoo(EvaluatorOneWithPriority):
|
||||
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 BaseTest.tretval(context.sheerka, Concept("bar"))
|
||||
|
||||
|
||||
class EvaluatorOneModifyBar(EvaluatorOneWithPriority):
|
||||
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 BaseTest.tretval(context.sheerka, Concept("baz"))
|
||||
|
||||
|
||||
class EvaluatorOnePreEvaluation(OneReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self):
|
||||
super().__init__("preEval", [BuiltinConcepts.BEFORE_EVALUATION], 10)
|
||||
|
||||
|
||||
class EvaluatorOneMultiSteps(OneReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self):
|
||||
super().__init__("multiStep", [BuiltinConcepts.EVALUATION, BuiltinConcepts.BEFORE_EVALUATION], 10)
|
||||
|
||||
|
||||
class EvaluatorAllReduceFooBar(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_reduce_foobar", 10)
|
||||
|
||||
def matches(self, context, return_values):
|
||||
super().matches(context, return_values)
|
||||
keys = [c.body.key for c in return_values]
|
||||
return "foo" in keys and "bar" in keys
|
||||
|
||||
def eval(self, context, return_values):
|
||||
super().eval(context, return_values)
|
||||
ret = BaseTest.tretval(context.sheerka, context.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||
ret.parents = return_values
|
||||
return ret
|
||||
|
||||
|
||||
class EvaluatorAllSuppressFooEntry(EvaluatorAllWithPriority):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("suppress", 100)
|
||||
|
||||
def matches(self, context, return_values):
|
||||
super().matches(context, return_values)
|
||||
return True
|
||||
|
||||
def eval(self, context, return_values):
|
||||
super().eval(context, return_values)
|
||||
foo = None
|
||||
for ret in return_values:
|
||||
if ret.body.name == "foo":
|
||||
foo = ret
|
||||
|
||||
if foo:
|
||||
return context.sheerka.ret(self.name, False, Concept("does not matter"), parents=[foo])
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_that_return_values_is_unchanged_when_no_evaluator(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = []
|
||||
|
||||
entries = self.tretval(sheerka, Concept("foo"))
|
||||
return_values = sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert return_values == [entries]
|
||||
|
||||
def test_i_can_use_a_list_as_input(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = []
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
return_values = sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert return_values == entries
|
||||
|
||||
def test_step_concept_is_removed_after_processing_if_not_reduced(self):
|
||||
"""
|
||||
No evaluator
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = []
|
||||
|
||||
entry = self.tretval(sheerka, Concept("foo"))
|
||||
return_values = sheerka.execute(self.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(self):
|
||||
"""
|
||||
This time the entry is modified by an evaluator,
|
||||
nevertheless, step concept is removed
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
|
||||
entry = self.tretval(sheerka, Concept("foo"))
|
||||
return_values = sheerka.execute(self.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(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [
|
||||
EvaluatorAllWithPriority10,
|
||||
EvaluatorOneWithPriority20,
|
||||
EvaluatorAllWithPriority15,
|
||||
EvaluatorOneWithPriority10,
|
||||
EvaluatorOneWithPriority15,
|
||||
EvaluatorAllWithPriority20, ]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_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] all_priority20 - matches - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority20 - eval - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority15 - matches - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority15 - eval - target=['foo', '__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] all_priority10 - matches - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority10 - eval - target=['foo', '__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_for_one_return(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo")), self.tretval(sheerka, Concept("baz"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_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_that_predicate_is_checked_before_evaluation_for_all_return(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorAllReduceFooBar]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo")), self.tretval(sheerka, Concept("bar"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
"__EVALUATION [0] all_reduce_foobar - matches - target=['foo', 'bar', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_reduce_foobar - eval - target=['foo', 'bar', '__EVALUATION']",
|
||||
"__EVALUATION [1] all_reduce_foobar - matches - target=['__SUCCESS']"
|
||||
]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
"__EVALUATION [0] all_reduce_foobar - matches - target=['foo', '__EVALUATION']"
|
||||
]
|
||||
|
||||
def test_evaluation_continue_until_no_more_modification(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo, EvaluatorOneModifyBar]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo")), self.tretval(sheerka, Concept("baz"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_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'
|
||||
]
|
||||
|
||||
def test_evaluation_steps_are_respected(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneWithPriority10, EvaluatorOnePreEvaluation]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.BEFORE_EVALUATION])
|
||||
|
||||
assert Out.debug_out == [
|
||||
'__BEFORE_EVALUATION [0] preEval - matches - target=foo',
|
||||
'__BEFORE_EVALUATION [0] preEval - eval - target=foo',
|
||||
'__BEFORE_EVALUATION [0] preEval - matches - target=__BEFORE_EVALUATION',
|
||||
'__BEFORE_EVALUATION [0] preEval - eval - target=__BEFORE_EVALUATION']
|
||||
|
||||
def test_evaluation_multi_steps_are_respected(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneMultiSteps]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries,
|
||||
[BuiltinConcepts.BEFORE_EVALUATION, BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_out == [
|
||||
'__BEFORE_EVALUATION [0] multiStep - matches - target=foo',
|
||||
'__BEFORE_EVALUATION [0] multiStep - eval - target=foo',
|
||||
'__BEFORE_EVALUATION [0] multiStep - matches - target=__BEFORE_EVALUATION',
|
||||
'__BEFORE_EVALUATION [0] multiStep - eval - target=__BEFORE_EVALUATION',
|
||||
'__EVALUATION [0] multiStep - matches - target=foo',
|
||||
'__EVALUATION [0] multiStep - eval - target=foo',
|
||||
'__EVALUATION [0] multiStep - matches - target=__EVALUATION',
|
||||
'__EVALUATION [0] multiStep - eval - target=__EVALUATION'
|
||||
]
|
||||
|
||||
def test_evaluators_can_be_pre_processed(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
|
||||
# disable evaluator
|
||||
context = self.get_context(sheerka)
|
||||
context.add_preprocess(EvaluatorOneModifyFoo().name, enabled=False) # disabled for this exec context
|
||||
Out.debug_out = []
|
||||
sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == []
|
||||
|
||||
# other contextes are not impacted
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
'__EVALUATION [0] modifyFoo - matches - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - eval - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - matches - target=__EVALUATION',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=bar',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=__EVALUATION'
|
||||
]
|
||||
@@ -0,0 +1,363 @@
|
||||
from core.builtin_concepts import ReturnValueConcept, UserInputConcept, BuiltinConcepts, ParserResultConcept
|
||||
from parsers.BaseParser import BaseParser
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def get_ret_val(text, who="who"):
|
||||
return ReturnValueConcept(who, True, UserInputConcept(text, "user_name"))
|
||||
|
||||
|
||||
class BaseTestParser(BaseParser):
|
||||
debug_out = []
|
||||
|
||||
def __init__(self, name, priority, status=None, parser_result=None):
|
||||
super().__init__(name, priority)
|
||||
self.status = status
|
||||
self.parser_result = parser_result
|
||||
|
||||
@staticmethod
|
||||
def _get_name(name):
|
||||
return name[8:] if name.startswith("parsers.") else name
|
||||
|
||||
@staticmethod
|
||||
def _get_source(text_):
|
||||
return text_ if isinstance(text_, str) else text_.body
|
||||
|
||||
def _out(self, name, priority, status, source):
|
||||
debug = f"name={name}"
|
||||
debug += f", priority={priority}"
|
||||
debug += f", status={status}"
|
||||
debug += f", source={source}"
|
||||
self.debug_out.append(debug)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
value = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body)
|
||||
parser_result = ParserResultConcept(parser=self, value=value)
|
||||
return ReturnValueConcept(self, self.status, self.parser_result or parser_result)
|
||||
|
||||
|
||||
class Enabled90FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled90False", 90, False)
|
||||
|
||||
|
||||
class Enabled80FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled80False", 80, False)
|
||||
|
||||
|
||||
class Enabled80MultipleFalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled80MultipleFalse", 80, False)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
value1 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_1"
|
||||
value2 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_2"
|
||||
return [
|
||||
ReturnValueConcept(self, self.status, ParserResultConcept(parser=self, value=value1)),
|
||||
ReturnValueConcept(self, self.status, ParserResultConcept(parser=self, value=value2)),
|
||||
]
|
||||
|
||||
|
||||
class Enabled80MultipleTrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled80MultipleTrue", 80)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
value1 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_1"
|
||||
value2 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_2"
|
||||
return [
|
||||
ReturnValueConcept(self, True, ParserResultConcept(parser=self, value=value1)),
|
||||
ReturnValueConcept(self, False, ParserResultConcept(parser=self, value=value2)),
|
||||
]
|
||||
|
||||
|
||||
class Enabled70FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled70False", 70, False, "Not a ParserResult")
|
||||
|
||||
|
||||
class Enabled50TrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled50True", 50, True)
|
||||
|
||||
def parse(self, context, text):
|
||||
source = self._get_source(text)
|
||||
status = isinstance(text, ParserResultConcept) and source == "Enabled80False:Enabled90False:hello world"
|
||||
self._out(self._get_name(self.name), self.priority, status, source)
|
||||
|
||||
value = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body)
|
||||
return_value = ParserResultConcept(parser=self, value=value)
|
||||
return ReturnValueConcept(self, status, return_value)
|
||||
|
||||
|
||||
class Enabled50bisTrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled50BisTrue", 50, True)
|
||||
|
||||
|
||||
class Enabled50FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled50False", 50, False)
|
||||
|
||||
|
||||
class Enabled10TrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled10True", 10, True)
|
||||
|
||||
|
||||
class DisabledParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Disabled", 90, True)
|
||||
self.enabled = False
|
||||
|
||||
|
||||
class NoneParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("None", 90, True, None)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
return None
|
||||
|
||||
|
||||
class ListOfNoneParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("ListOfNone", 90, True, None)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
return [None, None]
|
||||
|
||||
|
||||
class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_disabled_parsers_are_not_executed(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled": Enabled10TrueParser,
|
||||
"Disabled": DisabledParser
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == ['name=Enabled10True, priority=10, status=True, source=hello world']
|
||||
|
||||
def test_parser_are_executed_by_priority(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled90False, priority=90, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=True, source=Enabled80False:Enabled90False:hello world',
|
||||
]
|
||||
|
||||
def test_parsing_stop_at_the_first_success(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50bisTrue": Enabled50bisTrueParser,
|
||||
"Enabled10True": Enabled10TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled50BisTrue, priority=50, status=True, source=hello world',
|
||||
]
|
||||
|
||||
def test_parsing_stop_at_the_first_success_2(self):
|
||||
"""
|
||||
Same test than before, but Enabled50True takes more time to find a match
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
"Enabled10True": Enabled10TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled90False, priority=90, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=True, source=Enabled80False:Enabled90False:hello world',
|
||||
]
|
||||
|
||||
def test_all_parsers_of_a_given_priority_are_executed(self):
|
||||
"""
|
||||
Make sure that all parsers with priority 50 are executed
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
"Enabled50bisTrue": Enabled50bisTrueParser,
|
||||
"Enabled50False": Enabled50FalseParser,
|
||||
"Enabled10True": Enabled10TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled90False, priority=90, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=True, source=Enabled80False:Enabled90False:hello world',
|
||||
'name=Enabled50BisTrue, priority=50, status=True, source=hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=Enabled80False:Enabled90False:hello world',
|
||||
]
|
||||
|
||||
def test_a_parser_has_access_to_the_output_of_its_predecessors(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
res_as_tuple = [(str(r.who)[8:], r.status, r.body.body) for r in res]
|
||||
assert res_as_tuple == [
|
||||
('Enabled90False', False, 'Enabled90False:hello world'),
|
||||
('Enabled80False', False, 'Enabled80False:hello world'),
|
||||
('Enabled80False', False, 'Enabled80False:Enabled90False:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled90False:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled80False:hello world'),
|
||||
('Enabled50True', True, 'Enabled50True:Enabled80False:Enabled90False:hello world'),
|
||||
]
|
||||
|
||||
def test_none_return_values_are_discarded(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"NoneParser": NoneParser,
|
||||
"ListOfNone": ListOfNoneParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
assert res == []
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=None, priority=90, status=True, source=hello world',
|
||||
'name=ListOfNone, priority=90, status=True, source=hello world'
|
||||
]
|
||||
|
||||
def test_following_priorities_can_only_see_parser_result_return_values(self):
|
||||
"""
|
||||
Normally, lower priority parsers can see the result of the higher priority parsers
|
||||
This is true only if the higher priority parser return a ParserResultConcept
|
||||
:return:
|
||||
"""
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled70False": Enabled70FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled70False, priority=70, status=False, source=hello world',
|
||||
'name=Enabled70False, priority=70, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
]
|
||||
|
||||
def test_i_can_manage_parser_with_multiple_results(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80MultipleFalse": Enabled80MultipleFalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80MultipleFalse, priority=80, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80MultipleFalse:hello world_1',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80MultipleFalse:hello world_2',
|
||||
]
|
||||
|
||||
res_as_tuple = [(str(r.who)[8:], r.status, r.body.body) for r in res]
|
||||
assert res_as_tuple == [
|
||||
('Enabled80MultipleFalse', False, 'Enabled80MultipleFalse:hello world_1'),
|
||||
('Enabled80MultipleFalse', False, 'Enabled80MultipleFalse:hello world_2'),
|
||||
('Enabled50True', False, 'Enabled50True:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled80MultipleFalse:hello world_1'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled80MultipleFalse:hello world_2'),
|
||||
]
|
||||
|
||||
def test_i_can_manage_parser_with_multiple_results_and_a_sucess(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80MultipleTrue": Enabled80MultipleTrueParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80MultipleTrue, priority=80, status=None, source=hello world',
|
||||
]
|
||||
|
||||
res_as_tuple = [(str(r.who)[8:], r.status, r.body.body) for r in res]
|
||||
assert res_as_tuple == [
|
||||
('Enabled80MultipleTrue', True, 'Enabled80MultipleTrue:hello world_1'),
|
||||
('Enabled80MultipleTrue', False, 'Enabled80MultipleTrue:hello world_2'),
|
||||
]
|
||||
@@ -0,0 +1,318 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka_transform import SheerkaTransform, OBJ_TYPE_KEY, SheerkaTransformType, OBJ_ID_KEY
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaTransform(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_transform_an_unknown_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
foo = Concept("foo", body="body")
|
||||
concept_with_sub = Concept("concept_with_sub", body=foo)
|
||||
|
||||
concept = Concept(
|
||||
name="concept_name",
|
||||
is_builtin=True,
|
||||
is_unique=True,
|
||||
key="concept_key",
|
||||
body=concept_with_sub,
|
||||
where=[foo, 1, "1", True, 1.0],
|
||||
pre=foo,
|
||||
post=None, # will not appear
|
||||
definition="it is a definition",
|
||||
definition_type="def type",
|
||||
desc="this this the desc"
|
||||
).def_prop("a", "10").def_prop("b", "foo").def_prop("c", "concept_with_sub")
|
||||
|
||||
# add values and props
|
||||
concept.values[ConceptParts.BODY] = Concept().update_from(concept_with_sub).auto_init()
|
||||
concept.values[ConceptParts.WHERE] = [foo, 1, "1", True, 1.0]
|
||||
concept.values[ConceptParts.PRE] = Concept().update_from(foo).auto_init()
|
||||
concept.values[ConceptParts.POST] = "a value for POST"
|
||||
concept.set_prop("a", 10).set_prop("b", foo).set_prop("c", concept_with_sub)
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(concept)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
'meta.name': 'concept_name',
|
||||
'meta.key': 'concept_key',
|
||||
'meta.is_builtin': True,
|
||||
'meta.is_unique': True,
|
||||
'meta.definition': 'it is a definition',
|
||||
'meta.definition_type': 'def type',
|
||||
'meta.desc': 'this this the desc',
|
||||
'meta.where': [{OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 1,
|
||||
'meta.body': 'body',
|
||||
'meta.name': 'foo'}, 1, '1', True, 1.0],
|
||||
'meta.pre': {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1},
|
||||
'meta.body': {
|
||||
'__type__': SheerkaTransformType.Concept,
|
||||
'__id__': 2,
|
||||
'meta.name': 'concept_with_sub',
|
||||
'meta.body': {
|
||||
'__type__': SheerkaTransformType.Reference,
|
||||
'__id__': 1}},
|
||||
'meta.props': [['a', '10'], ['b', 'foo'], ['c', 'concept_with_sub']],
|
||||
'pre': {'__type__': SheerkaTransformType.Concept,
|
||||
'__id__': 4,
|
||||
'meta.body': 'body',
|
||||
'meta.name': 'foo',
|
||||
'body': 'body'},
|
||||
'post': "a value for POST",
|
||||
'body': {'__type__': SheerkaTransformType.Concept,
|
||||
'__id__': 3,
|
||||
'meta.body': {'__id__': 1, '__type__': SheerkaTransformType.Reference},
|
||||
'meta.name': 'concept_with_sub',
|
||||
'body': {'__id__': 1, '__type__': SheerkaTransformType.Reference}},
|
||||
'where': [{OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}, 1, '1', True, 1.0],
|
||||
'props': [('a', 10),
|
||||
('b', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}),
|
||||
('c', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 2})],
|
||||
}
|
||||
|
||||
def test_i_can_transform_unknown_concept_with_almost_same_value(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept("foo")
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(concept)
|
||||
|
||||
assert to_dict == {OBJ_TYPE_KEY: SheerkaTransformType.Concept, OBJ_ID_KEY: 0, 'meta.name': 'foo'}
|
||||
|
||||
def test_i_can_transform_known_concept_when_the_values_are_the_same(self):
|
||||
"""
|
||||
Values are the same means that we are serializing a concept which has kept all its default values
|
||||
There is not diff between the concept to serialize and the one which was registered with create_new_concept()
|
||||
We serialize only the id of the concept
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept(
|
||||
name="concept_name",
|
||||
is_builtin=True,
|
||||
is_unique=False,
|
||||
key="concept_key",
|
||||
body="body definition",
|
||||
where="where definition",
|
||||
pre="pre definition",
|
||||
post="post definition",
|
||||
definition="it is a definition",
|
||||
definition_type="def type",
|
||||
desc="this this the desc"
|
||||
).def_prop("a").def_prop("b")
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
new_concept = sheerka.new(concept.key)
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(new_concept)
|
||||
|
||||
assert to_dict == {OBJ_TYPE_KEY: SheerkaTransformType.Concept, OBJ_ID_KEY: 0, "id": "1001"}
|
||||
|
||||
def test_i_can_transform_known_concept_when_the_values_are_different(self):
|
||||
"""
|
||||
Values are the different means the concept was modified.
|
||||
It's different from the one which was registered with create_new_concept()
|
||||
We serialize only the differences
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
concept = Concept(
|
||||
name="concept_name",
|
||||
is_builtin=True,
|
||||
is_unique=False,
|
||||
key="concept_key",
|
||||
body="body definition",
|
||||
where="where definition",
|
||||
pre="pre definition",
|
||||
post="post definition",
|
||||
definition="it is a definition",
|
||||
definition_type="def type",
|
||||
desc="this this the desc"
|
||||
).def_prop("a").def_prop("b")
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
||||
|
||||
new_concept = sheerka.new(concept.key, body="another", a=10, pre="another pre")
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(new_concept)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
"id": "1001",
|
||||
'pre': 'another pre',
|
||||
"body": "another",
|
||||
'props': [('a', 10)]
|
||||
}
|
||||
|
||||
def test_i_can_transform_concept_with_circular_reference(self):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar", body=foo)
|
||||
foo.metadata.body = bar
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(foo)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
'meta.name': 'foo',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 1,
|
||||
'meta.name': 'bar',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
|
||||
OBJ_ID_KEY: 0},
|
||||
},
|
||||
}
|
||||
|
||||
def test_i_can_transform_concept_with_circular_reference_2(self):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Concept("foo")
|
||||
bar = Concept("foo", body=foo)
|
||||
foo.metadata.body = bar
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(foo)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
'meta.name': 'foo',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 1,
|
||||
'meta.name': 'foo',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
|
||||
OBJ_ID_KEY: 0},
|
||||
},
|
||||
}
|
||||
|
||||
def test_i_can_transform_the_unknown_concept(self):
|
||||
sheerka = self.get_sheerka(False)
|
||||
|
||||
unknown = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(unknown)
|
||||
|
||||
assert len(to_dict) == 3
|
||||
assert to_dict[OBJ_TYPE_KEY] == SheerkaTransformType.Concept
|
||||
assert to_dict[OBJ_ID_KEY] == 0
|
||||
assert "id" in to_dict
|
||||
|
||||
def test_i_can_transform_simple_execution_context(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(context)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.ExecutionContext,
|
||||
OBJ_ID_KEY: 0,
|
||||
'_parent': None,
|
||||
'_id': 0,
|
||||
'_tab': '',
|
||||
'_bag': {},
|
||||
'_start': 0,
|
||||
'_stop': 0,
|
||||
'who': 'requester',
|
||||
'event': {OBJ_TYPE_KEY: SheerkaTransformType.Event, OBJ_ID_KEY: 1, 'digest': 'xxx'},
|
||||
'desc': 'this is the desc',
|
||||
'children': [],
|
||||
'preprocess': None,
|
||||
'inputs': {},
|
||||
'values': {},
|
||||
'obj': None,
|
||||
'concepts': {}
|
||||
}
|
||||
|
||||
def test_i_can_transform_list(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict([context])
|
||||
|
||||
assert len(to_dict) == 1
|
||||
assert isinstance(to_dict, list)
|
||||
assert to_dict[0]["who"] == "requester"
|
||||
assert to_dict[0]["desc"] == "this is the desc"
|
||||
|
||||
def test_i_can_transform_set(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict({context})
|
||||
|
||||
assert len(to_dict) == 1
|
||||
assert isinstance(to_dict, list)
|
||||
assert to_dict[0]["who"] == "requester"
|
||||
assert to_dict[0]["desc"] == "this is the desc"
|
||||
|
||||
def test_i_can_transform_dict(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
known_concept = Concept("foo", body="foo").set_prop("a", "value_of_a").init_key()
|
||||
sheerka.create_new_concept(self.get_context(sheerka), known_concept)
|
||||
unknown_concept = Concept("bar")
|
||||
known = sheerka.new("foo")
|
||||
|
||||
bag = {
|
||||
"context": context,
|
||||
"known_concept": known_concept,
|
||||
"unknown_concept": unknown_concept,
|
||||
"True": True,
|
||||
"Number": 1.1,
|
||||
"String": "a string value",
|
||||
"None": None,
|
||||
unknown_concept: "hello",
|
||||
known: "world"
|
||||
}
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(bag)
|
||||
|
||||
assert isinstance(to_dict, dict)
|
||||
assert to_dict['Number'] == 1.1
|
||||
assert to_dict['String'] == 'a string value'
|
||||
assert to_dict['True']
|
||||
assert to_dict['None'] is None
|
||||
assert to_dict["context"][OBJ_TYPE_KEY] == SheerkaTransformType.ExecutionContext
|
||||
assert to_dict["known_concept"][OBJ_TYPE_KEY] == SheerkaTransformType.Concept
|
||||
assert to_dict["known_concept"]["id"] == '1001'
|
||||
assert to_dict["unknown_concept"][OBJ_TYPE_KEY] == SheerkaTransformType.Concept
|
||||
assert to_dict["(None)bar"] == "hello"
|
||||
assert to_dict["(1001)foo"] == "world"
|
||||
|
||||
def test_i_can_transform_when_circular_references(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
context.push("another requester", "another desc")
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(context)
|
||||
|
||||
assert isinstance(to_dict, dict)
|
||||
assert to_dict[OBJ_TYPE_KEY] == SheerkaTransformType.ExecutionContext
|
||||
assert len(to_dict["children"]) == 1
|
||||
assert to_dict["children"][0][OBJ_TYPE_KEY] == SheerkaTransformType.ExecutionContext
|
||||
assert to_dict["children"][0]['_parent'][OBJ_TYPE_KEY] == SheerkaTransformType.Reference
|
||||
assert to_dict["children"][0]['_parent'][OBJ_ID_KEY] == 0
|
||||
assert to_dict["children"][0]['event'][OBJ_TYPE_KEY] == SheerkaTransformType.Reference
|
||||
assert to_dict["children"][0]['event'][OBJ_ID_KEY] == 1
|
||||
@@ -0,0 +1,155 @@
|
||||
import ast
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import VARIABLE_PREFIX, Concept
|
||||
from core.tokenizer import Tokenizer
|
||||
from evaluators.AddConceptEvaluator import AddConceptEvaluator
|
||||
from parsers.BaseParser import BaseParser
|
||||
from parsers.ConceptLexerParser import Sequence, StrMatch, ZeroOrMore, ConceptExpression
|
||||
from parsers.BnfParser import BnfParser
|
||||
from parsers.DefaultParser import DefConceptNode, NameNode
|
||||
from parsers.PythonParser import PythonNode, PythonParser
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@staticmethod
|
||||
def get_concept_part(part):
|
||||
if isinstance(part, str):
|
||||
node = PythonNode(part, ast.parse(part, mode="eval"))
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part,
|
||||
parser=PythonParser(),
|
||||
value=node))
|
||||
|
||||
if isinstance(part, PythonNode):
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part.source,
|
||||
parser=PythonParser(),
|
||||
value=part))
|
||||
|
||||
if isinstance(part, ReturnValueConcept):
|
||||
return part
|
||||
|
||||
@staticmethod
|
||||
def get_return_value(source, parsing_expression):
|
||||
return ReturnValueConcept(
|
||||
who="Parsers:RegexParser",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=source,
|
||||
parser=BnfParser(),
|
||||
value=parsing_expression
|
||||
)
|
||||
)
|
||||
|
||||
def get_def_concept(self, name, where=None, pre=None, post=None, body=None, definition=None):
|
||||
concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
|
||||
|
||||
if body:
|
||||
concept.body = self.get_concept_part(body)
|
||||
if where:
|
||||
concept.where = self.get_concept_part(where)
|
||||
if pre:
|
||||
concept.pre = self.get_concept_part(pre)
|
||||
if post:
|
||||
concept.post = self.get_concept_part(post)
|
||||
if definition:
|
||||
concept.definition = definition
|
||||
|
||||
return ReturnValueConcept(BaseParser.PREFIX + "some_name", True, ParserResultConcept(value=concept))
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", True, ParserResultConcept(value=DefConceptNode([]))),
|
||||
True),
|
||||
(ReturnValueConcept(BaseParser.PREFIX + "some_name", False, ParserResultConcept(value=DefConceptNode([]))),
|
||||
False),
|
||||
(ReturnValueConcept(BaseParser.PREFIX + "some_name", True, "not a ParserResultConcept"), False),
|
||||
(ReturnValueConcept(BaseParser.PREFIX + "some_name", True, ParserResultConcept()), False),
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert AddConceptEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
def test_that_the_source_is_correctly_set(self):
|
||||
context = self.get_context()
|
||||
def_concept_return_value = self.get_def_concept(
|
||||
name="hello a",
|
||||
definition=self.get_return_value("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
|
||||
where="isinstance(a, str )",
|
||||
pre="a is not None",
|
||||
body="print('hello' + a)")
|
||||
|
||||
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
|
||||
|
||||
assert evaluated.status
|
||||
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
created_concept = evaluated.body.body
|
||||
assert created_concept.metadata.name == "hello a"
|
||||
assert created_concept.metadata.where == "isinstance(a, str )"
|
||||
assert created_concept.metadata.pre == "a is not None"
|
||||
assert created_concept.metadata.post is None
|
||||
assert created_concept.metadata.body == "print('hello' + a)"
|
||||
assert created_concept.metadata.definition == "hello a"
|
||||
|
||||
def test_that_the_new_concept_is_correctly_saved_in_db(self):
|
||||
context = self.get_context()
|
||||
def_concept_return_value = self.get_def_concept(
|
||||
name="hello a",
|
||||
definition=self.get_return_value("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
|
||||
where="isinstance(a, str )",
|
||||
pre="a is not None",
|
||||
body="print('hello' + a)")
|
||||
|
||||
# sanity. Make sure that the concept does not already exist
|
||||
from_db = context.sheerka.get("hello " + VARIABLE_PREFIX + "0")
|
||||
assert context.sheerka.isinstance(from_db, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
|
||||
AddConceptEvaluator().eval(context, def_concept_return_value)
|
||||
context.sheerka.concepts_cache = {} # reset cache
|
||||
from_db = context.sheerka.get("hello " + VARIABLE_PREFIX + "0")
|
||||
|
||||
assert from_db.metadata.key == f"hello {VARIABLE_PREFIX}0"
|
||||
assert from_db.metadata.name == "hello a"
|
||||
assert from_db.metadata.where == "isinstance(a, str )"
|
||||
assert from_db.metadata.pre == "a is not None"
|
||||
assert from_db.metadata.post is None
|
||||
assert from_db.metadata.body == "print('hello' + a)"
|
||||
assert from_db.metadata.definition == "hello a"
|
||||
assert len(from_db.metadata.props) == 1
|
||||
assert from_db.metadata.props[0] == ("a", None)
|
||||
assert "a" in from_db.props
|
||||
|
||||
assert from_db.compiled == {} # ast is not saved in db
|
||||
|
||||
def test_i_can_get_props_from_python_node(self):
|
||||
ret_val = self.get_concept_part("isinstance(a, str)")
|
||||
context = self.get_context()
|
||||
|
||||
assert AddConceptEvaluator.get_props(context.sheerka, ret_val, ["a"]) == ["a"]
|
||||
|
||||
def test_i_can_get_props_from_another_concept(self):
|
||||
concept = Concept("hello").def_prop("a").def_prop("b")
|
||||
ret_val = ReturnValueConcept(who="some_parser",
|
||||
status=True,
|
||||
value=ParserResultConcept(value=concept))
|
||||
|
||||
assert AddConceptEvaluator.get_props(self.get_context(), ret_val, []) == ["a", "b"]
|
||||
|
||||
def test_i_can_get_props_from_definition(self):
|
||||
parsing_expression = Sequence(ConceptExpression('mult'),
|
||||
ZeroOrMore(Sequence(StrMatch("+"), ConceptExpression("add"))))
|
||||
ret_val = self.get_return_value("mult (('+'|'-') add)?", parsing_expression)
|
||||
|
||||
assert AddConceptEvaluator.get_props(self.get_context(), ret_val, []) == ["add", "mult"]
|
||||
@@ -0,0 +1,102 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Tokenizer
|
||||
from evaluators.AddConceptInSetEvaluator import AddConceptInSetEvaluator
|
||||
from parsers.DefaultParser import IsaConceptNode, NameNode
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def get_ret_val(concept_name, concept_set_name):
|
||||
n1 = NameNode(list(Tokenizer(concept_name)))
|
||||
n2 = NameNode(list(Tokenizer(concept_set_name)))
|
||||
|
||||
return ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([], n1, n2)))
|
||||
|
||||
|
||||
class TestAssConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([]))), True),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=IsaConceptNode([]))), False),
|
||||
(ReturnValueConcept("some_name", True, "not a ParserResultConcept"), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept()), False),
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert AddConceptInSetEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
def test_i_cannot_add_if_the_concept_does_not_exists(self):
|
||||
context = self.get_context()
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == "foo"
|
||||
|
||||
def test_i_cannot_add_if_the_set_does_not_exists(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == "bar"
|
||||
|
||||
def test_i_can_add_concept_to_a_set_of_concept(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
bar = Concept("bar")
|
||||
context.sheerka.set_id_if_needed(bar, False)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
|
||||
|
||||
def test_i_can_add_concept_with_a_body_to_a_set_of_concept(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo", body="1")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
bar = Concept("bar")
|
||||
context.sheerka.set_id_if_needed(bar, False)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
|
||||
|
||||
def test_i_cannot_add_the_same_concept_twice(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
bar = Concept("bar")
|
||||
context.sheerka.set_id_if_needed(bar, False)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_IN_SET)
|
||||
assert res.value.concept == foo
|
||||
assert res.value.concept_set == bar
|
||||
@@ -0,0 +1,117 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts
|
||||
from evaluators.ConceptEvaluator import ConceptEvaluator
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=Concept())), True),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=Concept())), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value="Not a concept")), False),
|
||||
(ReturnValueConcept("some_name", True, Concept()), False),
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert ConceptEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
def test_i_can_evaluate_concept(self):
|
||||
context = self.get_context()
|
||||
concept = Concept(name="foo",
|
||||
where="1",
|
||||
pre="2",
|
||||
post="3").def_prop("a", "4").def_prop("b", "5")
|
||||
|
||||
evaluator = ConceptEvaluator()
|
||||
item = self.pretval(concept)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert result.value.name == "foo"
|
||||
assert result.value.get_metadata_value(ConceptParts.WHERE) == 1
|
||||
assert result.value.get_metadata_value(ConceptParts.PRE) == 2
|
||||
assert result.value.get_metadata_value(ConceptParts.POST) == 3
|
||||
assert result.value.get_prop("a") == 4
|
||||
assert result.value.get_prop("b") == 5
|
||||
assert result.value.key == "foo"
|
||||
assert result.parents == [item]
|
||||
|
||||
def test_body_is_returned_when_defined_and_requested(self):
|
||||
context = self.get_context()
|
||||
concept = Concept(name="foo",
|
||||
body="'I have a value'",
|
||||
where="1",
|
||||
pre="2",
|
||||
post="3").set_prop("a", "4").set_prop("b", "5")
|
||||
|
||||
evaluator = ConceptEvaluator(return_body=True)
|
||||
item = self.pretval(concept)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert result.value == "I have a value"
|
||||
assert result.parents == [item]
|
||||
|
||||
def test_body_is_not_returned_if_not_requested(self):
|
||||
context = self.get_context()
|
||||
concept = Concept(name="foo",
|
||||
body="'I have a value'",
|
||||
where="1",
|
||||
pre="2",
|
||||
post="3").set_prop("a", "4").set_prop("b", "5")
|
||||
|
||||
evaluator = ConceptEvaluator(return_body=False) # which is the default behaviour
|
||||
item = self.pretval(concept)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert result.value == concept
|
||||
assert result.parents == [item]
|
||||
|
||||
def test_i_can_eval_if_with_the_same_name_is_defined_in_the_context(self):
|
||||
# If we evaluate Concept("foo", body="a").set_prop("a", "'property_a'")
|
||||
# ConceptEvaluator will be called to resolve 'a' while we know that 'a' refers to the string 'property_a'
|
||||
|
||||
context = self.get_context()
|
||||
context.obj = Concept("other").set_prop("foo", "'some_other_value'")
|
||||
concept = Concept(name="foo")
|
||||
|
||||
item = self.pretval(concept)
|
||||
result = ConceptEvaluator().eval(context, item)
|
||||
|
||||
assert result.status
|
||||
assert result.value == "'some_other_value'"
|
||||
|
||||
def test_i_cannot_recognize_a_concept_if_one_of_the_prop_is_unknown(self):
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(Concept(name="one").init_key())
|
||||
concept_plus = context.sheerka.add_in_cache(Concept(name="a plus b")
|
||||
.def_prop("a", "one")
|
||||
.def_prop("b", "two").init_key())
|
||||
|
||||
evaluator = ConceptEvaluator()
|
||||
item = self.pretval(concept_plus)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert not result.status
|
||||
assert context.sheerka.isinstance(result.value, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
assert result.value.concept == concept_plus
|
||||
assert result.value.property_name == "b"
|
||||
assert context.sheerka.isinstance(result.value.error, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
|
||||
def test_that_error_concepts_are_transformed_into_errors_only_if_the_key_is_different(self):
|
||||
context = self.get_context()
|
||||
|
||||
error_concept = context.sheerka.new(BuiltinConcepts.ERROR)
|
||||
item = self.pretval(error_concept)
|
||||
result = ConceptEvaluator().eval(context, item)
|
||||
|
||||
assert not context.sheerka.is_success(error_concept) # it's indeed an error
|
||||
assert result.status
|
||||
assert result.value == error_concept
|
||||
@@ -0,0 +1,72 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.EvalEvaluator import EvalEvaluator
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
eval_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.CONCEPT_EVAL_REQUESTED))
|
||||
|
||||
|
||||
def retval(obj, who="who", status=True):
|
||||
"""ret_val"""
|
||||
return ReturnValueConcept(who, status, obj)
|
||||
|
||||
|
||||
class TestEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_match_and_eval(self):
|
||||
context = self.get_context()
|
||||
|
||||
to_eval1 = ReturnValueConcept("some_name", True, Concept(name="2", body="to eval").auto_init())
|
||||
to_eval2 = ReturnValueConcept("some_name", True, Concept(name="3", body="also to eval").auto_init())
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept("some_name", True, "not to eval"),
|
||||
ReturnValueConcept("some_name", True, Concept(name="not to eval")),
|
||||
ReturnValueConcept("some_name", False, Concept(name="1", body="'not to eval'")),
|
||||
to_eval1,
|
||||
to_eval2,
|
||||
eval_requested
|
||||
]
|
||||
|
||||
evaluator = EvalEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert len(evaluated) == 2
|
||||
assert evaluated[0].value == to_eval1.body.body
|
||||
assert evaluated[0].parents == [to_eval1, eval_requested]
|
||||
|
||||
assert evaluated[1].value == to_eval2.body.body
|
||||
assert evaluated[1].parents == [to_eval2, eval_requested]
|
||||
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([retval(Concept("foo", body="bar")), eval_requested], True),
|
||||
([retval(Concept("status is false", body="bar"), status=False), eval_requested], True),
|
||||
([retval("string_value"), eval_requested], True),
|
||||
([retval(Concept("no body")), eval_requested], True),
|
||||
([retval(Concept("eval requested missing", body="bar"))], False),
|
||||
])
|
||||
def test_i_cannot_match_if_eval_request_is_not_present(self, return_values, expected):
|
||||
context = self.get_context()
|
||||
assert EvalEvaluator().matches(context, return_values) == expected
|
||||
|
||||
def test_concept_eval_requested_is_reduced_when_nothing_to_reduce(self):
|
||||
context = self.get_context()
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept("some_name", True, "not to eval"),
|
||||
ReturnValueConcept("some_name", True, Concept(name="not to eval")),
|
||||
ReturnValueConcept("some_name", False, Concept(name="1", body="not to eval")),
|
||||
eval_requested
|
||||
]
|
||||
|
||||
evaluator = EvalEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated == ReturnValueConcept(
|
||||
"evaluators.Eval",
|
||||
False,
|
||||
context.sheerka.new(BuiltinConcepts.CONCEPT_EVAL_REQUESTED))
|
||||
assert evaluated.parents == [eval_requested]
|
||||
@@ -0,0 +1,104 @@
|
||||
import ast
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts, DoNotResolve
|
||||
from evaluators.LexerNodeEvaluator import LexerNodeEvaluator
|
||||
from parsers.ConceptLexerParser import ConceptNode, ConceptLexerParser, StrMatch, UnrecognizedTokensNode, SourceCodeNode
|
||||
from parsers.PythonParser import PythonNode
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestLexerNodeEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def from_parsing(self, context, grammar, expression):
|
||||
parser = ConceptLexerParser()
|
||||
parser.initialize(context, grammar)
|
||||
|
||||
ret_val = parser.parse(context, expression)
|
||||
assert ret_val.status
|
||||
return ret_val
|
||||
|
||||
def from_fragments(self, *fragments):
|
||||
nodes = []
|
||||
for fragment in fragments:
|
||||
if isinstance(fragment, str):
|
||||
node = PythonNode(fragment, ast.parse(fragment.strip(), mode="eval"))
|
||||
nodes.append(SourceCodeNode(node, 0, 0, [], fragment))
|
||||
else:
|
||||
nodes.append(ConceptNode(fragment, 0, 0, [], fragment.name))
|
||||
|
||||
return ReturnValueConcept("somme_name", True, ParserResultConcept(value=nodes))
|
||||
|
||||
def init(self, concept, grammar, text):
|
||||
context = self.get_context()
|
||||
if isinstance(concept, list):
|
||||
for c in concept:
|
||||
context.sheerka.add_in_cache(c)
|
||||
else:
|
||||
context.sheerka.add_in_cache(concept)
|
||||
ret_val = self.from_parsing(context, grammar, text)
|
||||
node = ret_val.value.value[0]
|
||||
|
||||
return context, node
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=ConceptNode(Concept(), 0, 0))), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[SourceCodeNode(0, 0, [])])), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=SourceCodeNode(0, 0, []))), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[UnrecognizedTokensNode(0, 0, [])])), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=UnrecognizedTokensNode(0, 0, []))), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=ConceptNode(Concept(), 0, 0))), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=[SourceCodeNode(0, 0, [])])), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=SourceCodeNode(0, 0, []))), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value="Not a concept node")), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=["Not a concept node"])), False),
|
||||
(ReturnValueConcept("some_name", True, [ConceptNode(Concept(), 0, 0)]), False),
|
||||
(ReturnValueConcept("some_name", True, ConceptNode(Concept(), 0, 0)), False),
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert LexerNodeEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
def test_concept_is_returned_when_only_one_in_the_list(self):
|
||||
foo = Concept("foo")
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
ret_val = self.from_parsing(context, {foo: StrMatch("foo")}, "foo")
|
||||
|
||||
evaluator = LexerNodeEvaluator()
|
||||
result = evaluator.eval(context, ret_val)
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.parser == evaluator
|
||||
assert wrapper.source == "foo"
|
||||
assert return_value == Concept("foo").init_key()
|
||||
assert return_value.compiled[ConceptParts.BODY] == DoNotResolve("foo")
|
||||
assert result.parents == [ret_val]
|
||||
|
||||
def test_concept_python_node_is_returned_when_source_code(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo")
|
||||
ret_val = self.from_fragments(foo, " + 1")
|
||||
|
||||
evaluator = LexerNodeEvaluator()
|
||||
result = evaluator.eval(context, ret_val)
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.parser == evaluator
|
||||
assert wrapper.source == "foo + 1"
|
||||
|
||||
assert return_value == PythonNode('foo + 1', ast.parse("__C__foo__C__ + 1", mode="eval"))
|
||||
assert return_value.concepts == {"__C__foo__C__": foo}
|
||||
assert result.parents == [ret_val]
|
||||
@@ -0,0 +1,200 @@
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.BaseEvaluator import BaseEvaluator
|
||||
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
|
||||
from parsers.BaseParser import BaseParser
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestMultipleSameSuccessEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_match_and_eval(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1", body="value").auto_init() # the first concept is returned
|
||||
|
||||
def test_i_can_match_and_eval_when_no_body(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1").auto_init()
|
||||
|
||||
def test_i_can_match_and_eval_when_value_is_not_a_concept(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, "value"),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == "value"
|
||||
|
||||
def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_concept_evaluator_first(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Concept", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="3", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1", body="value").auto_init() # the concept is returned, not the value
|
||||
|
||||
def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_python_evaluator_first(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="3", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1", body="value").auto_init() # the concept is returned, not the value
|
||||
|
||||
def test_i_can_match_even_if_the_value_are_not_the_same_but_eval_will_fail(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value2").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
assert evaluator.eval(context, return_values) is None
|
||||
|
||||
def test_i_can_match_even_if_the_value_are_not_the_same_but_eval_will_fail_when_no_body(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
assert evaluator.eval(context, return_values) is None
|
||||
|
||||
def test_i_can_match_if_no_parser(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
|
||||
def test_i_cannot_match_if_not_reduced_requested(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, Concept(name="2", body="value")),
|
||||
# ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert not MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
|
||||
def test_i_cannot_match_if_only_one_successful_evaluator(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
# ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, Concept(name="2", body="value")),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert not MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
|
||||
def test_i_cannot_match_if_at_least_one_parser_is_successful(self):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", True, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert not MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
@@ -0,0 +1,73 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.OneErrorEvaluator import OneErrorEvaluator
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def r(value, status=True):
|
||||
return ReturnValueConcept(value, status, value)
|
||||
|
||||
|
||||
reduce_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.REDUCE_REQUESTED))
|
||||
|
||||
|
||||
class TestOneErrorEvaluator(TestUsingMemoryBasedSheerka):
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([r("evaluators.one error", False), reduce_requested], True),
|
||||
([r("evaluators.one error", False), r("failed", False), r("failed", False), reduce_requested], True),
|
||||
([r("evaluators.error", False), r("not a parser in success"), reduce_requested], True),
|
||||
([r("evaluators.no reduce required", False), r("failed", False), r("failed", False)], False),
|
||||
([r("evaluators.no reduce required", False)], False),
|
||||
([r("evaluators.error", False), r("evaluators.success"), reduce_requested], False),
|
||||
([r("evaluators.error", False), r("parsers.success"), reduce_requested], False),
|
||||
([r("evaluators.success"), r("not an evaluator in error", False), reduce_requested], False),
|
||||
([r("evaluators.error", False), r("evaluators.another error", False), reduce_requested], False),
|
||||
])
|
||||
def test_i_can_match(self, return_values, expected):
|
||||
context = self.get_context()
|
||||
assert OneErrorEvaluator().matches(context, return_values) == expected
|
||||
|
||||
def test_i_can_eval(self):
|
||||
context = self.get_context()
|
||||
|
||||
return_values = [
|
||||
r("evaluators.one error", False),
|
||||
r("parsers.failed", False),
|
||||
r("parsers.failed", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneErrorEvaluator()
|
||||
evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert not res.status
|
||||
assert res.body == "evaluators.one error"
|
||||
assert len(res.parents) == 4
|
||||
|
||||
def test_unwanted_return_values_are_not_eaten(self):
|
||||
context = self.get_context()
|
||||
|
||||
a_successful_concept = r("successful concept")
|
||||
a_concept_in_error = r("concept in error", False)
|
||||
return_values = [
|
||||
r("evaluators.one error", False),
|
||||
r("parsers.failed", False),
|
||||
r("parsers.failed", False),
|
||||
a_successful_concept,
|
||||
a_concept_in_error,
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneErrorEvaluator()
|
||||
evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert not res.status
|
||||
assert res.body == "evaluators.one error"
|
||||
assert len(res.parents) == 4
|
||||
|
||||
assert a_successful_concept not in res.parents
|
||||
@@ -0,0 +1,72 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.OneSuccessEvaluator import OneSuccessEvaluator
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def r(value, status=True):
|
||||
return ReturnValueConcept(value, status, value)
|
||||
|
||||
|
||||
reduce_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.REDUCE_REQUESTED))
|
||||
|
||||
|
||||
class TestOneSuccessEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([r("evaluators.one success"), reduce_requested], True),
|
||||
([r("evaluators.one success"), r("failed", False), r("failed", False), reduce_requested], True),
|
||||
([r("evaluators.no reduce required"), r("failed", False), r("failed", False)], False),
|
||||
([r("evaluators.no reduce required")], False),
|
||||
([r("evaluators.failed", False), r("failed", False), r("failed", False), reduce_requested], False),
|
||||
([r("evaluators.failed", False), r("not evaluator success"), reduce_requested], False),
|
||||
([r("evaluators.success"), r("evaluators.another success"), reduce_requested], False),
|
||||
([r("evaluators.one success"), r("other success"), r("failed", False), reduce_requested], True),
|
||||
([r("evaluators.one success"), r("parsers.success"), reduce_requested], False),
|
||||
])
|
||||
def test_i_can_match(self, return_values, expected):
|
||||
context = self.get_context()
|
||||
assert OneSuccessEvaluator().matches(context, return_values) == expected
|
||||
|
||||
def test_i_can_eval(self):
|
||||
context = self.get_context()
|
||||
|
||||
return_values = [
|
||||
r("evaluators.one success"),
|
||||
r("failed", False),
|
||||
r("failed", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneSuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert res.status
|
||||
assert res.body == "evaluators.one success"
|
||||
assert len(res.parents) == 4
|
||||
|
||||
def test_i_do_not_eat_the_other_success(self):
|
||||
context = self.get_context()
|
||||
|
||||
not_a_parser_success = r("other success")
|
||||
return_values = [
|
||||
r("evaluators.one success"),
|
||||
not_a_parser_success,
|
||||
r("failed", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneSuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert res.status
|
||||
assert res.body == "evaluators.one success"
|
||||
assert len(res.parents) == 3
|
||||
|
||||
assert not_a_parser_success not in res.parents
|
||||
@@ -0,0 +1,49 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
||||
from core.concept import Concept
|
||||
from evaluators.PrepareEvalEvaluator import PrepareEvalEvaluator
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
r = ReturnValueConcept
|
||||
|
||||
|
||||
class TestPrepareEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("eval 1 + 1")), True),
|
||||
(r("name", True, UserInputConcept(" eval 1 + 1")), True),
|
||||
(r("name", True, UserInputConcept("eval")), False),
|
||||
(r("name", True, UserInputConcept("1+1")), False),
|
||||
(r("name", True, UserInputConcept("")), False),
|
||||
(r("name", True, UserInputConcept("eval ")), False),
|
||||
(r("name", True, UserInputConcept([])), False),
|
||||
(r("name", True, Concept("foo")), False),
|
||||
(r("name", True, "not a concept"), False),
|
||||
(r("name", False, UserInputConcept("eval 1 + 1")), False),
|
||||
(r("name", False, UserInputConcept(" eval 1 + 1")), False),
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert PrepareEvalEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("eval 1 + 1")), "1 + 1"),
|
||||
(r("name", True, UserInputConcept(" eval 1 + 1")), "1 + 1"),
|
||||
])
|
||||
def test_i_can_eval(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
prepare_evaluator = PrepareEvalEvaluator()
|
||||
prepare_evaluator.matches(context, ret_val)
|
||||
res = prepare_evaluator.eval(context, ret_val)
|
||||
|
||||
assert len(res) == 2
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.USER_INPUT)
|
||||
assert res[0].body.body == expected
|
||||
|
||||
assert res[1].status
|
||||
assert sheerka.isinstance(res[1].body, BuiltinConcepts.CONCEPT_EVAL_REQUESTED)
|
||||
@@ -0,0 +1,138 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.PythonEvaluator import PythonEvaluator
|
||||
from parsers.PythonParser import PythonNode, PythonParser
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def get_context_name(context):
|
||||
return context.name
|
||||
|
||||
|
||||
class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=PythonNode("", None))), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value="other thing")), False),
|
||||
(ReturnValueConcept("some_name", False, "not relevant"), False),
|
||||
(ReturnValueConcept("some_name", True, Concept()), False)
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert PythonEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1 + 1", 2),
|
||||
("sheerka.test()", "I have access to Sheerka !"),
|
||||
("a=10\na", 10),
|
||||
])
|
||||
def test_i_can_eval(self, text, expected):
|
||||
context = self.get_context()
|
||||
parsed = PythonParser().parse(context, text)
|
||||
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == expected
|
||||
|
||||
@pytest.mark.parametrize("concept", [
|
||||
Concept("foo"),
|
||||
Concept("foo", body="2"),
|
||||
Concept("foo").set_prop("prop", "'a'"),
|
||||
Concept("foo", body="bar")
|
||||
])
|
||||
def test_i_cannot_eval_simple_concept(self, concept):
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo"))
|
||||
|
||||
parsed = PythonParser().parse(context, "foo")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert not evaluated.status
|
||||
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.NOT_FOR_ME)
|
||||
|
||||
def test_i_can_eval_expression_with_that_references_concepts(self):
|
||||
"""
|
||||
I can test modules with variables
|
||||
:return:
|
||||
"""
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo", body="1"))
|
||||
|
||||
parsed = PythonParser().parse(context, "foo + 2")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == 3
|
||||
|
||||
def test_i_can_eval_module_with_that_references_concepts(self):
|
||||
"""
|
||||
I can test modules with variables
|
||||
:return:
|
||||
"""
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo"))
|
||||
|
||||
parsed = PythonParser().parse(context, "def a(b):\n return b\na(c:foo:)")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept("foo").init_key()
|
||||
|
||||
def test_i_can_eval_module_with_that_references_concepts_with_body(self):
|
||||
"""
|
||||
I can test modules with variables
|
||||
:return:
|
||||
"""
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo", body="2"))
|
||||
|
||||
parsed = PythonParser().parse(context, "def a(b):\n return b\na(foo)")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == 2
|
||||
|
||||
def test_i_can_eval_concept_token(self):
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo", body="2"))
|
||||
|
||||
parsed = PythonParser().parse(context, "get_context_name(c:foo:)")
|
||||
python_evaluator = PythonEvaluator()
|
||||
python_evaluator.locals["get_context_name"] = get_context_name
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == "foo"
|
||||
|
||||
# sanity, does not work otherwise
|
||||
parsed = PythonParser().parse(context, "get_context_name(foo)")
|
||||
python_evaluator = PythonEvaluator()
|
||||
python_evaluator.locals["get_context_name"] = get_context_name
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
|
||||
assert not evaluated.status
|
||||
assert evaluated.body.body.args[0] == "'int' object has no attribute 'name'"
|
||||
|
||||
@pytest.mark.parametrize("text, concept_key, concept_id, use_concept", [
|
||||
("__C__key__C__", "key", None, False),
|
||||
("__C__key__id__C__", "key", "id", False),
|
||||
("__C__USE_CONCEPT__key__id__C__", "key", "id", True),
|
||||
("__C__USE_CONCEPT__key__id__C__", "key", "id", True),
|
||||
])
|
||||
def test_i_can_resolve_name(self, text, concept_key, concept_id, use_concept):
|
||||
context = self.get_context()
|
||||
assert PythonEvaluator().resolve_name(context, text) == (concept_key, concept_id, use_concept)
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"__C__",
|
||||
"__C__key",
|
||||
"__C__key____",
|
||||
"__C____",
|
||||
"__C__USE_CONCEPT__",
|
||||
])
|
||||
def test_i_cannot_resolve_name(self, text):
|
||||
context = self.get_context()
|
||||
assert PythonEvaluator().resolve_name(context, text) is None
|
||||
@@ -0,0 +1,105 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.TooManySuccessEvaluator import TooManySuccessEvaluator
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def r(name, status=True, value=None):
|
||||
value = value or name
|
||||
return ReturnValueConcept(name, status, value)
|
||||
|
||||
|
||||
reduce_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.REDUCE_REQUESTED))
|
||||
|
||||
|
||||
class TestTooManySuccessEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([r("evaluators.success1"), r("evaluators.success2"), reduce_requested], True),
|
||||
([r("evaluators.success1"), r("evaluators.success2"), r("other"), reduce_requested], True),
|
||||
([r("evaluators.success1"), r("evaluators.success2"), r("other", False), reduce_requested], True),
|
||||
([r("evaluators.a", value=Concept("c1", body="1")),
|
||||
r("evaluators.a", value=Concept("c2", body="1")),
|
||||
r("other"),
|
||||
reduce_requested], True),
|
||||
([r("evaluators.a", value=Concept("c1", body="1")),
|
||||
r("evaluators.a", value=Concept("c2", body="1")),
|
||||
r("parsers.other", False),
|
||||
reduce_requested], True),
|
||||
([r("evaluators.a", value=Concept("c1", body="1")),
|
||||
r("evaluators.a", value=Concept("c2", body="1")),
|
||||
r("parsers.other"),
|
||||
reduce_requested], False),
|
||||
([r("evaluators.success1"), reduce_requested], False),
|
||||
([reduce_requested], False),
|
||||
([r("evaluators.success1"), r("evaluators.success2")], False),
|
||||
])
|
||||
def test_i_can_match(self, return_values, expected):
|
||||
context = self.get_context()
|
||||
assert TooManySuccessEvaluator().matches(context, return_values) == expected
|
||||
|
||||
def test_i_can_eval(self):
|
||||
context = self.get_context()
|
||||
|
||||
value1 = r("evaluators.a", value=Concept("c1", body="1"))
|
||||
value2 = r("evaluators.a", value=Concept("c2", body="2"))
|
||||
return_values = [
|
||||
value1,
|
||||
value2,
|
||||
r("other", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = TooManySuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.body, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||
assert res.body.body == [value1, value2]
|
||||
assert len(res.parents) == 4
|
||||
|
||||
def test_i_can_eval_when_same_success(self):
|
||||
context = self.get_context()
|
||||
|
||||
return_values = [
|
||||
r("evaluators.a", value=Concept("c1", body="1").auto_init()),
|
||||
r("evaluators.a", value=Concept("c2", body="1").auto_init()),
|
||||
r("other", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = TooManySuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert res is None
|
||||
|
||||
def test_other_success_are_not_reduced(self):
|
||||
context = self.get_context()
|
||||
|
||||
value1 = r("evaluators.a", value=Concept("c1", body="1").auto_init())
|
||||
value2 = r("evaluators.a", value=Concept("c2", body="2").auto_init())
|
||||
other_success = r("other")
|
||||
return_values = [
|
||||
value1,
|
||||
value2,
|
||||
other_success,
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = TooManySuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.body, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||
assert res.body.body == [value1, value2]
|
||||
assert len(res.parents) == 3
|
||||
assert other_success not in res.parents
|
||||
@@ -0,0 +1,625 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property, simplec
|
||||
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
|
||||
from parsers.ConceptLexerParser import Sequence, StrMatch, OrderedChoice, Optional, ConceptExpression
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider
|
||||
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaNonReg(TestUsingFileBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1 + 1", 2),
|
||||
("sheerka.test()", 'I have access to Sheerka !')
|
||||
])
|
||||
def test_i_can_eval_python_expressions_with_no_variable(self, text, expected):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == expected
|
||||
|
||||
def test_i_can_eval_concept_with_python_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept(name="one", body="1")
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == simplec("one", 1) # by default, the concept is returned
|
||||
|
||||
def test_i_can_eval_concept_with_concept_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_one = Concept(name="one")
|
||||
concept_un = Concept(name="un", body="one")
|
||||
sheerka.add_in_cache(concept_one)
|
||||
sheerka.add_in_cache(concept_un)
|
||||
|
||||
res = sheerka.evaluate_user_input("un")
|
||||
return_value = res[0].value
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert return_value == simplec("un", simplec("one", None))
|
||||
|
||||
def test_i_can_eval_concept_with_no_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept(name="one")
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == concept
|
||||
assert id(res[0].value) != id(concept)
|
||||
|
||||
def test_is_unique_property_is_used_when_evaluating(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept = Concept(name="one", is_unique=True)
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == concept
|
||||
assert id(res[0].value) == id(concept)
|
||||
|
||||
def test_i_can_eval_def_concept_request(self):
|
||||
text = """
|
||||
def concept a + b
|
||||
where isinstance(a, int) and isinstance(b, int)
|
||||
pre isinstance(a, int) and isinstance(b, int)
|
||||
post isinstance(res, int)
|
||||
as:
|
||||
def func(x,y):
|
||||
return x+y
|
||||
func(a,b)
|
||||
"""
|
||||
|
||||
expected = self.get_default_concept()
|
||||
expected.metadata.id = "1001"
|
||||
expected.metadata.desc = None
|
||||
expected.metadata.props = [("a", None), ("b", None)]
|
||||
expected.init_key()
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
concept_saved = res[0].value.body
|
||||
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||
|
||||
assert concept_saved.key in sheerka.cache_by_key
|
||||
assert concept_saved.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_digest()))
|
||||
|
||||
def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept(self):
|
||||
"""
|
||||
In this test, we test that the properties of 'concept a xx b' (which are 'a' and 'b')
|
||||
are correctly detected, thanks to the source code 'a plus b' in its body
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
# concept 'a plus b' is known
|
||||
concept_a_plus_b = Concept(name="a plus b").def_prop("a").def_prop("b")
|
||||
sheerka.add_in_cache(concept_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").def_prop("a").def_prop("b").init_key()
|
||||
expected.metadata.id = "1001"
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
concept_saved = res[0].value.body
|
||||
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||
|
||||
assert concept_saved.key in sheerka.cache_by_key
|
||||
assert concept_saved.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_digest()))
|
||||
|
||||
def test_i_cannot_eval_the_same_def_concept_twice(self):
|
||||
text = """
|
||||
def concept a + b
|
||||
where isinstance(a, int) and isinstance(b, int)
|
||||
pre isinstance(a, int) and isinstance(b, int)
|
||||
post isinstance(res, int)
|
||||
as:
|
||||
def func(x,y):
|
||||
return x+y
|
||||
func(a,b)
|
||||
"""
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
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)
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"",
|
||||
" ",
|
||||
"\n",
|
||||
])
|
||||
def test_i_can_eval_a_empty_input(self, text):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NOP)
|
||||
|
||||
def test_i_can_eval_concept_with_variable(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_hello = Concept(name="hello a").def_prop("a")
|
||||
concept_foo = Concept(name="foo")
|
||||
sheerka.add_in_cache(concept_hello)
|
||||
sheerka.add_in_cache(concept_foo)
|
||||
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
return_value = res[0].value
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(return_value, concept_hello)
|
||||
assert return_value.props["a"].value == concept_foo
|
||||
|
||||
def test_i_can_eval_concept_with_variable_and_python_as_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
hello_a = sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
|
||||
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, hello_a)
|
||||
assert res[0].value.body == "hello foo"
|
||||
assert res[0].value.metadata.is_evaluated
|
||||
assert res[0].value.props["a"].value == simplec("foo", "foo")
|
||||
assert res[0].value.props["a"].value.metadata.is_evaluated
|
||||
|
||||
def test_i_can_eval_duplicate_concepts_with_same_value(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.add_in_cache(Concept(name="hello foo", body="'hello foo'"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
|
||||
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value.body == "hello foo"
|
||||
assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME)
|
||||
|
||||
def test_i_cannot_manage_duplicate_concepts_when_the_values_are_different(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.add_in_cache(Concept(name="hello foo", body="'hello foo'"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'another value'"))
|
||||
|
||||
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)
|
||||
|
||||
concepts = res[0].value.body
|
||||
assert len(concepts) == 2
|
||||
sorted_values = sorted(concepts, key=lambda x: x.value.body)
|
||||
assert sorted_values[0].value.body == "hello another value"
|
||||
assert sorted_values[1].value.body == "hello foo"
|
||||
|
||||
def test_i_can_manage_concepts_with_the_same_key_when_values_are_the_same(self):
|
||||
sheerka = self.get_sheerka()
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
sheerka.create_new_concept(context, Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.create_new_concept(context, Concept(name="hello b", body="'hello ' + b").def_prop("b"))
|
||||
|
||||
res = sheerka.evaluate_user_input("hello 'foo'")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value.body == "hello foo" # I don't know yet the one to choose
|
||||
assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME)
|
||||
|
||||
def test_i_can_create_concepts_with_python_code_as_body(self):
|
||||
sheerka = self.get_sheerka()
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
sheerka.create_new_concept(context, Concept(name="concepts", body="sheerka.concepts()"))
|
||||
res = sheerka.evaluate_user_input("concepts")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert isinstance(res[0].value.body, list)
|
||||
|
||||
def test_i_can_create_concept_with_bnf_definition(self):
|
||||
sheerka = self.get_sheerka(False, False)
|
||||
a = Concept("a")
|
||||
sheerka.add_in_cache(a)
|
||||
sheerka.concepts_definition_cache = {a: OrderedChoice("one", "two")}
|
||||
|
||||
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)
|
||||
|
||||
saved_concept = sheerka.sdp.get_safe(sheerka.CONCEPTS_ENTRY, "plus")
|
||||
assert saved_concept.key == "plus"
|
||||
assert saved_concept.metadata.definition == "a ('plus' plus)?"
|
||||
assert "a" in saved_concept.props
|
||||
assert "plus" in saved_concept.props
|
||||
|
||||
saved_definitions = sheerka.sdp.get_safe(sheerka.CONCEPTS_DEFINITIONS_ENTRY)
|
||||
expected_bnf = Sequence(
|
||||
a, Optional(Sequence(StrMatch("plus"), ConceptExpression("plus", rule_name="plus"))))
|
||||
assert saved_definitions[saved_concept] == expected_bnf
|
||||
|
||||
new_concept = res[0].value.body
|
||||
assert new_concept.metadata.name == "plus"
|
||||
assert new_concept.metadata.definition == "a ('plus' plus)?"
|
||||
assert new_concept.bnf == expected_bnf
|
||||
assert "a" in new_concept.props
|
||||
assert "plus" in new_concept.props
|
||||
|
||||
def test_i_can_eval_bnf_definitions(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
|
||||
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(self):
|
||||
sheerka = self.get_sheerka()
|
||||
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.evaluate_user_input("one three")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
return_value = res[0].value
|
||||
|
||||
assert sheerka.isinstance(return_value, concept_b)
|
||||
assert return_value.body == "one three"
|
||||
assert return_value.metadata.is_evaluated
|
||||
|
||||
assert return_value.props["a"] == Property("a", sheerka.new(concept_a.key, body="one").init_key())
|
||||
assert return_value.props["a"].value.metadata.is_evaluated
|
||||
|
||||
def test_i_can_eval_bnf_definitions_from_separate_instances(self):
|
||||
"""
|
||||
Same test then before,
|
||||
but make sure that the BNF are correctly persisted and loaded
|
||||
"""
|
||||
sheerka = self.get_sheerka(False)
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' 'two'")[0].body.body
|
||||
|
||||
res = self.get_sheerka(False).evaluate_user_input("one two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
# add another bnf definition
|
||||
concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body
|
||||
|
||||
res = self.get_sheerka(False).evaluate_user_input("one two") # previous one still works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
res = self.get_sheerka(False).evaluate_user_input("one two three") # new one works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_b)
|
||||
assert res[0].value.body == "one two three"
|
||||
assert res[0].value.props["a"] == Property("a", sheerka.new(concept_a.key, body="one two").init_key())
|
||||
|
||||
@pytest.mark.parametrize("desc, definitions", [
|
||||
("Simple form", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit"
|
||||
]),
|
||||
("When twenty is a concept", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenty as 20",
|
||||
"def concept twenties from bnf twenty (one|two)=unit as twenty + unit"
|
||||
]),
|
||||
("When digit is a concept", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenty as 20",
|
||||
"def concept digit from bnf one|two",
|
||||
"def concept twenties from bnf twenty digit as twenty + digit"
|
||||
]),
|
||||
("When using isa and concept twenty", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"two isa number",
|
||||
"def concept twenties from bnf 'twenty' number as 20 + number"
|
||||
]),
|
||||
("When using isa and concept twenty", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenty as 20",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"two isa number",
|
||||
"def concept twenties from bnf twenty number as 20 + number"
|
||||
]),
|
||||
])
|
||||
def test_i_can_mix_concept_with_python_to_define_numbers(self, desc, definitions):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
for definition in definitions:
|
||||
sheerka.evaluate_user_input(definition)
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, "twenties")
|
||||
assert res[0].body.body == 21
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + twenty two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 43
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + 1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 23
|
||||
|
||||
def test_i_can_mix_bnf_and_isa(self):
|
||||
"""
|
||||
if 'one' isa 'number, twenty number should be recognized
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("def concept two as 2")
|
||||
sheerka.evaluate_user_input("def concept number")
|
||||
sheerka.evaluate_user_input("one isa number")
|
||||
sheerka.evaluate_user_input("two isa number")
|
||||
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' number as 20 + number")
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == simplec("twenties", 21)
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + twenty two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 43
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + 1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 23
|
||||
|
||||
def test_i_can_mix_concept_of_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
definitions = [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit",
|
||||
"def concept a plus b as a + b"
|
||||
]
|
||||
|
||||
for definition in definitions:
|
||||
sheerka.evaluate_user_input(definition)
|
||||
|
||||
res = sheerka.evaluate_user_input("1 plus 2")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("1 plus one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 2
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + 1 plus 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("1 plus twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("one plus 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 2
|
||||
|
||||
res = sheerka.evaluate_user_input("one plus two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("one plus twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one plus 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one plus one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one plus twenty two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 43
|
||||
|
||||
@pytest.mark.xfail
|
||||
def test_i_can_evaluate_concept_of_concept_when_multiple_choices(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
definitions = [
|
||||
"def concept little a where a",
|
||||
"def concept blue a where a",
|
||||
"def concept little blue a where a",
|
||||
"def concept house"
|
||||
]
|
||||
|
||||
for definition in definitions:
|
||||
sheerka.evaluate_user_input(definition)
|
||||
|
||||
### CAUTION ####
|
||||
# this test cannot work !!
|
||||
# it is just to hint the result that I would like to achieve
|
||||
|
||||
res = sheerka.evaluate_user_input("little blue house")
|
||||
assert len(res) == 2
|
||||
assert res[0].status
|
||||
assert res[0].body == "little(blue(house))"
|
||||
|
||||
assert res[1].status
|
||||
assert res[1].body == "little blue(house)"
|
||||
|
||||
def test_i_can_say_that_a_concept_isa_another_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept foo")
|
||||
sheerka.evaluate_user_input("def concept bar")
|
||||
|
||||
res = sheerka.evaluate_user_input("foo isa bar")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
def test_eval_does_not_break_valid_result(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("def concept two as 2")
|
||||
|
||||
res = sheerka.evaluate_user_input("one + two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("eval one + two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 3
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"'hello",
|
||||
'"foo" + "string',
|
||||
"c::",
|
||||
"c:foo\nbar:",
|
||||
"c:foo",
|
||||
"def concept 'name",
|
||||
"def concept name from bnf 'name"
|
||||
])
|
||||
def test_i_can_manage_tokenizer_error(self, text):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept("foo"))
|
||||
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) > 1
|
||||
for r in [r for r in res if r.who.startswith("parsers.")]:
|
||||
assert not r.status
|
||||
|
||||
def test_i_can_recognize_concept_from_string(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.add_in_cache(Concept("one", body="1"))
|
||||
|
||||
res = sheerka.evaluate_user_input("'one'")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == "one"
|
||||
|
||||
res = sheerka.evaluate_user_input("eval 'one'")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == "one"
|
||||
|
||||
@pytest.mark.parametrize("expression", [
|
||||
"def concept twenties from bnf 'twenty' (one | two)=unit as 20 + unit",
|
||||
"def concept twenties from bnf 'twenty' (one | two)=unit as twenty + unit",
|
||||
"def concept twenties from bnf twenty (one | two)=unit as 20 + unit",
|
||||
"def concept twenties from bnf twenty (one | two)=unit as twenty + unit",
|
||||
])
|
||||
def test_i_can_evaluate_bnf_concepts(self, expression):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("def concept two as 2")
|
||||
sheerka.evaluate_user_input("def concept twenty as 20")
|
||||
sheerka.evaluate_user_input(expression)
|
||||
res = sheerka.evaluate_user_input("eval twenty one")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 21
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from core.tokenizer import Tokenizer, Token, TokenKind
|
||||
from core.tokenizer import Tokenizer, TokenKind
|
||||
from parsers.BaseParser import BaseParser
|
||||
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Tokenizer, TokenKind, LexerError
|
||||
from parsers.BaseParser import UnexpectedTokenErrorNode
|
||||
from parsers.BnfParser import BnfParser, UnexpectedEndOfFileError
|
||||
from parsers.ConceptLexerParser import StrMatch, Optional, ZeroOrMore, OrderedChoice, Sequence, OneOrMore, \
|
||||
ConceptLexerParser, ConceptExpression, cnode
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class ClassWithName:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
class TestBnfParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("'str'", StrMatch("str")),
|
||||
("1", StrMatch("1")),
|
||||
(" 1", StrMatch("1")),
|
||||
(",", StrMatch(",")),
|
||||
("'foo'?", Optional(StrMatch("foo"))),
|
||||
("'foo'*", ZeroOrMore(StrMatch("foo"))),
|
||||
("'foo'+", OneOrMore(StrMatch("foo"))),
|
||||
("1 | 2 | 3", OrderedChoice(StrMatch("1"), StrMatch("2"), StrMatch("3"))),
|
||||
("1|2|3", OrderedChoice(StrMatch("1"), StrMatch("2"), StrMatch("3"))),
|
||||
("1'|' 2 '|' 3", Sequence(StrMatch("1"), StrMatch("|"), StrMatch("2"), StrMatch("|"), StrMatch("3"))),
|
||||
("1 2 'foo'", Sequence(StrMatch("1"), StrMatch("2"), StrMatch("foo"))),
|
||||
("1 2 | 3 4+", OrderedChoice(
|
||||
Sequence(StrMatch("1"), StrMatch("2")),
|
||||
Sequence(StrMatch("3"), OneOrMore(StrMatch("4"))))),
|
||||
(
|
||||
"1 (2 | 3) 4+",
|
||||
Sequence(StrMatch("1"), OrderedChoice(StrMatch("2"), StrMatch("3")), OneOrMore(StrMatch("4")))),
|
||||
("(1|2)+", OneOrMore(OrderedChoice(StrMatch("1"), StrMatch("2")))),
|
||||
("(1 2)+", OneOrMore(Sequence(StrMatch("1"), StrMatch("2")))),
|
||||
("1 *", Sequence(StrMatch("1"), StrMatch("*"))),
|
||||
("1 ?", Sequence(StrMatch("1"), StrMatch("?"))),
|
||||
("1 +", Sequence(StrMatch("1"), StrMatch("+"))),
|
||||
("(1|*) +", Sequence(OrderedChoice(StrMatch("1"), StrMatch("*")), StrMatch("+"))),
|
||||
("1, :&", Sequence(StrMatch("1"), StrMatch(","), StrMatch(":"), StrMatch("&"))),
|
||||
("(1 )", StrMatch("1")),
|
||||
("'str'=var", StrMatch("str", rule_name="var")),
|
||||
("'foo'?=var", Optional(StrMatch("foo"), rule_name="var")),
|
||||
("('foo'?)=var", Optional(StrMatch("foo"), rule_name="var")),
|
||||
("'foo'*=var", ZeroOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("('foo'*)=var", ZeroOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("'foo'+=var", OneOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("('foo'+)=var", OneOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("'foo'=var?", Optional(StrMatch("foo", rule_name="var"))),
|
||||
("('foo'=var)?", Optional(StrMatch("foo", rule_name="var"))),
|
||||
("'foo'=var*", ZeroOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("('foo'=var)*", ZeroOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("'foo'=var+", OneOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("('foo'=var)+", OneOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("(1 | 2 | 3)=var", OrderedChoice(StrMatch("1"), StrMatch("2"), StrMatch("3"), rule_name="var")),
|
||||
("(1 2)=var", Sequence(StrMatch("1"), StrMatch("2"), rule_name="var")),
|
||||
("(1 2)+=var", OneOrMore(Sequence(StrMatch("1"), StrMatch("2")), rule_name="var")),
|
||||
("(1 2)=var+", OneOrMore(Sequence(StrMatch("1"), StrMatch("2"), rule_name="var"))),
|
||||
])
|
||||
def test_i_can_parse_regex(self, expression, expected):
|
||||
parser = BnfParser()
|
||||
res = parser.parse(self.get_context(), Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("foo", Concept("foo").init_key()),
|
||||
("foo*", ZeroOrMore(Concept("foo").init_key())),
|
||||
("foo 'and' bar+", Sequence(Concept("foo").init_key(), StrMatch("and"), OneOrMore(Concept("bar").init_key()))),
|
||||
("foo | bar?", OrderedChoice(Concept("foo").init_key(), Optional(Concept("bar").init_key()))),
|
||||
("'str' = var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
|
||||
("'str''='var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
|
||||
])
|
||||
def test_i_can_parse_regex_with_concept(self, expression, expected):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
var = Concept("var")
|
||||
context = self.get_context()
|
||||
|
||||
for c in (foo, bar, var):
|
||||
context.sheerka.add_in_cache(c)
|
||||
parser = BnfParser()
|
||||
res = parser.parse(context, Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
def test_i_can_parse_regex_with_concept_when_the_concept_is_still_under_definition(self):
|
||||
expression = "foo"
|
||||
expected = ConceptExpression("foo")
|
||||
|
||||
context = self.get_context()
|
||||
context.obj = ClassWithName("foo")
|
||||
|
||||
parser = BnfParser()
|
||||
res = parser.parse(context, Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
@pytest.mark.parametrize("expression, error", [
|
||||
("1 ", UnexpectedEndOfFileError()),
|
||||
("1|", UnexpectedEndOfFileError()),
|
||||
("(1|)", UnexpectedTokenErrorNode("Unexpected token 'Token(<EOF>)'", [TokenKind.RPAR])),
|
||||
("1=", UnexpectedTokenErrorNode("Unexpected token 'Token(<EOF>)'", [TokenKind.IDENTIFIER])),
|
||||
("'name", LexerError("Missing Trailing quote", "'name", 5, 1, 6))
|
||||
])
|
||||
def test_i_can_detect_errors(self, expression, error):
|
||||
parser = BnfParser()
|
||||
res = parser.parse(self.get_context(), Tokenizer(expression))
|
||||
ret_value = res.value.value
|
||||
assert parser.has_error
|
||||
assert not res.status
|
||||
assert ret_value[0] == error
|
||||
|
||||
def test_i_can_use_the_result_of_regex_parsing_to_parse_a_text(self):
|
||||
foo = Concept(name="foo")
|
||||
bar = Concept(name="bar")
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(foo)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
regex_parser = BnfParser()
|
||||
foo_definition = regex_parser.parse(context, "'twenty' | 'thirty'").value.value
|
||||
bar_definition = regex_parser.parse(context, "foo ('one' | 'two')").value.value
|
||||
|
||||
concepts = {bar: bar_definition, foo: foo_definition}
|
||||
concept_parser = ConceptLexerParser()
|
||||
concept_parser.initialize(context, concepts)
|
||||
|
||||
res = concept_parser.parse(context, "twenty two")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("bar", 0, 2, "twenty two")]
|
||||
|
||||
res = concept_parser.parse(context, "thirty one")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("bar", 0, 2, "thirty one")]
|
||||
|
||||
res = concept_parser.parse(context, "twenty")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("foo", 0, 0, "twenty")]
|
||||
|
||||
def test_i_cannot_parse_when_too_many_concepts(self):
|
||||
foo1 = Concept(name="foo", body="1")
|
||||
foo2 = Concept(name="foo", body="2")
|
||||
context = self.get_context()
|
||||
context.sheerka.cache_by_key["foo"] = [foo1, foo2]
|
||||
|
||||
regex_parser = BnfParser()
|
||||
res = regex_parser.parse(context, "foo")
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CANNOT_RESOLVE_CONCEPT)
|
||||
assert res.value.body == ('key', 'foo')
|
||||
|
||||
def test_i_cannot_parse_when_unknown_concept(self):
|
||||
context = self.get_context()
|
||||
|
||||
regex_parser = BnfParser()
|
||||
res = regex_parser.parse(self.get_context(), "foo")
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == ('key', 'foo')
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,193 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Token, TokenKind, Tokenizer
|
||||
from parsers.ConceptLexerParser import ConceptNode, UnrecognizedTokensNode, SourceCodeNode
|
||||
from parsers.ConceptsWithConceptsParser import ConceptsWithConceptsParser
|
||||
from parsers.MultipleConceptsParser import MultipleConceptsParser
|
||||
from parsers.PythonParser import PythonNode
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
multiple_concepts_parser = MultipleConceptsParser()
|
||||
|
||||
|
||||
def ret_val(*args):
|
||||
result = []
|
||||
index = 0
|
||||
source = ""
|
||||
for item in args:
|
||||
if isinstance(item, Concept):
|
||||
tokens = [Token(TokenKind.IDENTIFIER, item.name, 0, 0, 0)]
|
||||
result.append(ConceptNode(item, index, index, tokens, item.name))
|
||||
index += 1
|
||||
source += item.name
|
||||
elif isinstance(item, PythonNode):
|
||||
tokens = list(Tokenizer(item.source))[:-1] # strip trailing EOF
|
||||
result.append(SourceCodeNode(item, index, index + len(tokens) - 1, tokens, item.source))
|
||||
index += len(tokens)
|
||||
source += item.source
|
||||
else:
|
||||
tokens = list(Tokenizer(item))[:-1] # strip trailing EOF
|
||||
result.append(UnrecognizedTokensNode(index, index + len(tokens) - 1, tokens))
|
||||
index += len(tokens)
|
||||
source += item
|
||||
|
||||
return ReturnValueConcept(
|
||||
"who",
|
||||
False,
|
||||
ParserResultConcept(parser=multiple_concepts_parser, value=result, source=source))
|
||||
|
||||
|
||||
class TestConceptsWithConceptsParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def init(self, concepts, inputs):
|
||||
context = self.get_context()
|
||||
for concept in concepts:
|
||||
context.sheerka.create_new_concept(context, concept)
|
||||
|
||||
return context, ret_val(*inputs)
|
||||
|
||||
def execute(self, concepts, inputs):
|
||||
context, input_return_values = self.init(concepts, inputs)
|
||||
|
||||
parser = ConceptsWithConceptsParser()
|
||||
result = parser.parse(context, input_return_values.body)
|
||||
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
return context, parser, result, wrapper, return_value
|
||||
|
||||
@pytest.mark.parametrize("text, interested", [
|
||||
("not parser result", False),
|
||||
(ParserResultConcept(parser="not multiple_concepts_parser"), False),
|
||||
(ParserResultConcept(parser=multiple_concepts_parser, value=[]), True),
|
||||
])
|
||||
def test_not_interested(self, text, interested):
|
||||
context = self.get_context()
|
||||
|
||||
res = ConceptsWithConceptsParser().parse(context, text)
|
||||
if interested:
|
||||
assert res is not None
|
||||
else:
|
||||
assert res is None
|
||||
|
||||
def test_i_can_parse_composition_of_concepts(self):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
plus = Concept("a plus b").def_prop("a").def_prop("b")
|
||||
|
||||
context, parser, result, wrapper, return_value = self.execute([foo, bar, plus], [foo, " plus ", bar])
|
||||
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert result.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus bar"
|
||||
assert context.sheerka.isinstance(return_value, plus)
|
||||
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == bar
|
||||
|
||||
# sanity check, I can evaluate the result
|
||||
evaluated = context.sheerka.evaluate_concept(context, return_value)
|
||||
assert evaluated.key == return_value.key
|
||||
assert evaluated.get_prop("a") == foo.init_key()
|
||||
assert evaluated.get_prop("b") == bar.init_key()
|
||||
|
||||
def test_i_can_parse_when_composition_of_source_code(self):
|
||||
plus = Concept("a plus b", body="a + b").def_prop("a").def_prop("b")
|
||||
left = PythonNode("1+1", ast.parse("1+1", mode="eval"))
|
||||
right = PythonNode("2+2", ast.parse("2+2", mode="eval"))
|
||||
context, parser, result, wrapper, return_value = self.execute([plus], [left, " plus ", right])
|
||||
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert result.who == wrapper.parser.name
|
||||
assert wrapper.source == "1+1 plus 2+2"
|
||||
assert context.sheerka.isinstance(return_value, plus)
|
||||
|
||||
left_parser_result = ParserResultConcept(parser=parser, source="1+1", value=left)
|
||||
right_parser_result = ParserResultConcept(parser=parser, source="2+2", value=right)
|
||||
assert return_value.compiled["a"] == [ReturnValueConcept(parser.name, True, left_parser_result)]
|
||||
assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, right_parser_result)]
|
||||
|
||||
# sanity check, I can evaluate the result
|
||||
evaluated = context.sheerka.evaluate_concept(context, return_value)
|
||||
assert evaluated.key == return_value.key
|
||||
assert evaluated.get_prop("a") == 2
|
||||
assert evaluated.get_prop("b") == 4
|
||||
assert evaluated.body == 6
|
||||
|
||||
def test_i_can_parse_when_mix_of_concept_and_code(self):
|
||||
plus = Concept("a plus b").def_prop("a").def_prop("b")
|
||||
code = PythonNode("1+1", ast.parse("1+1", mode="eval"))
|
||||
foo = Concept("foo")
|
||||
context, parser, result, wrapper, return_value = self.execute([plus, foo], [foo, " plus ", code])
|
||||
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert result.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus 1+1"
|
||||
assert context.sheerka.isinstance(return_value, plus)
|
||||
|
||||
code_parser_result = ParserResultConcept(parser=parser, source="1+1", value=code)
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, code_parser_result)]
|
||||
|
||||
# sanity check, I can evaluate the result
|
||||
evaluated = context.sheerka.evaluate_concept(context, return_value)
|
||||
assert evaluated.key == return_value.key
|
||||
assert evaluated.get_prop("a") == foo.init_key()
|
||||
assert evaluated.get_prop("b") == 2
|
||||
|
||||
def test_i_can_parse_when_multiple_concepts_are_recognized(self):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
plus_1 = Concept("a plus b", body="body1").def_prop("a").def_prop("b")
|
||||
plus_2 = Concept("a plus b", body="body2").def_prop("a").def_prop("b")
|
||||
|
||||
context, input_return_values = self.init([foo, bar, plus_1, plus_2], [foo, " plus ", bar])
|
||||
parser = ConceptsWithConceptsParser()
|
||||
result = parser.parse(context, input_return_values.body)
|
||||
|
||||
assert len(result) == 2
|
||||
|
||||
res = result[0]
|
||||
wrapper = res.value
|
||||
return_value = res.value.value
|
||||
assert res.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert res.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus bar"
|
||||
assert context.sheerka.isinstance(return_value, plus_1)
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == bar
|
||||
|
||||
res = result[1]
|
||||
wrapper = res.value
|
||||
return_value = res.value.value
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert res.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus bar"
|
||||
assert context.sheerka.isinstance(return_value, plus_2)
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == bar
|
||||
|
||||
def test_i_cannot_parse_when_unknown_concept(self):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
|
||||
context, input_return_values = self.init([foo, bar], [foo, " plus ", bar])
|
||||
parser = ConceptsWithConceptsParser()
|
||||
result = parser.parse(context, input_return_values.body)
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
assert not result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.NOT_FOR_ME)
|
||||
assert result.who == parser.name
|
||||
assert return_value == input_return_values.body.body
|
||||
@@ -0,0 +1,345 @@
|
||||
import pytest
|
||||
import ast
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from parsers.ConceptLexerParser import OrderedChoice, StrMatch
|
||||
from parsers.PythonParser import PythonParser, PythonNode
|
||||
from core.tokenizer import Keywords, Tokenizer, LexerError
|
||||
from parsers.DefaultParser import DefaultParser, NameNode, SyntaxErrorNode, CannotHandleErrorNode, IsaConceptNode
|
||||
from parsers.DefaultParser import UnexpectedTokenErrorNode, DefConceptNode
|
||||
from parsers.BnfParser import BnfParser
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None):
|
||||
def_concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
|
||||
|
||||
if body:
|
||||
def_concept.body = get_concept_part(body)
|
||||
if where:
|
||||
def_concept.where = get_concept_part(where)
|
||||
if pre:
|
||||
def_concept.pre = get_concept_part(pre)
|
||||
if post:
|
||||
def_concept.post = get_concept_part(post)
|
||||
if definition:
|
||||
def_concept.definition = ReturnValueConcept(
|
||||
"parsers.Bnf",
|
||||
True,
|
||||
definition)
|
||||
|
||||
return def_concept
|
||||
|
||||
|
||||
def get_concept_part(part):
|
||||
if isinstance(part, str):
|
||||
node = PythonNode(part, ast.parse(part, mode="eval"))
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part,
|
||||
parser=PythonParser(),
|
||||
value=node))
|
||||
|
||||
if isinstance(part, PythonNode):
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part.source,
|
||||
parser=PythonParser(),
|
||||
value=part))
|
||||
|
||||
if isinstance(part, ReturnValueConcept):
|
||||
return part
|
||||
|
||||
|
||||
class TestDefaultParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("def concept hello", get_def_concept(name="hello")),
|
||||
("def concept hello ", get_def_concept(name="hello")),
|
||||
("def concept a + b", get_def_concept(name="a + b")),
|
||||
("def concept a+b", get_def_concept(name="a + b")),
|
||||
("def concept 'a+b'+c", get_def_concept(name="'a+b' + c")),
|
||||
("def concept 'as if'", get_def_concept(name="'as if'")),
|
||||
("def concept 'as' if", get_def_concept(name="'as if'")),
|
||||
("def concept hello as 'hello'", get_def_concept(name="hello", body="'hello'")),
|
||||
("def concept hello as 1", get_def_concept(name="hello", body="1")),
|
||||
("def concept hello as 1 + 1", get_def_concept(name="hello", body="1 + 1")),
|
||||
])
|
||||
def test_i_can_parse_def_concept(self, text, expected):
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
node = res.value.value
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert node == expected
|
||||
|
||||
def test_i_can_parse_complex_def_concept_statement(self):
|
||||
text = """def concept a plus b
|
||||
where a,b
|
||||
pre isinstance(a, int) and isinstance(b, float)
|
||||
post isinstance(res, int)
|
||||
as res = a + b
|
||||
"""
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
return_value = res.value
|
||||
expected_concept = get_def_concept(
|
||||
name="a plus b",
|
||||
where="a,b",
|
||||
pre="isinstance(a, int) and isinstance(b, float)",
|
||||
post="isinstance(res, int)",
|
||||
body=PythonNode("res = a + b", ast.parse("res = a + b", mode="exec"))
|
||||
)
|
||||
|
||||
assert res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert return_value.value == expected_concept
|
||||
|
||||
def test_i_can_have_mutilines_declarations(self):
|
||||
text = """
|
||||
def concept add one to a as
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
|
||||
expected_concept = get_def_concept(
|
||||
name="add one to a ",
|
||||
body=PythonNode(
|
||||
"def func(x):\n return x+1\nfunc(a)",
|
||||
ast.parse("def func(x):\n return x+1\nfunc(a)", mode="exec"))
|
||||
)
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert return_value.value == expected_concept
|
||||
|
||||
def test_i_can_use_colon_to_use_indentation(self):
|
||||
text = """
|
||||
def concept add one to a as:
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
|
||||
expected_concept = get_def_concept(
|
||||
name="add one to a ",
|
||||
body=PythonNode(
|
||||
"def func(x):\n return x+1\nfunc(a)",
|
||||
ast.parse("def func(x):\n return x+1\nfunc(a)", mode="exec"))
|
||||
)
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert return_value.value == expected_concept
|
||||
|
||||
def test_indentation_is_mandatory_after_a_colon(self):
|
||||
text = """
|
||||
def concept add one to a as:
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert isinstance(return_value.value[0], SyntaxErrorNode)
|
||||
assert return_value.value[0].message == "Indentation not found."
|
||||
|
||||
def test_indentation_is_not_allowed_if_the_colon_is_missing(self):
|
||||
text = """
|
||||
def concept add one to a as
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
context = self.get_context()
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(return_value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
|
||||
def test_name_is_mandatory(self):
|
||||
text = "def concept as 'hello'"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert isinstance(return_value.value[0], SyntaxErrorNode)
|
||||
assert return_value.value[0].message == "Name is mandatory"
|
||||
|
||||
def test_concept_keyword_is_mandatory_but_the_concept_is_recognized(self):
|
||||
text = "def hello as a where b pre c post d"
|
||||
|
||||
expected_concept = get_def_concept(name="hello", body="a", where="b", pre="c", post="d")
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert isinstance(return_value.value[0], UnexpectedTokenErrorNode)
|
||||
assert return_value.value[0].message == "Syntax error."
|
||||
assert return_value.value[0].expected_tokens == [Keywords.CONCEPT]
|
||||
assert return_value.try_parsed == expected_concept
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"def concept hello where 1+",
|
||||
"def concept hello pre 1+",
|
||||
"def concept hello post 1+",
|
||||
"def concept hello as 1+"
|
||||
])
|
||||
def test_i_can_detect_error_in_declaration(self, text):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(return_value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
|
||||
def test_new_line_is_not_allowed_in_the_name(self):
|
||||
text = "def concept hello \n my friend as 'hello'"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert return_value.value == [SyntaxErrorNode([], "Newline are not allowed in name.")]
|
||||
|
||||
def test_i_can_parse_def_concept_from_regex(self):
|
||||
context = self.get_context()
|
||||
a_concept = Concept("a_concept")
|
||||
context.sheerka.add_in_cache(a_concept)
|
||||
|
||||
text = "def concept name from bnf a_concept | 'a_string' as __definition[0]"
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
node = res.value.value
|
||||
definition = OrderedChoice(a_concept, StrMatch("a_string"))
|
||||
parser_result = ParserResultConcept(BnfParser(), "a_concept | 'a_string'", definition, definition)
|
||||
expected = get_def_concept(name="name", body="__definition[0]", definition=parser_result)
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert node == expected
|
||||
|
||||
def test_i_can_parse_def_concept_where_bnf_references_itself(self):
|
||||
context = self.get_context()
|
||||
a_concept = Concept("a_concept")
|
||||
context.sheerka.add_in_cache(a_concept)
|
||||
|
||||
text = "def concept name from bnf 'a' + name?"
|
||||
parser = DefaultParser()
|
||||
parser.parse(context, text)
|
||||
|
||||
assert not parser.has_error
|
||||
|
||||
def test_i_can_detect_empty_bnf_declaration(self):
|
||||
text = "def concept name from bnf as __definition[0]"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert res.value.value[0] == SyntaxErrorNode([], "Empty declaration")
|
||||
|
||||
def test_i_can_detect_not_for_me(self):
|
||||
text = "hello world"
|
||||
context = self.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)
|
||||
|
||||
def test_i_can_parse_is_a(self):
|
||||
parser = DefaultParser()
|
||||
text = "the name of my 'concept' isa the name of the set"
|
||||
res = parser.parse(self.get_context(), text)
|
||||
expected = IsaConceptNode([],
|
||||
concept=NameNode(list(Tokenizer("the name of my 'concept'"))),
|
||||
set=NameNode(list(Tokenizer("the name of the set"))))
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert res.value.value == expected
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"concept",
|
||||
"isa number",
|
||||
"name isa",
|
||||
"def",
|
||||
"def concept_name"
|
||||
])
|
||||
def test_i_cannot_parse_invalid_entries(self, text):
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(res.body, ParserResultConcept)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
|
||||
@pytest.mark.parametrize("text, error_msg, error_text", [
|
||||
("'name", "Missing Trailing quote", "'name"),
|
||||
("foo isa 'name", "Missing Trailing quote", "'name"),
|
||||
("def concept 'name", "Missing Trailing quote", "'name"),
|
||||
("def concept name as 'body", "Missing Trailing quote", "'body"),
|
||||
("def concept name from bnf 'expression", "Missing Trailing quote", "'expression"),
|
||||
("def concept c::", "Concept name not found", ""),
|
||||
])
|
||||
def test_i_cannot_parse_when_tokenizer_fails(self, text, error_msg, error_text):
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(res.body, ParserResultConcept)
|
||||
assert isinstance(res.body.body[0], LexerError)
|
||||
assert res.body.body[0].message == error_msg
|
||||
assert res.body.body[0].text == error_text
|
||||
|
||||
def test_i_cannot_parse_bnf_definition_referencing_unknown_concept(self):
|
||||
context = self.get_context()
|
||||
text = "def concept name from bnf unknown"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == ("key", "unknown")
|
||||
@@ -0,0 +1,138 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Tokenizer
|
||||
from parsers.ExactConceptParser import ExactConceptParser
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def metadata_prop(concept, prop_name):
|
||||
for name, value in concept.metadata.props:
|
||||
if name == prop_name:
|
||||
return value
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_concept(name, variables):
|
||||
c = Concept(name=name)
|
||||
if variables:
|
||||
for v in variables:
|
||||
c.def_prop(v)
|
||||
c.init_key()
|
||||
return c
|
||||
|
||||
|
||||
class TestExactConceptParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_compute_combinations(self):
|
||||
parser = ExactConceptParser()
|
||||
res = parser.combinations(["foo", "bar", "baz"])
|
||||
|
||||
assert res == {('foo', 'bar', 'baz'),
|
||||
('__var__0', 'bar', 'baz'),
|
||||
('foo', '__var__0', 'baz'),
|
||||
('foo', 'bar', '__var__0'),
|
||||
('__var__0', '__var__1', 'baz'),
|
||||
('__var__0', 'bar', '__var__1'),
|
||||
('foo', '__var__0', '__var__1'),
|
||||
('__var__0', '__var__1', '__var__2')}
|
||||
|
||||
def test_i_can_compute_combinations_with_duplicates(self):
|
||||
parser = ExactConceptParser()
|
||||
res = parser.combinations(["foo", "bar", "foo"])
|
||||
|
||||
assert res == {('foo', 'bar', 'foo'),
|
||||
('__var__0', 'bar', '__var__0'),
|
||||
('foo', '__var__0', 'foo'),
|
||||
('__var__0', '__var__1', '__var__0'),
|
||||
('__var__1', '__var__0', '__var__1')}
|
||||
# TODO: the last tuple is not possible, so the algo can be improved
|
||||
|
||||
def test_i_can_recognize_a_simple_concept(self):
|
||||
context = self.get_context()
|
||||
concept = get_concept("hello world", [])
|
||||
context.sheerka.add_in_cache(concept)
|
||||
|
||||
source = "hello world"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
assert results[0].value.value == concept
|
||||
|
||||
def test_i_can_recognize_concepts_defined_several_times(self):
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(get_concept("hello world", []))
|
||||
context.sheerka.add_in_cache(get_concept("hello a", ["a"]))
|
||||
|
||||
source = "hello world"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 2
|
||||
results = sorted(results, key=lambda x: x.value.value.name) # because of the usage of sets
|
||||
|
||||
assert results[0].status
|
||||
assert results[0].value.value.name == "hello a"
|
||||
assert metadata_prop(results[0].value.value, "a") == "world"
|
||||
|
||||
assert results[1].status
|
||||
assert results[1].value.value.name == "hello world"
|
||||
|
||||
def test_i_can_recognize_a_concept_with_variables(self):
|
||||
context = self.get_context()
|
||||
concept = get_concept("a + b", ["a", "b"])
|
||||
context.sheerka.add_in_cache(concept)
|
||||
source = "10 + 5"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
concept_found = results[0].value.value
|
||||
assert concept_found.key == concept.key
|
||||
assert metadata_prop(concept_found, "a") == "10"
|
||||
assert metadata_prop(concept_found, "b") == "5"
|
||||
|
||||
def test_i_can_recognize_a_concept_with_duplicate_variables(self):
|
||||
context = self.get_context()
|
||||
concept = get_concept("a + b + a", ["a", "b"])
|
||||
context.sheerka.cache_by_key[concept.key] = concept
|
||||
source = "10 + 5 + 10"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
concept_found = results[0].value.value
|
||||
assert concept_found.key == concept.key
|
||||
assert metadata_prop(concept_found, "a") == "10"
|
||||
assert metadata_prop(concept_found, "b") == "5"
|
||||
|
||||
def test_i_can_manage_unknown_concept(self):
|
||||
context = self.get_context()
|
||||
source = "def concept hello world" # this is not a concept by itself
|
||||
res = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == "def concept hello world"
|
||||
|
||||
def test_i_can_detect_concepts_too_long(self):
|
||||
context = self.get_context()
|
||||
source = "a very very long concept that cannot be an unique one"
|
||||
res = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_TOO_LONG)
|
||||
assert res.value.body == "a very very long concept that cannot be an unique one"
|
||||
|
||||
def test_i_can_detect_concept_from_tokens(self):
|
||||
context = self.get_context()
|
||||
concept = get_concept("hello world", [])
|
||||
context.sheerka.add_in_cache(concept)
|
||||
|
||||
source = "hello world"
|
||||
results = ExactConceptParser().parse(context, list(Tokenizer(source)))
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
assert results[0].value.value == concept
|
||||
@@ -0,0 +1,215 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Tokenizer, TokenKind, Token
|
||||
from parsers.ConceptLexerParser import ConceptLexerParser, ConceptNode, Sequence, cnode, utnode, scnode, SourceCodeNode
|
||||
from parsers.MultipleConceptsParser import MultipleConceptsParser
|
||||
from parsers.PythonParser import PythonNode
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def get_return_value(context, grammar, expression):
|
||||
parser = ConceptLexerParser()
|
||||
parser.initialize(context, grammar)
|
||||
|
||||
ret_val = parser.parse(context, expression)
|
||||
assert not ret_val.status
|
||||
return ret_val
|
||||
|
||||
|
||||
class TestMultipleConceptsParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def init(self, concepts, grammar, expression):
|
||||
context = self.get_context()
|
||||
for c in concepts:
|
||||
context.sheerka.create_new_concept(context, c)
|
||||
return_value = get_return_value(context, grammar, expression)
|
||||
|
||||
return context, return_value
|
||||
|
||||
def test_not_interested_if_not_parser_result(self):
|
||||
context = self.get_context()
|
||||
text = "not parser result"
|
||||
|
||||
res = MultipleConceptsParser().parse(context, text)
|
||||
assert res is None
|
||||
|
||||
def test_not_interested_if_not_from_concept_lexer_parser(self):
|
||||
context = self.get_context()
|
||||
text = ParserResultConcept(parser="not concept lexer", value="some value")
|
||||
|
||||
res = MultipleConceptsParser().parse(context, text)
|
||||
assert res is None
|
||||
|
||||
def test_i_can_parse_exact_concepts(self):
|
||||
foo = Concept("foo", body="'foo'")
|
||||
bar = Concept("bar", body="'bar'")
|
||||
baz = Concept("baz", body="'baz'")
|
||||
grammar = {}
|
||||
context, return_value = self.init([foo, bar, baz], grammar, "bar foo baz")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
ConceptNode(bar, 0, 0, source="bar"),
|
||||
ConceptNode(foo, 2, 2, source="foo"),
|
||||
ConceptNode(baz, 4, 4, source="baz")]
|
||||
assert ret_val.value.source == "bar foo baz"
|
||||
|
||||
def test_i_can_parse_when_ending_with_bnf(self):
|
||||
foo = Concept("foo", body="'foo'")
|
||||
bar = Concept("bar", body="'bar'")
|
||||
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
|
||||
context, return_value = self.init([foo, bar], grammar, "bar foo1 foo2 foo3")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [cnode("bar", 0, 0, "bar"), cnode("foo", 2, 6, "foo1 foo2 foo3")]
|
||||
assert ret_val.value.source == "bar foo1 foo2 foo3"
|
||||
|
||||
def test_i_can_parse_when_starting_with_bnf(self):
|
||||
foo = Concept("foo", body="'foo'")
|
||||
bar = Concept("bar", body="'bar'")
|
||||
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
|
||||
context, return_value = self.init([foo, bar], grammar, "foo1 foo2 foo3 bar")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [cnode("foo", 0, 4, "foo1 foo2 foo3"), cnode("bar", 6, 6, "bar")]
|
||||
assert ret_val.value.source == "foo1 foo2 foo3 bar"
|
||||
|
||||
def test_i_can_parse_when_concept_are_mixed(self):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
baz = Concept("baz")
|
||||
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
|
||||
context, return_value = self.init([foo, bar, baz], grammar, "baz foo1 foo2 foo3 bar")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
cnode("baz", 0, 0, "baz"),
|
||||
cnode("foo", 2, 6, "foo1 foo2 foo3"),
|
||||
cnode("bar", 8, 8, "bar")]
|
||||
assert ret_val.value.source == "baz foo1 foo2 foo3 bar"
|
||||
|
||||
def test_i_can_parse_when_multiple_concepts_are_matching(self):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar", body="bar1")
|
||||
baz = Concept("bar", body="bar2")
|
||||
grammar = {foo: "foo"}
|
||||
context, return_value = self.init([foo, bar, baz], grammar, "foo bar")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert len(ret_val) == 2
|
||||
assert ret_val[0].status
|
||||
assert ret_val[0].value.value == [cnode("foo", 0, 0, "foo"), cnode("bar", 2, 2, "bar")]
|
||||
assert ret_val[0].value.source == "foo bar"
|
||||
assert ret_val[0].value.value[1].concept.metadata.body == "bar1"
|
||||
|
||||
assert ret_val[1].status
|
||||
assert ret_val[1].value.value == [cnode("foo", 0, 0, "foo"), cnode("bar", 2, 2, "bar")]
|
||||
assert ret_val[1].value.source == "foo bar"
|
||||
assert ret_val[1].value.value[1].concept.metadata.body == "bar2"
|
||||
|
||||
def test_i_can_parse_when_source_code(self):
|
||||
foo = Concept("foo")
|
||||
grammar = {foo: "foo"}
|
||||
context, return_value = self.init([foo], grammar, "1 foo")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
wrapper = ret_val.value
|
||||
value = ret_val.value.value
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.source == "1 foo"
|
||||
assert value == [
|
||||
scnode(0, 1, "1 "),
|
||||
cnode("foo", 2, 2, "foo")]
|
||||
|
||||
def test_i_cannot_parse_when_unrecognized_token(self):
|
||||
twenty_two = Concept("twenty two")
|
||||
one = Concept("one")
|
||||
grammar = {twenty_two: Sequence("twenty", "two")}
|
||||
context, return_value = self.init([twenty_two, one], grammar, "twenty two + one")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert not ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
cnode("twenty two", 0, 2, "twenty two"),
|
||||
utnode(3, 5, " + "),
|
||||
cnode("one", 6, 6, "one")
|
||||
]
|
||||
assert ret_val.value.source == "twenty two + one"
|
||||
|
||||
def test_i_cannot_parse_when_unknown_concepts(self):
|
||||
twenty_two = Concept("twenty two")
|
||||
one = Concept("one")
|
||||
grammar = {twenty_two: Sequence("twenty", "two")}
|
||||
context, return_value = self.init([twenty_two, one], grammar, "twenty two plus one")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert not ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
cnode("twenty two", 0, 2, "twenty two"),
|
||||
utnode(3, 5, " plus "),
|
||||
cnode("one", 6, 6, "one")
|
||||
]
|
||||
assert ret_val.value.source == "twenty two plus one"
|
||||
|
||||
@pytest.mark.parametrize("text, expected_source, expected_end", [
|
||||
("True", "True", 0),
|
||||
("1 == 1", "1 == 1", 5),
|
||||
("1!xdf", "1", 0),
|
||||
("1", "1", 0),
|
||||
])
|
||||
def test_i_can_get_source_code_node(self, text, expected_source, expected_end):
|
||||
tokens = list(Tokenizer(text))[:-1] # strip trailing EOF
|
||||
|
||||
start_index = 5 # a random number different of zero
|
||||
res = MultipleConceptsParser().get_source_code_node(self.get_context(), start_index, tokens)
|
||||
|
||||
assert isinstance(res, SourceCodeNode)
|
||||
assert isinstance(res.node, PythonNode)
|
||||
assert res.source == expected_source
|
||||
assert res.start == start_index
|
||||
assert res.end == start_index + expected_end
|
||||
|
||||
def test_i_cannot_parse_null_text(self):
|
||||
res = MultipleConceptsParser().get_source_code_node(self.get_context(), 0, [])
|
||||
assert res is None
|
||||
|
||||
eof = Token(TokenKind.EOF, "", 0, 0, 0)
|
||||
res = MultipleConceptsParser().get_source_code_node(self.get_context(), 0, [eof])
|
||||
assert res is None
|
||||
@@ -0,0 +1,77 @@
|
||||
import ast
|
||||
import pytest
|
||||
from core.builtin_concepts import ParserResultConcept
|
||||
from core.tokenizer import Tokenizer, LexerError
|
||||
from parsers.PythonParser import PythonNode, PythonParser, PythonErrorNode
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestPythonParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1+1", PythonNode("1+1", ast.parse("1+1", mode="eval"))),
|
||||
("a=10", PythonNode("a=10", ast.parse("a=10", mode="exec"))),
|
||||
])
|
||||
def test_i_can_parse_a_simple_expression(self, text, expected):
|
||||
parser = PythonParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert res.value.value == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1+1", PythonNode("1+1", ast.parse("1+1", mode="eval"))),
|
||||
("a=10", PythonNode("a=10", ast.parse("a=10", mode="exec"))),
|
||||
])
|
||||
def test_i_can_parse_from_tokens(self, text, expected):
|
||||
parser = PythonParser()
|
||||
tokens = list(Tokenizer(text))
|
||||
res = parser.parse(self.get_context(), tokens)
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert res.value.value == expected
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"1+",
|
||||
"'name",
|
||||
"foo = 'name"
|
||||
])
|
||||
def test_i_can_detect_error(self, text):
|
||||
parser = PythonParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert res.who == parser.name
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert isinstance(res.value.value[0], PythonErrorNode)
|
||||
assert isinstance(res.value.value[0].exception, SyntaxError)
|
||||
|
||||
@pytest.mark.parametrize("text, error_msg, error_text", [
|
||||
("c::", "Concept name not found", ""),
|
||||
("c:: + 1", "Concept name not found", ""),
|
||||
])
|
||||
def test_i_can_detect_lexer_errors(self, text, error_msg, error_text):
|
||||
parser = PythonParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(res.body, ParserResultConcept)
|
||||
assert isinstance(res.body.body[0], LexerError)
|
||||
assert res.body.body[0].message == error_msg
|
||||
assert res.body.body[0].text == error_text
|
||||
|
||||
def test_i_can_parse_a_concept(self):
|
||||
text = "c:concept_name: + 1"
|
||||
|
||||
parser = PythonParser()
|
||||
res = parser.parse(self.get_context(), text)
|
||||
|
||||
assert res
|
||||
assert res.value.value == PythonNode(
|
||||
"c:concept_name: + 1",
|
||||
ast.parse("__C__USE_CONCEPT__concept_name__C__+1", mode="eval"))
|
||||
@@ -0,0 +1,138 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Token, TokenKind, Tokenizer
|
||||
from parsers.ConceptLexerParser import ConceptNode, UnrecognizedTokensNode
|
||||
from parsers.MultipleConceptsParser import MultipleConceptsParser
|
||||
from parsers.PythonParser import PythonNode, PythonErrorNode
|
||||
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
multiple_concepts_parser = MultipleConceptsParser()
|
||||
|
||||
|
||||
def ret_val(*args):
|
||||
result = []
|
||||
index = 0
|
||||
for item in args:
|
||||
if isinstance(item, Concept):
|
||||
tokens = [Token(TokenKind.IDENTIFIER, item.name, 0, 0, 0)]
|
||||
result.append(ConceptNode(item, index, index, tokens, item.name))
|
||||
index += 1
|
||||
else:
|
||||
tokens = list(Tokenizer(item))
|
||||
result.append(UnrecognizedTokensNode(index, index + len(tokens) - 1, tokens))
|
||||
index += len(tokens)
|
||||
|
||||
return ReturnValueConcept("who", False, ParserResultConcept(parser=multiple_concepts_parser, value=result))
|
||||
|
||||
|
||||
def to_str_ast(expression):
|
||||
return PythonNode.get_dump(ast.parse(expression, mode="eval"))
|
||||
|
||||
|
||||
class TestPythonWithConceptsParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("text, interested", [
|
||||
("not parser result", False),
|
||||
(ParserResultConcept(parser="not multiple_concepts_parser"), False),
|
||||
(ParserResultConcept(parser=multiple_concepts_parser, value=[]), True),
|
||||
])
|
||||
def test_not_interested(self, text, interested):
|
||||
context = self.get_context()
|
||||
|
||||
res = PythonWithConceptsParser().parse(context, text)
|
||||
if interested:
|
||||
assert res is not None
|
||||
else:
|
||||
assert res is None
|
||||
|
||||
def test_i_can_parse_concepts_and_python(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo")
|
||||
input_return_value = ret_val(foo, " + 1")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
wrapper = result.value
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert result.who == parser.name
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.source == "foo + 1"
|
||||
assert isinstance(return_value, PythonNode)
|
||||
assert return_value.source == "foo + 1"
|
||||
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__C__ + 1")
|
||||
assert return_value.concepts["__C__foo__C__"] == foo
|
||||
|
||||
def test_i_can_parse_concepts_and_python_when_concept_is_known(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo")
|
||||
foo = context.sheerka.create_new_concept(context, foo).body.body
|
||||
input_return_value = ret_val(foo, " + 1")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
wrapper = result.value
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert result.who == parser.name
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.source == "foo + 1"
|
||||
assert isinstance(return_value, PythonNode)
|
||||
assert return_value.source == "foo + 1"
|
||||
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__1001__C__ + 1")
|
||||
assert return_value.concepts["__C__foo__1001__C__"] == foo
|
||||
|
||||
def test_i_can_parse_when_concept_name_has_invalid_characters(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo et > (,")
|
||||
foo = context.sheerka.create_new_concept(context, foo).body.body
|
||||
input_return_value = ret_val(foo, " + 1")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert return_value.concepts["__C__foo0et000000__1001__C__"] == foo
|
||||
|
||||
def test_python_ids_mappings_are_correct_when_concepts_with_the_same_name(self):
|
||||
context = self.get_context()
|
||||
foo1 = Concept("foo")
|
||||
foo2 = Concept("foo")
|
||||
foo3 = context.sheerka.create_new_concept(context, Concept("foo", body="foo3")).body.body
|
||||
foo4 = context.sheerka.create_new_concept(context, Concept("foo", body="foo4")).body.body
|
||||
|
||||
input_return_value = ret_val(foo1, "+", foo2, "+", foo3, "+", foo4)
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert return_value.concepts["__C__foo__C__"] == foo1
|
||||
assert return_value.concepts["__C__foo_1__C__"] == foo2
|
||||
assert return_value.concepts["__C__foo__1001__C__"] == foo3
|
||||
assert return_value.concepts["__C__foo__1002__C__"] == foo4
|
||||
|
||||
def test_i_cannot_parse_if_syntax_error(self):
|
||||
context = self.get_context()
|
||||
foo = Concept("foo")
|
||||
foo = context.sheerka.create_new_concept(context, foo).body.body
|
||||
input_return_value = ret_val(foo, " + ")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
wrapper = result.value
|
||||
return_value = result.value.value
|
||||
|
||||
assert not result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert isinstance(return_value[0], PythonErrorNode)
|
||||
@@ -12,7 +12,7 @@ import json
|
||||
from sdp.sheerkaSerializer import JsonSerializer, Serializer, PickleSerializer
|
||||
import core.utils
|
||||
|
||||
tests_root = path.abspath("../build/tests")
|
||||
tests_root = path.abspath("../../build/tests")
|
||||
evt_digest = "3a571cb6034ef6fc8d7fe91948d0d29728eed74de02bac7968b0e9facca2c2d7"
|
||||
|
||||
|
||||
@@ -821,17 +821,17 @@ def test_i_can_set_using_reference(root):
|
||||
entry, key = sdp.set(evt_digest, "entry", ObjWithKey(2, "foo"), use_ref=True)
|
||||
|
||||
state = sdp.load_state(sdp.get_snapshot())
|
||||
assert state.data == {"entry": {"2": '##REF##:95b5cbab545dded0b90b57a3d15a157b9a559fb586ee2f8d6ccbc6d2491f1268'}}
|
||||
assert state.data == {"entry": {"2": '##REF##:43f07065c7bad051cdd726bdfa4de7f8d754c31486c65ddb31d6b6548dec3db9'}}
|
||||
assert entry == "entry"
|
||||
assert key == "2"
|
||||
|
||||
assert sdp.io.exists(sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder,
|
||||
"95b5cbab545dded0b90b57a3d15a157b9a559fb586ee2f8d6ccbc6d2491f1268"))
|
||||
"43f07065c7bad051cdd726bdfa4de7f8d754c31486c65ddb31d6b6548dec3db9"))
|
||||
|
||||
# sanity check, make sure that I can load back
|
||||
loaded = sdp.get(entry, key)
|
||||
assert loaded == ObjWithKey(2, "foo")
|
||||
assert getattr(loaded, Serializer.ORIGIN) == "95b5cbab545dded0b90b57a3d15a157b9a559fb586ee2f8d6ccbc6d2491f1268"
|
||||
assert getattr(loaded, Serializer.ORIGIN) == "43f07065c7bad051cdd726bdfa4de7f8d754c31486c65ddb31d6b6548dec3db9"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
@@ -1430,7 +1430,7 @@ def test_i_can_modify_a_ref(root):
|
||||
state = sdp.load_state(sdp.get_snapshot())
|
||||
assert state.data == {"entry": {
|
||||
"key1": ObjWithKey("key1", "foo"),
|
||||
"key2": "##REF##:d70b0247311645ed18d275337cbcf79ad186d995236cdc8ad4fcfc708085bd3d"}}
|
||||
"key2": "##REF##:041d3cca905b51bc2c66251e73e56b836aae7b9435ee3d7eb05d44bb67ff575e"}}
|
||||
assert entry == "entry"
|
||||
assert key == "key2"
|
||||
|
||||
@@ -37,7 +37,7 @@ def test_i_can_serialize_an_event():
|
||||
def test_i_can_serialize_an_object():
|
||||
obj = Obj("10", "value")
|
||||
serializer = Serializer()
|
||||
serializer.register(JsonSerializer("tests.test_sheerkaSerializer.Obj"))
|
||||
serializer.register(JsonSerializer("tests.sdp.test_sheerkaSerializer.Obj"))
|
||||
context = SerializerContext("kodjo", "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b")
|
||||
|
||||
stream = serializer.serialize(obj, context)
|
||||
@@ -51,7 +51,7 @@ def test_i_can_serialize_an_object():
|
||||
|
||||
|
||||
@pytest.mark.parametrize("obj, expected", [
|
||||
(Obj("10", "value"), "tests.test_sheerkaSerializer.Obj")
|
||||
(Obj("10", "value"), "tests.sdp.test_sheerkaSerializer.Obj")
|
||||
])
|
||||
def test_get_full_qualified_name(obj, expected):
|
||||
assert expected == core.utils.get_full_qualified_name(obj)
|
||||
@@ -1,194 +0,0 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import VARIABLE_PREFIX, ConceptParts, Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Tokenizer
|
||||
from evaluators.AddConceptEvaluator import AddConceptEvaluator
|
||||
from parsers.BaseParser import BaseParser
|
||||
from parsers.ConceptLexerParser import Sequence, StrMatch, ZeroOrMore, ConceptExpression
|
||||
from parsers.BnfParser import BnfParser
|
||||
from parsers.DefaultParser import DefConceptNode, NameNode
|
||||
from parsers.PythonParser import PythonNode, PythonParser
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None):
|
||||
concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
|
||||
|
||||
if body:
|
||||
concept.body = get_concept_part(body)
|
||||
if where:
|
||||
concept.where = get_concept_part(where)
|
||||
if pre:
|
||||
concept.pre = get_concept_part(pre)
|
||||
if post:
|
||||
concept.post = get_concept_part(post)
|
||||
if definition:
|
||||
concept.definition = definition
|
||||
|
||||
return ReturnValueConcept(BaseParser.PREFIX + "some_name", True, ParserResultConcept(value=concept))
|
||||
|
||||
|
||||
def get_concept_part(part):
|
||||
if isinstance(part, str):
|
||||
node = PythonNode(part, ast.parse(part, mode="eval"))
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part,
|
||||
parser=PythonParser(),
|
||||
value=node))
|
||||
|
||||
if isinstance(part, PythonNode):
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part.source,
|
||||
parser=PythonParser(),
|
||||
value=part))
|
||||
|
||||
if isinstance(part, ReturnValueConcept):
|
||||
return part
|
||||
|
||||
|
||||
def get_concept_definition(source, parsing_expression):
|
||||
return ReturnValueConcept(
|
||||
who="Parsers:RegexParser",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=source,
|
||||
parser=BnfParser(),
|
||||
value=parsing_expression
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept(BaseParser.PREFIX + "some_name", True, ParserResultConcept(value=DefConceptNode([]))), True),
|
||||
(ReturnValueConcept(BaseParser.PREFIX + "some_name", False, ParserResultConcept(value=DefConceptNode([]))), False),
|
||||
(ReturnValueConcept(BaseParser.PREFIX + "some_name", True, "not a ParserResultConcept"), False),
|
||||
(ReturnValueConcept(BaseParser.PREFIX + "some_name", True, ParserResultConcept()), False),
|
||||
])
|
||||
def test_i_can_match(ret_val, expected):
|
||||
context = get_context()
|
||||
assert AddConceptEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
|
||||
def test_that_the_source_is_correctly_set():
|
||||
context = get_context()
|
||||
def_concept_return_value = get_def_concept(
|
||||
name="hello a",
|
||||
definition=get_concept_definition("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
|
||||
where="isinstance(a, str )",
|
||||
pre="a is not None",
|
||||
body="print('hello' + a)")
|
||||
|
||||
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
|
||||
|
||||
assert evaluated.status
|
||||
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
created_concept = evaluated.body.body
|
||||
assert created_concept.metadata.name == "hello a"
|
||||
assert created_concept.metadata.where == "isinstance(a, str )"
|
||||
assert created_concept.metadata.pre == "a is not None"
|
||||
assert created_concept.metadata.post is None
|
||||
assert created_concept.metadata.body == "print('hello' + a)"
|
||||
assert created_concept.metadata.definition == "hello a"
|
||||
|
||||
|
||||
# def test_that_the_ast_is_correctly_initialized():
|
||||
# """
|
||||
# When I parse the definition of a concept, I evaluate the metadata (like the body)
|
||||
# I wanted to keep in cache these evaluation for further utilisation but I have
|
||||
# a serialization issue.
|
||||
# So I had to comment concept.add_codes(def_concept_node.get_asts()) around line 85
|
||||
# So this test is now irrelevant
|
||||
# :return:
|
||||
# """
|
||||
# context = get_context()
|
||||
# def_concept_return_value = get_concept(
|
||||
# name="hello a",
|
||||
# definition=get_concept_definition("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
|
||||
# where="isinstance(a, str )",
|
||||
# pre="a is not None",
|
||||
# body="print('hello' + a)")
|
||||
#
|
||||
# evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
|
||||
#
|
||||
# assert evaluated.status
|
||||
# assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||
#
|
||||
# created_concept = evaluated.body.body
|
||||
#
|
||||
# assert ConceptParts.WHERE in created_concept.compiled
|
||||
# assert ConceptParts.PRE in created_concept.compiled
|
||||
# assert ConceptParts.BODY in created_concept.compiled
|
||||
# assert ConceptParts.POST not in created_concept.compiled
|
||||
|
||||
|
||||
def test_that_the_new_concept_is_correctly_saved_in_db():
|
||||
context = get_context()
|
||||
def_concept_return_value = get_def_concept(
|
||||
name="hello a",
|
||||
definition=get_concept_definition("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
|
||||
where="isinstance(a, str )",
|
||||
pre="a is not None",
|
||||
body="print('hello' + a)")
|
||||
|
||||
# sanity. Make sure that the concept does not already exist
|
||||
from_db = context.sheerka.get("hello " + VARIABLE_PREFIX + "0")
|
||||
assert context.sheerka.isinstance(from_db, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
|
||||
AddConceptEvaluator().eval(context, def_concept_return_value)
|
||||
context.sheerka.concepts_cache = {} # reset cache
|
||||
from_db = context.sheerka.get("hello " + VARIABLE_PREFIX + "0")
|
||||
|
||||
assert from_db.metadata.key == f"hello {VARIABLE_PREFIX}0"
|
||||
assert from_db.metadata.name == "hello a"
|
||||
assert from_db.metadata.where == "isinstance(a, str )"
|
||||
assert from_db.metadata.pre == "a is not None"
|
||||
assert from_db.metadata.post is None
|
||||
assert from_db.metadata.body == "print('hello' + a)"
|
||||
assert from_db.metadata.definition == "hello a"
|
||||
assert len(from_db.metadata.props) == 1
|
||||
assert from_db.metadata.props[0] == ("a", None)
|
||||
assert "a" in from_db.props
|
||||
|
||||
assert from_db.compiled == {} # ast is not saved in db
|
||||
|
||||
|
||||
def test_i_can_get_props_from_python_node():
|
||||
ret_val = get_concept_part("isinstance(a, str)")
|
||||
context = get_context()
|
||||
|
||||
assert AddConceptEvaluator.get_props(context.sheerka, ret_val, ["a"]) == ["a"]
|
||||
|
||||
|
||||
def test_i_can_get_props_from_another_concept():
|
||||
concept = Concept("hello").def_prop("a").def_prop("b")
|
||||
ret_val = ReturnValueConcept(who="some_parser",
|
||||
status=True,
|
||||
value=ParserResultConcept(value=concept))
|
||||
|
||||
assert AddConceptEvaluator.get_props(get_context(), ret_val, []) == ["a", "b"]
|
||||
|
||||
|
||||
def test_i_can_get_props_from_definition():
|
||||
parsing_expression = Sequence(ConceptExpression('mult'), ZeroOrMore(Sequence(StrMatch("+"), ConceptExpression("add"))))
|
||||
ret_val = get_concept_definition("mult (('+'|'-') add)?", parsing_expression)
|
||||
|
||||
assert AddConceptEvaluator.get_props(get_context(), ret_val, []) == ["add", "mult"]
|
||||
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Tokenizer
|
||||
from evaluators.AddConceptInSetEvaluator import AddConceptInSetEvaluator
|
||||
from parsers.DefaultParser import IsaConceptNode, NameNode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_ret_val(concept_name, concept_set_name):
|
||||
n1 = NameNode(list(Tokenizer(concept_name)))
|
||||
n2 = NameNode(list(Tokenizer(concept_set_name)))
|
||||
|
||||
return ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([], n1, n2)))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([]))), True),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=IsaConceptNode([]))), False),
|
||||
(ReturnValueConcept("some_name", True, "not a ParserResultConcept"), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept()), False),
|
||||
])
|
||||
def test_i_can_match(ret_val, expected):
|
||||
context = get_context()
|
||||
assert AddConceptInSetEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
|
||||
def test_i_cannot_add_if_the_concept_does_not_exists():
|
||||
context = get_context()
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == "foo"
|
||||
|
||||
|
||||
def test_i_cannot_add_if_the_set_does_not_exists():
|
||||
context = get_context()
|
||||
foo = Concept("foo")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == "bar"
|
||||
|
||||
|
||||
def test_i_can_add_concept_to_a_set_of_concept():
|
||||
context = get_context()
|
||||
foo = Concept("foo")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
bar = Concept("bar")
|
||||
context.sheerka.set_id_if_needed(bar, False)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
|
||||
|
||||
|
||||
def test_i_can_add_concept_with_a_body_to_a_set_of_concept():
|
||||
context = get_context()
|
||||
foo = Concept("foo", body="1")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
bar = Concept("bar")
|
||||
context.sheerka.set_id_if_needed(bar, False)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
|
||||
|
||||
|
||||
def test_i_cannot_add_the_same_concept_twice():
|
||||
context = get_context()
|
||||
foo = Concept("foo")
|
||||
context.sheerka.set_id_if_needed(foo, False)
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
bar = Concept("bar")
|
||||
context.sheerka.set_id_if_needed(bar, False)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
ret_val = get_ret_val("foo", "bar")
|
||||
AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_IN_SET)
|
||||
assert res.value.concept == foo
|
||||
assert res.value.concept_set == bar
|
||||
@@ -1,185 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Tokenizer, TokenKind, LexerError
|
||||
from parsers.BaseParser import UnexpectedTokenErrorNode
|
||||
from parsers.BnfParser import BnfParser, UnexpectedEndOfFileError
|
||||
from parsers.ConceptLexerParser import StrMatch, Optional, ZeroOrMore, OrderedChoice, Sequence, OneOrMore, \
|
||||
ConceptLexerParser, ConceptNode, ConceptExpression, cnode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
|
||||
return ExecutionContext("sheerka", Event(), sheerka)
|
||||
|
||||
|
||||
class ClassWithName():
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("'str'", StrMatch("str")),
|
||||
("1", StrMatch("1")),
|
||||
(" 1", StrMatch("1")),
|
||||
(",", StrMatch(",")),
|
||||
("'foo'?", Optional(StrMatch("foo"))),
|
||||
("'foo'*", ZeroOrMore(StrMatch("foo"))),
|
||||
("'foo'+", OneOrMore(StrMatch("foo"))),
|
||||
("1 | 2 | 3", OrderedChoice(StrMatch("1"), StrMatch("2"), StrMatch("3"))),
|
||||
("1|2|3", OrderedChoice(StrMatch("1"), StrMatch("2"), StrMatch("3"))),
|
||||
("1'|' 2 '|' 3", Sequence(StrMatch("1"), StrMatch("|"), StrMatch("2"), StrMatch("|"), StrMatch("3"))),
|
||||
("1 2 'foo'", Sequence(StrMatch("1"), StrMatch("2"), StrMatch("foo"))),
|
||||
("1 2 | 3 4+", OrderedChoice(
|
||||
Sequence(StrMatch("1"), StrMatch("2")),
|
||||
Sequence(StrMatch("3"), OneOrMore(StrMatch("4"))))),
|
||||
("1 (2 | 3) 4+", Sequence(StrMatch("1"), OrderedChoice(StrMatch("2"), StrMatch("3")), OneOrMore(StrMatch("4")))),
|
||||
("(1|2)+", OneOrMore(OrderedChoice(StrMatch("1"), StrMatch("2")))),
|
||||
("(1 2)+", OneOrMore(Sequence(StrMatch("1"), StrMatch("2")))),
|
||||
("1 *", Sequence(StrMatch("1"), StrMatch("*"))),
|
||||
("1 ?", Sequence(StrMatch("1"), StrMatch("?"))),
|
||||
("1 +", Sequence(StrMatch("1"), StrMatch("+"))),
|
||||
("(1|*) +", Sequence(OrderedChoice(StrMatch("1"), StrMatch("*")), StrMatch("+"))),
|
||||
("1, :&", Sequence(StrMatch("1"), StrMatch(","), StrMatch(":"), StrMatch("&"))),
|
||||
("(1 )", StrMatch("1")),
|
||||
("'str'=var", StrMatch("str", rule_name="var")),
|
||||
("'foo'?=var", Optional(StrMatch("foo"), rule_name="var")),
|
||||
("('foo'?)=var", Optional(StrMatch("foo"), rule_name="var")),
|
||||
("'foo'*=var", ZeroOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("('foo'*)=var", ZeroOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("'foo'+=var", OneOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("('foo'+)=var", OneOrMore(StrMatch("foo"), rule_name="var")),
|
||||
("'foo'=var?", Optional(StrMatch("foo", rule_name="var"))),
|
||||
("('foo'=var)?", Optional(StrMatch("foo", rule_name="var"))),
|
||||
("'foo'=var*", ZeroOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("('foo'=var)*", ZeroOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("'foo'=var+", OneOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("('foo'=var)+", OneOrMore(StrMatch("foo", rule_name="var"))),
|
||||
("(1 | 2 | 3)=var", OrderedChoice(StrMatch("1"), StrMatch("2"), StrMatch("3"), rule_name="var")),
|
||||
("(1 2)=var", Sequence(StrMatch("1"), StrMatch("2"), rule_name="var")),
|
||||
("(1 2)+=var", OneOrMore(Sequence(StrMatch("1"), StrMatch("2")), rule_name="var")),
|
||||
("(1 2)=var+", OneOrMore(Sequence(StrMatch("1"), StrMatch("2"), rule_name="var"))),
|
||||
])
|
||||
def test_i_can_parse_regex(expression, expected):
|
||||
parser = BnfParser()
|
||||
res = parser.parse(get_context(), Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("foo", Concept("foo").init_key()),
|
||||
("foo*", ZeroOrMore(Concept("foo").init_key())),
|
||||
("foo 'and' bar+", Sequence(Concept("foo").init_key(), StrMatch("and"), OneOrMore(Concept("bar").init_key()))),
|
||||
("foo | bar?", OrderedChoice(Concept("foo").init_key(), Optional(Concept("bar").init_key()))),
|
||||
("'str' = var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
|
||||
("'str''='var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
|
||||
])
|
||||
def test_i_can_parse_regex_with_concept(expression, expected):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
var = Concept("var")
|
||||
context = get_context()
|
||||
|
||||
for c in (foo, bar, var):
|
||||
context.sheerka.add_in_cache(c)
|
||||
parser = BnfParser()
|
||||
res = parser.parse(context, Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
|
||||
def test_i_can_parse_regex_with_concept_when_the_concept_is_still_under_definition():
|
||||
expression = "foo"
|
||||
expected = ConceptExpression("foo")
|
||||
|
||||
context = get_context()
|
||||
context.obj = ClassWithName("foo")
|
||||
|
||||
parser = BnfParser()
|
||||
res = parser.parse(context, Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, error", [
|
||||
("1 ", UnexpectedEndOfFileError()),
|
||||
("1|", UnexpectedEndOfFileError()),
|
||||
("(1|)", UnexpectedTokenErrorNode("Unexpected token 'Token(<EOF>)'", [TokenKind.RPAR])),
|
||||
("1=", UnexpectedTokenErrorNode("Unexpected token 'Token(<EOF>)'", [TokenKind.IDENTIFIER])),
|
||||
("'name", LexerError("Missing Trailing quote", "'name", 5, 1, 6))
|
||||
])
|
||||
def test_i_can_detect_errors(expression, error):
|
||||
parser = BnfParser()
|
||||
res = parser.parse(get_context(), Tokenizer(expression))
|
||||
ret_value = res.value.value
|
||||
assert parser.has_error
|
||||
assert not res.status
|
||||
assert ret_value[0] == error
|
||||
|
||||
|
||||
def test_i_can_use_the_result_of_regex_parsing_to_parse_a_text():
|
||||
foo = Concept(name="foo")
|
||||
bar = Concept(name="bar")
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(foo)
|
||||
context.sheerka.add_in_cache(bar)
|
||||
|
||||
regex_parser = BnfParser()
|
||||
foo_definition = regex_parser.parse(context, "'twenty' | 'thirty'").value.value
|
||||
bar_definition = regex_parser.parse(context, "foo ('one' | 'two')").value.value
|
||||
|
||||
concepts = {bar: bar_definition, foo: foo_definition}
|
||||
concept_parser = ConceptLexerParser()
|
||||
concept_parser.initialize(context, concepts)
|
||||
|
||||
res = concept_parser.parse(context, "twenty two")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("bar", 0, 2, "twenty two")]
|
||||
|
||||
res = concept_parser.parse(context, "thirty one")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("bar", 0, 2, "thirty one")]
|
||||
|
||||
res = concept_parser.parse(context, "twenty")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("foo", 0, 0, "twenty")]
|
||||
|
||||
|
||||
def test_i_cannot_parse_when_too_many_concepts():
|
||||
foo1 = Concept(name="foo", body="1")
|
||||
foo2 = Concept(name="foo", body="2")
|
||||
context = get_context()
|
||||
context.sheerka.cache_by_key["foo"] = [foo1, foo2]
|
||||
|
||||
regex_parser = BnfParser()
|
||||
res = regex_parser.parse(context, "foo")
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CANNOT_RESOLVE_CONCEPT)
|
||||
assert res.value.body == ('key', 'foo')
|
||||
|
||||
|
||||
def test_i_cannot_parse_when_unknown_concept():
|
||||
context = get_context()
|
||||
|
||||
regex_parser = BnfParser()
|
||||
res = regex_parser.parse(get_context(), "foo")
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == ('key', 'foo')
|
||||
@@ -1,139 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.ConceptEvaluator import ConceptEvaluator
|
||||
from parsers.ExactConceptParser import ExactConceptParser
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_return_value(concept, source=None):
|
||||
return ReturnValueConcept(
|
||||
"some_name",
|
||||
True,
|
||||
ParserResultConcept(parser=ExactConceptParser(),
|
||||
source=source or concept.name,
|
||||
value=concept,
|
||||
try_parsed=concept))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=Concept())), True),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=Concept())), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value="Not a concept")), False),
|
||||
(ReturnValueConcept("some_name", True, Concept()), False),
|
||||
])
|
||||
def test_i_can_match(ret_val, expected):
|
||||
context = get_context()
|
||||
assert ConceptEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
|
||||
def test_i_can_evaluate_concept():
|
||||
context = get_context()
|
||||
concept = Concept(name="foo",
|
||||
where="1",
|
||||
pre="2",
|
||||
post="3").def_prop("a", "4").def_prop("b", "5")
|
||||
|
||||
evaluator = ConceptEvaluator()
|
||||
item = get_return_value(concept)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert result.value.name == "foo"
|
||||
assert result.value.get_metadata_value(ConceptParts.WHERE) == 1
|
||||
assert result.value.get_metadata_value(ConceptParts.PRE) == 2
|
||||
assert result.value.get_metadata_value(ConceptParts.POST) == 3
|
||||
assert result.value.get_prop("a") == 4
|
||||
assert result.value.get_prop("b") == 5
|
||||
assert result.value.key == "foo"
|
||||
assert result.parents == [item]
|
||||
|
||||
|
||||
def test_body_is_returned_when_defined_and_requested():
|
||||
context = get_context()
|
||||
concept = Concept(name="foo",
|
||||
body="'I have a value'",
|
||||
where="1",
|
||||
pre="2",
|
||||
post="3").set_prop("a", "4").set_prop("b", "5")
|
||||
|
||||
evaluator = ConceptEvaluator(return_body=True)
|
||||
item = get_return_value(concept)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert result.value == "I have a value"
|
||||
assert result.parents == [item]
|
||||
|
||||
|
||||
def test_body_is_not_returned_if_not_requested():
|
||||
context = get_context()
|
||||
concept = Concept(name="foo",
|
||||
body="'I have a value'",
|
||||
where="1",
|
||||
pre="2",
|
||||
post="3").set_prop("a", "4").set_prop("b", "5")
|
||||
|
||||
evaluator = ConceptEvaluator(return_body=False) # which is the default behaviour
|
||||
item = get_return_value(concept)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert result.value == concept
|
||||
assert result.parents == [item]
|
||||
|
||||
|
||||
def test_i_can_eval_if_with_the_same_name_is_defined_in_the_context():
|
||||
# If we evaluate Concept("foo", body="a").set_prop("a", "'property_a'")
|
||||
# ConceptEvaluator will be called to resolve 'a' while we know that 'a' refers to the string 'property_a'
|
||||
|
||||
context = get_context()
|
||||
context.obj = Concept("other").set_prop("foo", "'some_other_value'")
|
||||
concept = Concept(name="foo")
|
||||
|
||||
item = get_return_value(concept)
|
||||
result = ConceptEvaluator().eval(context, item)
|
||||
|
||||
assert result.status
|
||||
assert result.value == "'some_other_value'"
|
||||
|
||||
|
||||
def test_i_cannot_recognize_a_concept_if_one_of_the_prop_is_unknown():
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(Concept(name="one").init_key())
|
||||
concept_plus = context.sheerka.add_in_cache(Concept(name="a plus b")
|
||||
.def_prop("a", "one")
|
||||
.def_prop("b", "two").init_key())
|
||||
|
||||
evaluator = ConceptEvaluator()
|
||||
item = get_return_value(concept_plus)
|
||||
result = evaluator.eval(context, item)
|
||||
|
||||
assert not result.status
|
||||
assert context.sheerka.isinstance(result.value, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
assert result.value.property_name == "b"
|
||||
assert context.sheerka.isinstance(result.value.error, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
assert result.value.concept == concept_plus
|
||||
|
||||
|
||||
def test_that_error_concepts_are_transformed_into_errors_only_if_the_key_is_different():
|
||||
context = get_context()
|
||||
|
||||
error_concept = context.sheerka.new(BuiltinConcepts.ERROR)
|
||||
item = get_return_value(error_concept)
|
||||
result = ConceptEvaluator().eval(context, item)
|
||||
|
||||
assert not context.sheerka.is_success(error_concept) # it's indeed an error
|
||||
assert result.status
|
||||
assert result.value == error_concept
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,204 +0,0 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Token, TokenKind, Tokenizer
|
||||
from parsers.ConceptLexerParser import ConceptNode, UnrecognizedTokensNode, SourceCodeNode
|
||||
from parsers.ConceptsWithConceptsParser import ConceptsWithConceptsParser
|
||||
from parsers.MultipleConceptsParser import MultipleConceptsParser
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
multiple_concepts_parser = MultipleConceptsParser()
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_ret_from(*args):
|
||||
result = []
|
||||
index = 0
|
||||
source = ""
|
||||
for item in args:
|
||||
if isinstance(item, Concept):
|
||||
tokens = [Token(TokenKind.IDENTIFIER, item.name, 0, 0, 0)]
|
||||
result.append(ConceptNode(item, index, index, tokens, item.name))
|
||||
index += 1
|
||||
source += item.name
|
||||
elif isinstance(item, PythonNode):
|
||||
tokens = list(Tokenizer(item.source))[:-1] # strip trailing EOF
|
||||
result.append(SourceCodeNode(item, index, index + len(tokens) - 1, tokens, item.source))
|
||||
index += len(tokens)
|
||||
source += item.source
|
||||
else:
|
||||
tokens = list(Tokenizer(item))[:-1] # strip trailing EOF
|
||||
result.append(UnrecognizedTokensNode(index, index + len(tokens) - 1, tokens))
|
||||
index += len(tokens)
|
||||
source += item
|
||||
|
||||
return ReturnValueConcept(
|
||||
"who",
|
||||
False,
|
||||
ParserResultConcept(parser=multiple_concepts_parser, value=result, source=source))
|
||||
|
||||
|
||||
def init(concepts, inputs):
|
||||
context = get_context()
|
||||
for concept in concepts:
|
||||
context.sheerka.create_new_concept(context, concept)
|
||||
|
||||
return context, get_ret_from(*inputs)
|
||||
|
||||
|
||||
def execute(concepts, inputs):
|
||||
context, input_return_values = init(concepts, inputs)
|
||||
|
||||
parser = ConceptsWithConceptsParser()
|
||||
result = parser.parse(context, input_return_values.body)
|
||||
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
return context, parser, result, wrapper, return_value
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, interested", [
|
||||
("not parser result", False),
|
||||
(ParserResultConcept(parser="not multiple_concepts_parser"), False),
|
||||
(ParserResultConcept(parser=multiple_concepts_parser, value=[]), True),
|
||||
])
|
||||
def test_not_interested(text, interested):
|
||||
context = get_context()
|
||||
|
||||
res = ConceptsWithConceptsParser().parse(context, text)
|
||||
if interested:
|
||||
assert res is not None
|
||||
else:
|
||||
assert res is None
|
||||
|
||||
|
||||
def test_i_can_parse_composition_of_concepts():
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
plus = Concept("a plus b").def_prop("a").def_prop("b")
|
||||
|
||||
context, parser, result, wrapper, return_value = execute([foo, bar, plus], [foo, " plus ", bar])
|
||||
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert result.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus bar"
|
||||
assert context.sheerka.isinstance(return_value, plus)
|
||||
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == bar
|
||||
|
||||
# sanity check, I can evaluate the result
|
||||
evaluated = context.sheerka.evaluate_concept(context, return_value)
|
||||
assert evaluated.key == return_value.key
|
||||
assert evaluated.get_prop("a") == foo.init_key()
|
||||
assert evaluated.get_prop("b") == bar.init_key()
|
||||
|
||||
|
||||
def test_i_can_parse_when_composition_of_source_code():
|
||||
plus = Concept("a plus b", body="a + b").def_prop("a").def_prop("b")
|
||||
left = PythonNode("1+1", ast.parse("1+1", mode="eval"))
|
||||
right = PythonNode("2+2", ast.parse("2+2", mode="eval"))
|
||||
context, parser, result, wrapper, return_value = execute([plus], [left, " plus ", right])
|
||||
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert result.who == wrapper.parser.name
|
||||
assert wrapper.source == "1+1 plus 2+2"
|
||||
assert context.sheerka.isinstance(return_value, plus)
|
||||
|
||||
left_parser_result = ParserResultConcept(parser=parser, source="1+1", value=left)
|
||||
right_parser_result = ParserResultConcept(parser=parser, source="2+2", value=right)
|
||||
assert return_value.compiled["a"] == [ReturnValueConcept(parser.name, True, left_parser_result)]
|
||||
assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, right_parser_result)]
|
||||
|
||||
# sanity check, I can evaluate the result
|
||||
evaluated = context.sheerka.evaluate_concept(context, return_value)
|
||||
assert evaluated.key == return_value.key
|
||||
assert evaluated.get_prop("a") == 2
|
||||
assert evaluated.get_prop("b") == 4
|
||||
assert evaluated.body == 6
|
||||
|
||||
|
||||
def test_i_can_parse_when_mix_of_concept_and_code():
|
||||
plus = Concept("a plus b").def_prop("a").def_prop("b")
|
||||
code = PythonNode("1+1", ast.parse("1+1", mode="eval"))
|
||||
foo = Concept("foo")
|
||||
context, parser, result, wrapper, return_value = execute([plus, foo], [foo, " plus ", code])
|
||||
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert result.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus 1+1"
|
||||
assert context.sheerka.isinstance(return_value, plus)
|
||||
|
||||
code_parser_result = ParserResultConcept(parser=parser, source="1+1", value=code)
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, code_parser_result)]
|
||||
|
||||
# sanity check, I can evaluate the result
|
||||
evaluated = context.sheerka.evaluate_concept(context, return_value)
|
||||
assert evaluated.key == return_value.key
|
||||
assert evaluated.get_prop("a") == foo.init_key()
|
||||
assert evaluated.get_prop("b") == 2
|
||||
|
||||
|
||||
def test_i_can_parse_when_multiple_concepts_are_recognized():
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
plus_1 = Concept("a plus b", body="body1").def_prop("a").def_prop("b")
|
||||
plus_2 = Concept("a plus b", body="body2").def_prop("a").def_prop("b")
|
||||
|
||||
context, input_return_values = init([foo, bar, plus_1, plus_2], [foo, " plus ", bar])
|
||||
parser = ConceptsWithConceptsParser()
|
||||
result = parser.parse(context, input_return_values.body)
|
||||
|
||||
assert len(result) == 2
|
||||
|
||||
res = result[0]
|
||||
wrapper = res.value
|
||||
return_value = res.value.value
|
||||
assert res.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert res.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus bar"
|
||||
assert context.sheerka.isinstance(return_value, plus_1)
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == bar
|
||||
|
||||
res = result[1]
|
||||
wrapper = res.value
|
||||
return_value = res.value.value
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert res.who == wrapper.parser.name
|
||||
assert wrapper.source == "foo plus bar"
|
||||
assert context.sheerka.isinstance(return_value, plus_2)
|
||||
assert return_value.compiled["a"] == foo
|
||||
assert return_value.compiled["b"] == bar
|
||||
|
||||
|
||||
def test_i_cannot_parse_when_unknown_concept():
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
|
||||
context, input_return_values = init([foo, bar], [foo, " plus ", bar])
|
||||
parser = ConceptsWithConceptsParser()
|
||||
result = parser.parse(context, input_return_values.body)
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
assert not result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.NOT_FOR_ME)
|
||||
assert result.who == parser.name
|
||||
assert return_value == input_return_values.body.body
|
||||
@@ -1,368 +0,0 @@
|
||||
import pytest
|
||||
import ast
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from parsers.ConceptLexerParser import OrderedChoice, StrMatch, ConceptExpression
|
||||
from parsers.PythonParser import PythonParser, PythonNode
|
||||
from core.tokenizer import Keywords, Tokenizer, LexerError
|
||||
from parsers.DefaultParser import DefaultParser, NameNode, SyntaxErrorNode, CannotHandleErrorNode, IsaConceptNode
|
||||
from parsers.DefaultParser import UnexpectedTokenErrorNode, DefConceptNode
|
||||
from parsers.BnfParser import BnfParser
|
||||
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None):
|
||||
def_concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
|
||||
|
||||
if body:
|
||||
def_concept.body = get_concept_part(body)
|
||||
if where:
|
||||
def_concept.where = get_concept_part(where)
|
||||
if pre:
|
||||
def_concept.pre = get_concept_part(pre)
|
||||
if post:
|
||||
def_concept.post = get_concept_part(post)
|
||||
if definition:
|
||||
def_concept.definition = ReturnValueConcept(
|
||||
"parsers.Bnf",
|
||||
True,
|
||||
definition)
|
||||
|
||||
return def_concept
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_concept_part(part):
|
||||
if isinstance(part, str):
|
||||
node = PythonNode(part, ast.parse(part, mode="eval"))
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part,
|
||||
parser=PythonParser(),
|
||||
value=node))
|
||||
|
||||
if isinstance(part, PythonNode):
|
||||
return ReturnValueConcept(
|
||||
who="parsers.Default",
|
||||
status=True,
|
||||
value=ParserResultConcept(
|
||||
source=part.source,
|
||||
parser=PythonParser(),
|
||||
value=part))
|
||||
|
||||
if isinstance(part, ReturnValueConcept):
|
||||
return part
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("def concept hello", get_def_concept(name="hello")),
|
||||
("def concept hello ", get_def_concept(name="hello")),
|
||||
("def concept a + b", get_def_concept(name="a + b")),
|
||||
("def concept a+b", get_def_concept(name="a + b")),
|
||||
("def concept 'a+b'+c", get_def_concept(name="'a+b' + c")),
|
||||
("def concept 'as if'", get_def_concept(name="'as if'")),
|
||||
("def concept 'as' if", get_def_concept(name="'as if'")),
|
||||
("def concept hello as 'hello'", get_def_concept(name="hello", body="'hello'")),
|
||||
("def concept hello as 1", get_def_concept(name="hello", body="1")),
|
||||
("def concept hello as 1 + 1", get_def_concept(name="hello", body="1 + 1")),
|
||||
])
|
||||
def test_i_can_parse_def_concept(text, expected):
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
node = res.value.value
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert node == expected
|
||||
|
||||
|
||||
def test_i_can_parse_complex_def_concept_statement():
|
||||
text = """def concept a plus b
|
||||
where a,b
|
||||
pre isinstance(a, int) and isinstance(b, float)
|
||||
post isinstance(res, int)
|
||||
as res = a + b
|
||||
"""
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
return_value = res.value
|
||||
expected_concept = get_def_concept(
|
||||
name="a plus b",
|
||||
where="a,b",
|
||||
pre="isinstance(a, int) and isinstance(b, float)",
|
||||
post="isinstance(res, int)",
|
||||
body=PythonNode("res = a + b", ast.parse("res = a + b", mode="exec"))
|
||||
)
|
||||
|
||||
assert res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert return_value.value == expected_concept
|
||||
|
||||
|
||||
def test_i_can_have_mutilines_declarations():
|
||||
text = """
|
||||
def concept add one to a as
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
|
||||
expected_concept = get_def_concept(
|
||||
name="add one to a ",
|
||||
body=PythonNode(
|
||||
"def func(x):\n return x+1\nfunc(a)",
|
||||
ast.parse("def func(x):\n return x+1\nfunc(a)", mode="exec"))
|
||||
)
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert return_value.value == expected_concept
|
||||
|
||||
|
||||
def test_i_can_use_colon_to_use_indentation():
|
||||
text = """
|
||||
def concept add one to a as:
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
|
||||
expected_concept = get_def_concept(
|
||||
name="add one to a ",
|
||||
body=PythonNode(
|
||||
"def func(x):\n return x+1\nfunc(a)",
|
||||
ast.parse("def func(x):\n return x+1\nfunc(a)", mode="exec"))
|
||||
)
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert return_value.value == expected_concept
|
||||
|
||||
|
||||
def test_indentation_is_mandatory_after_a_colon():
|
||||
text = """
|
||||
def concept add one to a as:
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert isinstance(return_value.value[0], SyntaxErrorNode)
|
||||
assert return_value.value[0].message == "Indentation not found."
|
||||
|
||||
|
||||
def test_indentation_is_not_allowed_if_the_colon_is_missing():
|
||||
text = """
|
||||
def concept add one to a as
|
||||
def func(x):
|
||||
return x+1
|
||||
func(a)
|
||||
"""
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(return_value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
|
||||
|
||||
def test_name_is_mandatory():
|
||||
text = "def concept as 'hello'"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert isinstance(return_value.value[0], SyntaxErrorNode)
|
||||
assert return_value.value[0].message == "Name is mandatory"
|
||||
|
||||
|
||||
def test_concept_keyword_is_mandatory_but_the_concept_is_recognized():
|
||||
text = "def hello as a where b pre c post d"
|
||||
|
||||
expected_concept = get_def_concept(name="hello", body="a", where="b", pre="c", post="d")
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert isinstance(return_value.value[0], UnexpectedTokenErrorNode)
|
||||
assert return_value.value[0].message == "Syntax error."
|
||||
assert return_value.value[0].expected_tokens == [Keywords.CONCEPT]
|
||||
assert return_value.try_parsed == expected_concept
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"def concept hello where 1+",
|
||||
"def concept hello pre 1+",
|
||||
"def concept hello post 1+",
|
||||
"def concept hello as 1+"
|
||||
])
|
||||
def test_i_can_detect_error_in_declaration(text):
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(return_value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
|
||||
|
||||
def test_new_line_is_not_allowed_in_the_name():
|
||||
text = "def concept hello \n my friend as 'hello'"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert return_value.value == [SyntaxErrorNode([], "Newline are not allowed in name.")]
|
||||
|
||||
|
||||
def test_i_can_parse_def_concept_from_regex():
|
||||
context = get_context()
|
||||
a_concept = Concept("a_concept")
|
||||
context.sheerka.add_in_cache(a_concept)
|
||||
|
||||
text = "def concept name from bnf a_concept | 'a_string' as __definition[0]"
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
node = res.value.value
|
||||
definition = OrderedChoice(a_concept, StrMatch("a_string"))
|
||||
parser_result = ParserResultConcept(BnfParser(), "a_concept | 'a_string'", definition, definition)
|
||||
expected = get_def_concept(name="name", body="__definition[0]", definition=parser_result)
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert node == expected
|
||||
|
||||
|
||||
def test_i_can_parse_def_concept_where_bnf_references_itself():
|
||||
context = get_context()
|
||||
a_concept = Concept("a_concept")
|
||||
context.sheerka.add_in_cache(a_concept)
|
||||
|
||||
text = "def concept name from bnf 'a' + name?"
|
||||
parser = DefaultParser()
|
||||
parser.parse(context, text)
|
||||
|
||||
assert not parser.has_error
|
||||
|
||||
|
||||
def test_i_can_detect_empty_bnf_declaration():
|
||||
text = "def concept name from bnf as __definition[0]"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def test_i_can_parse_is_a():
|
||||
parser = DefaultParser()
|
||||
text = "the name of my 'concept' isa the name of the set"
|
||||
res = parser.parse(get_context(), text)
|
||||
expected = IsaConceptNode([],
|
||||
concept=NameNode(list(Tokenizer("the name of my 'concept'"))),
|
||||
set=NameNode(list(Tokenizer("the name of the set"))))
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert res.value.value == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"concept",
|
||||
"isa number",
|
||||
"name isa",
|
||||
"def",
|
||||
"def concept_name"
|
||||
])
|
||||
def test_i_cannot_parse_invalid_entries(text):
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(res.body, ParserResultConcept)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, error_msg, error_text", [
|
||||
("'name", "Missing Trailing quote", "'name"),
|
||||
("foo isa 'name", "Missing Trailing quote", "'name"),
|
||||
("def concept 'name", "Missing Trailing quote", "'name"),
|
||||
("def concept name as 'body", "Missing Trailing quote", "'body"),
|
||||
("def concept name from bnf 'expression", "Missing Trailing quote", "'expression"),
|
||||
("def concept c::", "Concept name not found", ""),
|
||||
])
|
||||
def test_i_cannot_parse_when_tokenizer_fails(text, error_msg, error_text):
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(res.body, ParserResultConcept)
|
||||
assert isinstance(res.body.body[0], LexerError)
|
||||
assert res.body.body[0].message == error_msg
|
||||
assert res.body.body[0].text == error_text
|
||||
|
||||
|
||||
def test_i_cannot_parse_bnf_definition_referencing_unknown_concept():
|
||||
context = get_context()
|
||||
text = "def concept name from bnf unknown"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == ("key", "unknown")
|
||||
@@ -1,80 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.EvalEvaluator import EvalEvaluator
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def r(value, status=True):
|
||||
return ReturnValueConcept("some_name", status, value)
|
||||
|
||||
|
||||
eval_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.CONCEPT_EVAL_REQUESTED))
|
||||
|
||||
|
||||
def test_i_can_match_and_eval():
|
||||
context = get_context()
|
||||
|
||||
to_eval1 = ReturnValueConcept("some_name", True, Concept(name="2", body="to eval").auto_init())
|
||||
to_eval2 = ReturnValueConcept("some_name", True, Concept(name="3", body="also to eval").auto_init())
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept("some_name", True, "not to eval"),
|
||||
ReturnValueConcept("some_name", True, Concept(name="not to eval")),
|
||||
ReturnValueConcept("some_name", False, Concept(name="1", body="'not to eval'")),
|
||||
to_eval1,
|
||||
to_eval2,
|
||||
eval_requested
|
||||
]
|
||||
|
||||
evaluator = EvalEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert len(evaluated) == 2
|
||||
assert evaluated[0].value == to_eval1.body.body
|
||||
assert evaluated[0].parents == [to_eval1, eval_requested]
|
||||
|
||||
assert evaluated[1].value == to_eval2.body.body
|
||||
assert evaluated[1].parents == [to_eval2, eval_requested]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([r(Concept("foo", body="bar")), eval_requested], True),
|
||||
([r(Concept("status is false", body="bar"), False), eval_requested], True),
|
||||
([r("string_value"), eval_requested], True),
|
||||
([r(Concept("no body")), eval_requested], True),
|
||||
([r(Concept("eval requested missing", body="bar"))], False),
|
||||
])
|
||||
def test_i_cannot_match_if_eval_request_is_not_present(return_values, expected):
|
||||
context = get_context()
|
||||
assert EvalEvaluator().matches(context, return_values) == expected
|
||||
|
||||
|
||||
def test_concept_eval_requested_is_reduced_when_nothing_to_reduce():
|
||||
context = get_context()
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept("some_name", True, "not to eval"),
|
||||
ReturnValueConcept("some_name", True, Concept(name="not to eval")),
|
||||
ReturnValueConcept("some_name", False, Concept(name="1", body="not to eval")),
|
||||
eval_requested
|
||||
]
|
||||
|
||||
evaluator = EvalEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated == ReturnValueConcept(
|
||||
"evaluators.Eval",
|
||||
False,
|
||||
context.sheerka.new(BuiltinConcepts.CONCEPT_EVAL_REQUESTED))
|
||||
assert evaluated.parents == [eval_requested]
|
||||
@@ -1,151 +0,0 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, Property
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Tokenizer
|
||||
from parsers.ExactConceptParser import ExactConceptParser
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def metadata_prop(concept, prop_name):
|
||||
for name, value in concept.metadata.props:
|
||||
if name == prop_name:
|
||||
return value
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def test_i_can_compute_combinations():
|
||||
parser = ExactConceptParser()
|
||||
res = parser.combinations(["foo", "bar", "baz"])
|
||||
|
||||
assert res == {('foo', 'bar', 'baz'),
|
||||
('__var__0', 'bar', 'baz'),
|
||||
('foo', '__var__0', 'baz'),
|
||||
('foo', 'bar', '__var__0'),
|
||||
('__var__0', '__var__1', 'baz'),
|
||||
('__var__0', 'bar', '__var__1'),
|
||||
('foo', '__var__0', '__var__1'),
|
||||
('__var__0', '__var__1', '__var__2')}
|
||||
|
||||
|
||||
def test_i_can_compute_combinations_with_duplicates():
|
||||
parser = ExactConceptParser()
|
||||
res = parser.combinations(["foo", "bar", "foo"])
|
||||
|
||||
assert res == {('foo', 'bar', 'foo'),
|
||||
('__var__0', 'bar', '__var__0'),
|
||||
('foo', '__var__0', 'foo'),
|
||||
('__var__0', '__var__1', '__var__0'),
|
||||
('__var__1', '__var__0', '__var__1')}
|
||||
# TODO: the last tuple is not possible, so the algo can be improved
|
||||
|
||||
|
||||
def test_i_can_recognize_a_simple_concept():
|
||||
context = get_context()
|
||||
concept = get_concept("hello world", [])
|
||||
context.sheerka.add_in_cache(concept)
|
||||
|
||||
source = "hello world"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
assert results[0].value.value == concept
|
||||
|
||||
|
||||
def test_i_can_recognize_concepts_defined_several_times():
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(get_concept("hello world", []))
|
||||
context.sheerka.add_in_cache(get_concept("hello a", ["a"]))
|
||||
|
||||
source = "hello world"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 2
|
||||
results = sorted(results, key=lambda x: x.value.value.name) # because of the usage of sets
|
||||
|
||||
assert results[0].status
|
||||
assert results[0].value.value.name == "hello a"
|
||||
assert metadata_prop(results[0].value.value, "a") == "world"
|
||||
|
||||
assert results[1].status
|
||||
assert results[1].value.value.name == "hello world"
|
||||
|
||||
|
||||
def test_i_can_recognize_a_concept_with_variables():
|
||||
context = get_context()
|
||||
concept = get_concept("a + b", ["a", "b"])
|
||||
context.sheerka.add_in_cache(concept)
|
||||
source = "10 + 5"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
concept_found = results[0].value.value
|
||||
assert concept_found.key == concept.key
|
||||
assert metadata_prop(concept_found, "a") == "10"
|
||||
assert metadata_prop(concept_found, "b") == "5"
|
||||
|
||||
|
||||
def test_i_can_recognize_a_concept_with_duplicate_variables():
|
||||
context = get_context()
|
||||
concept = get_concept("a + b + a", ["a", "b"])
|
||||
context.sheerka.cache_by_key[concept.key] = concept
|
||||
source = "10 + 5 + 10"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
concept_found = results[0].value.value
|
||||
assert concept_found.key == concept.key
|
||||
assert metadata_prop(concept_found, "a") == "10"
|
||||
assert metadata_prop(concept_found, "b") == "5"
|
||||
|
||||
|
||||
def test_i_can_manage_unknown_concept():
|
||||
context = get_context()
|
||||
source = "def concept hello world" # this is not a concept by itself
|
||||
res = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == "def concept hello world"
|
||||
|
||||
|
||||
def test_i_can_detect_concepts_too_long():
|
||||
context = get_context()
|
||||
source = "a very very long concept that cannot be an unique one"
|
||||
res = ExactConceptParser().parse(context, source)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_TOO_LONG)
|
||||
assert res.value.body == "a very very long concept that cannot be an unique one"
|
||||
|
||||
|
||||
def test_i_can_detect_concept_from_tokens():
|
||||
context = get_context()
|
||||
concept = get_concept("hello world", [])
|
||||
context.sheerka.add_in_cache(concept)
|
||||
|
||||
source = "hello world"
|
||||
results = ExactConceptParser().parse(context, list(Tokenizer(source)))
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].status
|
||||
assert results[0].value.value == concept
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
|
||||
return ExecutionContext("sheerka", Event(), sheerka)
|
||||
|
||||
|
||||
def get_concept(name, variables):
|
||||
c = Concept(name=name)
|
||||
if variables:
|
||||
for v in variables:
|
||||
c.def_prop(v)
|
||||
c.init_key()
|
||||
return c
|
||||
@@ -1,115 +0,0 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts, DoNotResolve
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.LexerNodeEvaluator import LexerNodeEvaluator
|
||||
from parsers.ConceptLexerParser import ConceptNode, ConceptLexerParser, StrMatch, UnrecognizedTokensNode, SourceCodeNode
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def from_parsing(context, grammar, expression):
|
||||
parser = ConceptLexerParser()
|
||||
parser.initialize(context, grammar)
|
||||
|
||||
ret_val = parser.parse(context, expression)
|
||||
assert ret_val.status
|
||||
return ret_val
|
||||
|
||||
|
||||
def from_fragments(*fragments):
|
||||
nodes = []
|
||||
for fragment in fragments:
|
||||
if isinstance(fragment, str):
|
||||
node = PythonNode(fragment, ast.parse(fragment.strip(), mode="eval"))
|
||||
nodes.append(SourceCodeNode(node, 0, 0, [], fragment))
|
||||
else:
|
||||
nodes.append(ConceptNode(fragment, 0, 0, [], fragment.name))
|
||||
|
||||
return ReturnValueConcept("somme_name", True, ParserResultConcept(value=nodes))
|
||||
|
||||
|
||||
def init(concept, grammar, text):
|
||||
context = get_context()
|
||||
if isinstance(concept, list):
|
||||
for c in concept:
|
||||
context.sheerka.add_in_cache(c)
|
||||
else:
|
||||
context.sheerka.add_in_cache(concept)
|
||||
ret_val = from_parsing(context, grammar, text)
|
||||
node = ret_val.value.value[0]
|
||||
|
||||
return context, node
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=ConceptNode(Concept(), 0, 0))), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[SourceCodeNode(0, 0, [])])), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=SourceCodeNode(0, 0, []))), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[UnrecognizedTokensNode(0, 0, [])])), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=UnrecognizedTokensNode(0, 0, []))), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=ConceptNode(Concept(), 0, 0))), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=[SourceCodeNode(0, 0, [])])), False),
|
||||
(ReturnValueConcept("some_name", False, ParserResultConcept(value=SourceCodeNode(0, 0, []))), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value="Not a concept node")), False),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=["Not a concept node"])), False),
|
||||
(ReturnValueConcept("some_name", True, [ConceptNode(Concept(), 0, 0)]), False),
|
||||
(ReturnValueConcept("some_name", True, ConceptNode(Concept(), 0, 0)), False),
|
||||
])
|
||||
def test_i_can_match(ret_val, expected):
|
||||
context = get_context()
|
||||
assert LexerNodeEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
|
||||
def test_concept_is_returned_when_only_one_in_the_list():
|
||||
foo = Concept("foo")
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(foo)
|
||||
|
||||
ret_val = from_parsing(context, {foo: StrMatch("foo")}, "foo")
|
||||
|
||||
evaluator = LexerNodeEvaluator()
|
||||
result = evaluator.eval(context, ret_val)
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.parser == evaluator
|
||||
assert wrapper.source == "foo"
|
||||
assert return_value == Concept("foo").init_key()
|
||||
assert return_value.compiled[ConceptParts.BODY] == DoNotResolve("foo")
|
||||
assert result.parents == [ret_val]
|
||||
|
||||
|
||||
def test_concept_python_node_is_returned_when_source_code():
|
||||
context = get_context()
|
||||
foo = Concept("foo")
|
||||
ret_val = from_fragments(foo, " + 1")
|
||||
|
||||
evaluator = LexerNodeEvaluator()
|
||||
result = evaluator.eval(context, ret_val)
|
||||
wrapper = result.body
|
||||
return_value = result.body.body
|
||||
|
||||
assert result.who == evaluator.name
|
||||
assert result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.parser == evaluator
|
||||
assert wrapper.source == "foo + 1"
|
||||
|
||||
assert return_value == PythonNode('foo + 1', ast.parse("__C__foo__C__ + 1", mode="eval"))
|
||||
assert return_value.concepts == {"__C__foo__C__": foo}
|
||||
assert result.parents == [ret_val]
|
||||
@@ -1,231 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Tokenizer, TokenKind, Token
|
||||
from parsers.ConceptLexerParser import ConceptLexerParser, ConceptNode, Sequence, cnode, utnode, scnode, SourceCodeNode
|
||||
from parsers.MultipleConceptsParser import MultipleConceptsParser
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_return_value(context, grammar, expression):
|
||||
parser = ConceptLexerParser()
|
||||
parser.initialize(context, grammar)
|
||||
|
||||
ret_val = parser.parse(context, expression)
|
||||
assert not ret_val.status
|
||||
return ret_val
|
||||
|
||||
|
||||
def init(concepts, grammar, expression):
|
||||
context = get_context()
|
||||
for c in concepts:
|
||||
context.sheerka.create_new_concept(context, c)
|
||||
return_value = get_return_value(context, grammar, expression)
|
||||
|
||||
return context, return_value
|
||||
|
||||
|
||||
def test_not_interested_if_not_parser_result():
|
||||
context = get_context()
|
||||
text = "not parser result"
|
||||
|
||||
res = MultipleConceptsParser().parse(context, text)
|
||||
assert res is None
|
||||
|
||||
|
||||
def test_not_interested_if_not_from_concept_lexer_parser():
|
||||
context = get_context()
|
||||
text = ParserResultConcept(parser="not concept lexer", value="some value")
|
||||
|
||||
res = MultipleConceptsParser().parse(context, text)
|
||||
assert res is None
|
||||
|
||||
|
||||
def test_i_can_parse_exact_concepts():
|
||||
foo = Concept("foo", body="'foo'")
|
||||
bar = Concept("bar", body="'bar'")
|
||||
baz = Concept("baz", body="'baz'")
|
||||
grammar = {}
|
||||
context, return_value = init([foo, bar, baz], grammar, "bar foo baz")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
ConceptNode(bar, 0, 0, source="bar"),
|
||||
ConceptNode(foo, 2, 2, source="foo"),
|
||||
ConceptNode(baz, 4, 4, source="baz")]
|
||||
assert ret_val.value.source == "bar foo baz"
|
||||
|
||||
|
||||
def test_i_can_parse_when_ending_with_bnf():
|
||||
foo = Concept("foo", body="'foo'")
|
||||
bar = Concept("bar", body="'bar'")
|
||||
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
|
||||
context, return_value = init([foo, bar], grammar, "bar foo1 foo2 foo3")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [cnode("bar", 0, 0, "bar"), cnode("foo", 2, 6, "foo1 foo2 foo3")]
|
||||
assert ret_val.value.source == "bar foo1 foo2 foo3"
|
||||
|
||||
|
||||
def test_i_can_parse_when_starting_with_bnf():
|
||||
foo = Concept("foo", body="'foo'")
|
||||
bar = Concept("bar", body="'bar'")
|
||||
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
|
||||
context, return_value = init([foo, bar], grammar, "foo1 foo2 foo3 bar")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [cnode("foo", 0, 4, "foo1 foo2 foo3"), cnode("bar", 6, 6, "bar")]
|
||||
assert ret_val.value.source == "foo1 foo2 foo3 bar"
|
||||
|
||||
|
||||
def test_i_can_parse_when_concept_are_mixed():
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
baz = Concept("baz")
|
||||
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
|
||||
context, return_value = init([foo, bar, baz], grammar, "baz foo1 foo2 foo3 bar")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
cnode("baz", 0, 0, "baz"),
|
||||
cnode("foo", 2, 6, "foo1 foo2 foo3"),
|
||||
cnode("bar", 8, 8, "bar")]
|
||||
assert ret_val.value.source == "baz foo1 foo2 foo3 bar"
|
||||
|
||||
|
||||
def test_i_can_parse_when_multiple_concepts_are_matching():
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar", body="bar1")
|
||||
baz = Concept("bar", body="bar2")
|
||||
grammar = {foo: "foo"}
|
||||
context, return_value = init([foo, bar, baz], grammar, "foo bar")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert len(ret_val) == 2
|
||||
assert ret_val[0].status
|
||||
assert ret_val[0].value.value == [cnode("foo", 0, 0, "foo"), cnode("bar", 2, 2, "bar")]
|
||||
assert ret_val[0].value.source == "foo bar"
|
||||
assert ret_val[0].value.value[1].concept.metadata.body == "bar1"
|
||||
|
||||
assert ret_val[1].status
|
||||
assert ret_val[1].value.value == [cnode("foo", 0, 0, "foo"), cnode("bar", 2, 2, "bar")]
|
||||
assert ret_val[1].value.source == "foo bar"
|
||||
assert ret_val[1].value.value[1].concept.metadata.body == "bar2"
|
||||
|
||||
|
||||
def test_i_can_parse_when_source_code():
|
||||
foo = Concept("foo")
|
||||
grammar = {foo: "foo"}
|
||||
context, return_value = init([foo], grammar, "1 foo")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
wrapper = ret_val.value
|
||||
value = ret_val.value.value
|
||||
|
||||
assert ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.source == "1 foo"
|
||||
assert value == [
|
||||
scnode(0, 1, "1 "),
|
||||
cnode("foo", 2, 2, "foo")]
|
||||
|
||||
|
||||
def test_i_cannot_parse_when_unrecognized_token():
|
||||
twenty_two = Concept("twenty two")
|
||||
one = Concept("one")
|
||||
grammar = {twenty_two: Sequence("twenty", "two")}
|
||||
context, return_value = init([twenty_two, one], grammar, "twenty two + one")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert not ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
cnode("twenty two", 0, 2, "twenty two"),
|
||||
utnode(3, 5, " + "),
|
||||
cnode("one", 6, 6, "one")
|
||||
]
|
||||
assert ret_val.value.source == "twenty two + one"
|
||||
|
||||
|
||||
def test_i_cannot_parse_when_unknown_concepts():
|
||||
twenty_two = Concept("twenty two")
|
||||
one = Concept("one")
|
||||
grammar = {twenty_two: Sequence("twenty", "two")}
|
||||
context, return_value = init([twenty_two, one], grammar, "twenty two plus one")
|
||||
|
||||
parser = MultipleConceptsParser()
|
||||
ret_val = parser.parse(context, return_value.body)
|
||||
|
||||
assert not ret_val.status
|
||||
assert ret_val.who == parser.name
|
||||
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
|
||||
assert ret_val.value.value == [
|
||||
cnode("twenty two", 0, 2, "twenty two"),
|
||||
utnode(3, 5, " plus "),
|
||||
cnode("one", 6, 6, "one")
|
||||
]
|
||||
assert ret_val.value.source == "twenty two plus one"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected_source, expected_end", [
|
||||
("True", "True", 0),
|
||||
("1 == 1", "1 == 1", 5),
|
||||
("1!xdf", "1", 0),
|
||||
("1", "1", 0),
|
||||
])
|
||||
def test_i_can_get_source_code_node(text, expected_source, expected_end):
|
||||
tokens = list(Tokenizer(text))[:-1] # strip trailing EOF
|
||||
|
||||
start_index = 5 # a random number different of zero
|
||||
res = MultipleConceptsParser().get_source_code_node(get_context(), start_index, tokens)
|
||||
|
||||
assert isinstance(res, SourceCodeNode)
|
||||
assert isinstance(res.node, PythonNode)
|
||||
assert res.source == expected_source
|
||||
assert res.start == start_index
|
||||
assert res.end == start_index + expected_end
|
||||
|
||||
|
||||
def test_i_cannot_parse_null_text():
|
||||
res = MultipleConceptsParser().get_source_code_node(get_context(), 0, [])
|
||||
assert res is None
|
||||
|
||||
eof = Token(TokenKind.EOF, "", 0, 0, 0)
|
||||
res = MultipleConceptsParser().get_source_code_node(get_context(), 0, [eof])
|
||||
assert res is None
|
||||
@@ -1,216 +0,0 @@
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.BaseEvaluator import BaseEvaluator
|
||||
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
|
||||
from parsers.BaseParser import BaseParser
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def test_i_can_match_and_eval():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1", body="value").auto_init() # the first concept is returned
|
||||
|
||||
|
||||
def test_i_can_match_and_eval_when_no_body():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1").auto_init()
|
||||
|
||||
|
||||
def test_i_can_match_and_eval_when_value_is_not_a_concept():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, "value"),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == "value"
|
||||
|
||||
|
||||
def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_concept_evaluator_first():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Concept", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="3", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1", body="value").auto_init() # the concept is returned, not the value
|
||||
|
||||
|
||||
def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_python_evaluator_first():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="3", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept(name="1", body="value").auto_init() # the concept is returned, not the value
|
||||
|
||||
|
||||
def test_i_can_match_even_if_the_value_are_not_the_same_but_eval_will_fail():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value2").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
assert evaluator.eval(context, return_values) is None
|
||||
|
||||
|
||||
def test_i_can_match_even_if_the_value_are_not_the_same_but_eval_will_fail_when_no_body():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
evaluator = MultipleSameSuccessEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
assert evaluator.eval(context, return_values) is None
|
||||
|
||||
|
||||
def test_i_can_match_if_no_parser():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
|
||||
|
||||
def test_i_cannot_match_if_not_reduced_requested():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, Concept(name="2", body="value")),
|
||||
# ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert not MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
|
||||
|
||||
def test_i_cannot_match_if_only_one_successful_evaluator():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
|
||||
# ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, Concept(name="2", body="value")),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert not MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
|
||||
|
||||
def test_i_cannot_match_if_at_least_one_parser_is_successful():
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
return_values = [
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
|
||||
ReturnValueConcept(BaseParser.PREFIX + "some_name2", True, "Not relevant"),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
|
||||
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
|
||||
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
]
|
||||
|
||||
assert not MultipleSameSuccessEvaluator().matches(context, return_values)
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.OneErrorEvaluator import OneErrorEvaluator
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def r(value, status=True):
|
||||
return ReturnValueConcept(value, status, value)
|
||||
|
||||
|
||||
reduce_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.REDUCE_REQUESTED))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([r("evaluators.one error", False), reduce_requested], True),
|
||||
([r("evaluators.one error", False), r("failed", False), r("failed", False), reduce_requested], True),
|
||||
([r("evaluators.error", False), r("not a parser in success"), reduce_requested], True),
|
||||
([r("evaluators.no reduce required", False), r("failed", False), r("failed", False)], False),
|
||||
([r("evaluators.no reduce required", False)], False),
|
||||
([r("evaluators.error", False), r("evaluators.success"), reduce_requested], False),
|
||||
([r("evaluators.error", False), r("parsers.success"), reduce_requested], False),
|
||||
([r("evaluators.success"), r("not an evaluator in error", False), reduce_requested], False),
|
||||
([r("evaluators.error", False), r("evaluators.another error", False), reduce_requested], False),
|
||||
])
|
||||
def test_i_can_match(return_values, expected):
|
||||
context = get_context()
|
||||
assert OneErrorEvaluator().matches(context, return_values) == expected
|
||||
|
||||
|
||||
def test_i_can_eval():
|
||||
context = get_context()
|
||||
|
||||
return_values = [
|
||||
r("evaluators.one error", False),
|
||||
r("parsers.failed", False),
|
||||
r("parsers.failed", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneErrorEvaluator()
|
||||
evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert not res.status
|
||||
assert res.body == "evaluators.one error"
|
||||
assert len(res.parents) == 4
|
||||
|
||||
|
||||
def test_unwanted_return_values_are_not_eaten():
|
||||
context = get_context()
|
||||
|
||||
a_successful_concept = r("successful concept")
|
||||
a_concept_in_error = r("concept in error", False)
|
||||
return_values = [
|
||||
r("evaluators.one error", False),
|
||||
r("parsers.failed", False),
|
||||
r("parsers.failed", False),
|
||||
a_successful_concept,
|
||||
a_concept_in_error,
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneErrorEvaluator()
|
||||
evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert not res.status
|
||||
assert res.body == "evaluators.one error"
|
||||
assert len(res.parents) == 4
|
||||
|
||||
assert a_successful_concept not in res.parents
|
||||
@@ -1,79 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.OneSuccessEvaluator import OneSuccessEvaluator
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def r(value, status=True):
|
||||
return ReturnValueConcept(value, status, value)
|
||||
|
||||
|
||||
reduce_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.REDUCE_REQUESTED))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([r("evaluators.one success"), reduce_requested], True),
|
||||
([r("evaluators.one success"), r("failed", False), r("failed", False), reduce_requested], True),
|
||||
([r("evaluators.no reduce required"), r("failed", False), r("failed", False)], False),
|
||||
([r("evaluators.no reduce required")], False),
|
||||
([r("evaluators.failed", False), r("failed", False), r("failed", False), reduce_requested], False),
|
||||
([r("evaluators.failed", False), r("not evaluator success"), reduce_requested], False),
|
||||
([r("evaluators.success"), r("evaluators.another success"), reduce_requested], False),
|
||||
([r("evaluators.one success"), r("other success"), r("failed", False), reduce_requested], True),
|
||||
([r("evaluators.one success"), r("parsers.success"), reduce_requested], False),
|
||||
])
|
||||
def test_i_can_match(return_values, expected):
|
||||
context = get_context()
|
||||
assert OneSuccessEvaluator().matches(context, return_values) == expected
|
||||
|
||||
|
||||
def test_i_can_eval():
|
||||
context = get_context()
|
||||
|
||||
return_values = [
|
||||
r("evaluators.one success"),
|
||||
r("failed", False),
|
||||
r("failed", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneSuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert res.status
|
||||
assert res.body == "evaluators.one success"
|
||||
assert len(res.parents) == 4
|
||||
|
||||
|
||||
def test_i_do_not_eat_the_other_success():
|
||||
context = get_context()
|
||||
|
||||
not_a_parser_success = r("other success")
|
||||
return_values = [
|
||||
r("evaluators.one success"),
|
||||
not_a_parser_success,
|
||||
r("failed", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = OneSuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert res.status
|
||||
assert res.body == "evaluators.one success"
|
||||
assert len(res.parents) == 3
|
||||
|
||||
assert not_a_parser_success not in res.parents
|
||||
@@ -1,55 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.PrepareEvalEvaluator import PrepareEvalEvaluator
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
r = ReturnValueConcept
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("eval 1 + 1")), True),
|
||||
(r("name", True, UserInputConcept(" eval 1 + 1")), True),
|
||||
(r("name", True, UserInputConcept("eval")), False),
|
||||
(r("name", True, UserInputConcept("1+1")), False),
|
||||
(r("name", True, UserInputConcept("")), False),
|
||||
(r("name", True, UserInputConcept("eval ")), False),
|
||||
(r("name", True, UserInputConcept([])), False),
|
||||
(r("name", True, Concept("foo")), False),
|
||||
(r("name", True, "not a concept"), False),
|
||||
(r("name", False, UserInputConcept("eval 1 + 1")), False),
|
||||
(r("name", False, UserInputConcept(" eval 1 + 1")), False),
|
||||
])
|
||||
def test_i_can_match(ret_val, expected):
|
||||
context = get_context()
|
||||
assert PrepareEvalEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("eval 1 + 1")), "1 + 1"),
|
||||
(r("name", True, UserInputConcept(" eval 1 + 1")), "1 + 1"),
|
||||
])
|
||||
def test_i_can_eval(ret_val, expected):
|
||||
context = get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
prepare_evaluator = PrepareEvalEvaluator()
|
||||
prepare_evaluator.matches(context, ret_val)
|
||||
res = prepare_evaluator.eval(context, ret_val)
|
||||
|
||||
assert len(res) == 2
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.USER_INPUT)
|
||||
assert res[0].body.body == expected
|
||||
|
||||
assert res[1].status
|
||||
assert sheerka.isinstance(res[1].body, BuiltinConcepts.CONCEPT_EVAL_REQUESTED)
|
||||
@@ -1,151 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.concept import Concept
|
||||
from evaluators.PythonEvaluator import PythonEvaluator
|
||||
from parsers.PythonParser import PythonNode, PythonParser
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_context_name(context):
|
||||
return context.name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=PythonNode("", None))), True),
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value="other thing")), False),
|
||||
(ReturnValueConcept("some_name", False, "not relevant"), False),
|
||||
(ReturnValueConcept("some_name", True, Concept()), False)
|
||||
])
|
||||
def test_i_can_match(ret_val, expected):
|
||||
context = get_context()
|
||||
assert PythonEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1 + 1", 2),
|
||||
("sheerka.test()", "I have access to Sheerka !"),
|
||||
("a=10\na", 10),
|
||||
])
|
||||
def test_i_can_eval(text, expected):
|
||||
context = get_context()
|
||||
parsed = PythonParser().parse(context, text)
|
||||
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("concept", [
|
||||
Concept("foo"),
|
||||
Concept("foo", body="2"),
|
||||
Concept("foo").set_prop("prop", "'a'"),
|
||||
Concept("foo", body="bar")
|
||||
])
|
||||
def test_i_cannot_eval_simple_concept(concept):
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo"))
|
||||
|
||||
parsed = PythonParser().parse(context, "foo")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert not evaluated.status
|
||||
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.NOT_FOR_ME)
|
||||
|
||||
|
||||
def test_i_can_eval_expression_with_that_references_concepts():
|
||||
"""
|
||||
I can test modules with variables
|
||||
:return:
|
||||
"""
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo", body="1"))
|
||||
|
||||
parsed = PythonParser().parse(context, "foo + 2")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == 3
|
||||
|
||||
|
||||
def test_i_can_eval_module_with_that_references_concepts():
|
||||
"""
|
||||
I can test modules with variables
|
||||
:return:
|
||||
"""
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo"))
|
||||
|
||||
parsed = PythonParser().parse(context, "def a(b):\n return b\na(c:foo:)")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == Concept("foo").init_key()
|
||||
|
||||
|
||||
def test_i_can_eval_module_with_that_references_concepts_with_body():
|
||||
"""
|
||||
I can test modules with variables
|
||||
:return:
|
||||
"""
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo", body="2"))
|
||||
|
||||
parsed = PythonParser().parse(context, "def a(b):\n return b\na(foo)")
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == 2
|
||||
|
||||
|
||||
def test_i_can_eval_concept_token():
|
||||
context = get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo", body="2"))
|
||||
|
||||
parsed = PythonParser().parse(context, "get_context_name(c:foo:)")
|
||||
python_evaluator = PythonEvaluator()
|
||||
python_evaluator.locals["get_context_name"] = get_context_name
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == "foo"
|
||||
|
||||
# sanity, does not work otherwise
|
||||
parsed = PythonParser().parse(context, "get_context_name(foo)")
|
||||
python_evaluator = PythonEvaluator()
|
||||
python_evaluator.locals["get_context_name"] = get_context_name
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
|
||||
assert not evaluated.status
|
||||
assert evaluated.body.body.args[0] == "'int' object has no attribute 'name'"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, concept_key, concept_id, use_concept", [
|
||||
("__C__key__C__", "key", None, False),
|
||||
("__C__key__id__C__", "key", "id", False),
|
||||
("__C__USE_CONCEPT__key__id__C__", "key", "id", True),
|
||||
("__C__USE_CONCEPT__key__id__C__", "key", "id", True),
|
||||
])
|
||||
def test_i_can_resolve_name(text, concept_key, concept_id, use_concept):
|
||||
context = get_context()
|
||||
assert PythonEvaluator().resolve_name(context, text) == (concept_key, concept_id, use_concept)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"__C__",
|
||||
"__C__key",
|
||||
"__C__key____",
|
||||
"__C____",
|
||||
"__C__USE_CONCEPT__",
|
||||
])
|
||||
def test_i_cannot_resolve_name(text):
|
||||
context = get_context()
|
||||
assert PythonEvaluator().resolve_name(context, text) is None
|
||||
@@ -1,87 +0,0 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Tokenizer, LexerError
|
||||
from parsers.PythonParser import PythonNode, PythonParser, PythonErrorNode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1+1", PythonNode("1+1", ast.parse("1+1", mode="eval"))),
|
||||
("a=10", PythonNode("a=10", ast.parse("a=10", mode="exec"))),
|
||||
])
|
||||
def test_i_can_parse_a_simple_expression(text, expected):
|
||||
parser = PythonParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert res.value.value == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1+1", PythonNode("1+1", ast.parse("1+1", mode="eval"))),
|
||||
("a=10", PythonNode("a=10", ast.parse("a=10", mode="exec"))),
|
||||
])
|
||||
def test_i_can_parse_from_tokens(text, expected):
|
||||
parser = PythonParser()
|
||||
tokens = list(Tokenizer(text))
|
||||
res = parser.parse(get_context(), tokens)
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert res.value.value == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"1+",
|
||||
"'name",
|
||||
"foo = 'name"
|
||||
])
|
||||
def test_i_can_detect_error(text):
|
||||
parser = PythonParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert res.who == parser.name
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert isinstance(res.value.value[0], PythonErrorNode)
|
||||
assert isinstance(res.value.value[0].exception, SyntaxError)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, error_msg, error_text", [
|
||||
("c::", "Concept name not found", ""),
|
||||
("c:: + 1", "Concept name not found", ""),
|
||||
])
|
||||
def test_i_can_detect_lexer_errors(text, error_msg, error_text):
|
||||
parser = PythonParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(res.body, ParserResultConcept)
|
||||
assert isinstance(res.body.body[0], LexerError)
|
||||
assert res.body.body[0].message == error_msg
|
||||
assert res.body.body[0].text == error_text
|
||||
|
||||
|
||||
def test_i_can_parse_a_concept():
|
||||
text = "c:concept_name: + 1"
|
||||
|
||||
parser = PythonParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
assert res
|
||||
assert res.value.value == PythonNode(
|
||||
"c:concept_name: + 1",
|
||||
ast.parse("__C__USE_CONCEPT__concept_name__C__+1", mode="eval"))
|
||||
@@ -1,147 +0,0 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Token, TokenKind, Tokenizer
|
||||
from parsers.ConceptLexerParser import ConceptNode, UnrecognizedTokensNode
|
||||
from parsers.MultipleConceptsParser import MultipleConceptsParser
|
||||
from parsers.PythonParser import PythonNode, PythonErrorNode
|
||||
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
multiple_concepts_parser = MultipleConceptsParser()
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_ret_from(*args):
|
||||
result = []
|
||||
index = 0
|
||||
for item in args:
|
||||
if isinstance(item, Concept):
|
||||
tokens = [Token(TokenKind.IDENTIFIER, item.name, 0, 0, 0)]
|
||||
result.append(ConceptNode(item, index, index, tokens, item.name))
|
||||
index += 1
|
||||
else:
|
||||
tokens = list(Tokenizer(item))
|
||||
result.append(UnrecognizedTokensNode(index, index + len(tokens) - 1, tokens))
|
||||
index += len(tokens)
|
||||
|
||||
return ReturnValueConcept("who", False, ParserResultConcept(parser=multiple_concepts_parser, value=result))
|
||||
|
||||
|
||||
def to_str_ast(expression):
|
||||
return PythonNode.get_dump(ast.parse(expression, mode="eval"))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, interested", [
|
||||
("not parser result", False),
|
||||
(ParserResultConcept(parser="not multiple_concepts_parser"), False),
|
||||
(ParserResultConcept(parser=multiple_concepts_parser, value=[]), True),
|
||||
])
|
||||
def test_not_interested(text, interested):
|
||||
context = get_context()
|
||||
|
||||
res = PythonWithConceptsParser().parse(context, text)
|
||||
if interested:
|
||||
assert res is not None
|
||||
else:
|
||||
assert res is None
|
||||
|
||||
|
||||
def test_i_can_parse_concepts_and_python():
|
||||
context = get_context()
|
||||
foo = Concept("foo")
|
||||
input_return_value = get_ret_from(foo, " + 1")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
wrapper = result.value
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert result.who == parser.name
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.source == "foo + 1"
|
||||
assert isinstance(return_value, PythonNode)
|
||||
assert return_value.source == "foo + 1"
|
||||
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__C__ + 1")
|
||||
assert return_value.concepts["__C__foo__C__"] == foo
|
||||
|
||||
|
||||
def test_i_can_parse_concepts_and_python_when_concept_is_known():
|
||||
context = get_context()
|
||||
foo = Concept("foo")
|
||||
foo = context.sheerka.create_new_concept(context, foo).body.body
|
||||
input_return_value = get_ret_from(foo, " + 1")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
wrapper = result.value
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert result.who == parser.name
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert wrapper.source == "foo + 1"
|
||||
assert isinstance(return_value, PythonNode)
|
||||
assert return_value.source == "foo + 1"
|
||||
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__1001__C__ + 1")
|
||||
assert return_value.concepts["__C__foo__1001__C__"] == foo
|
||||
|
||||
|
||||
def test_i_can_parse_when_concept_name_has_invalid_characters():
|
||||
context = get_context()
|
||||
foo = Concept("foo et > (,")
|
||||
foo = context.sheerka.create_new_concept(context, foo).body.body
|
||||
input_return_value = get_ret_from(foo, " + 1")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert return_value.concepts["__C__foo0et000000__1001__C__"] == foo
|
||||
|
||||
|
||||
def test_python_ids_mappings_are_correct_when_concepts_with_the_same_name():
|
||||
context = get_context()
|
||||
foo1 = Concept("foo")
|
||||
foo2 = Concept("foo")
|
||||
foo3 = context.sheerka.create_new_concept(context, Concept("foo", body="foo3")).body.body
|
||||
foo4 = context.sheerka.create_new_concept(context, Concept("foo", body="foo4")).body.body
|
||||
|
||||
input_return_value = get_ret_from(foo1, "+", foo2, "+", foo3, "+", foo4)
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
return_value = result.value.value
|
||||
|
||||
assert result.status
|
||||
assert return_value.concepts["__C__foo__C__"] == foo1
|
||||
assert return_value.concepts["__C__foo_1__C__"] == foo2
|
||||
assert return_value.concepts["__C__foo__1001__C__"] == foo3
|
||||
assert return_value.concepts["__C__foo__1002__C__"] == foo4
|
||||
|
||||
|
||||
def test_i_cannot_parse_if_syntax_error():
|
||||
context = get_context()
|
||||
foo = Concept("foo")
|
||||
foo = context.sheerka.create_new_concept(context, foo).body.body
|
||||
input_return_value = get_ret_from(foo, " + ")
|
||||
|
||||
parser = PythonWithConceptsParser()
|
||||
result = parser.parse(context, input_return_value.body)
|
||||
wrapper = result.value
|
||||
return_value = result.value.value
|
||||
|
||||
assert not result.status
|
||||
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert isinstance(return_value[0], PythonErrorNode)
|
||||
@@ -1,112 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.TooManySuccessEvaluator import TooManySuccessEvaluator
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_context():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def r(name, status=True, value=None):
|
||||
value = value or name
|
||||
return ReturnValueConcept(name, status, value)
|
||||
|
||||
|
||||
reduce_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.REDUCE_REQUESTED))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("return_values, expected", [
|
||||
([r("evaluators.success1"), r("evaluators.success2"), reduce_requested], True),
|
||||
([r("evaluators.success1"), r("evaluators.success2"), r("other"), reduce_requested], True),
|
||||
([r("evaluators.success1"), r("evaluators.success2"), r("other", False), reduce_requested], True),
|
||||
([r("evaluators.a", value=Concept("c1", body="1")),
|
||||
r("evaluators.a", value=Concept("c2", body="1")),
|
||||
r("other"),
|
||||
reduce_requested], True),
|
||||
([r("evaluators.a", value=Concept("c1", body="1")),
|
||||
r("evaluators.a", value=Concept("c2", body="1")),
|
||||
r("parsers.other", False),
|
||||
reduce_requested], True),
|
||||
([r("evaluators.a", value=Concept("c1", body="1")),
|
||||
r("evaluators.a", value=Concept("c2", body="1")),
|
||||
r("parsers.other"),
|
||||
reduce_requested], False),
|
||||
([r("evaluators.success1"), reduce_requested], False),
|
||||
([reduce_requested], False),
|
||||
([r("evaluators.success1"), r("evaluators.success2")], False),
|
||||
])
|
||||
def test_i_can_match(return_values, expected):
|
||||
context = get_context()
|
||||
assert TooManySuccessEvaluator().matches(context, return_values) == expected
|
||||
|
||||
|
||||
def test_i_can_eval():
|
||||
context = get_context()
|
||||
|
||||
value1 = r("evaluators.a", value=Concept("c1", body="1"))
|
||||
value2 = r("evaluators.a", value=Concept("c2", body="2"))
|
||||
return_values = [
|
||||
value1,
|
||||
value2,
|
||||
r("other", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = TooManySuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.body, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||
assert res.body.body == [value1, value2]
|
||||
assert len(res.parents) == 4
|
||||
|
||||
|
||||
def test_i_can_eval_when_same_success():
|
||||
context = get_context()
|
||||
|
||||
return_values = [
|
||||
r("evaluators.a", value=Concept("c1", body="1").auto_init()),
|
||||
r("evaluators.a", value=Concept("c2", body="1").auto_init()),
|
||||
r("other", False),
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = TooManySuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert res is None
|
||||
|
||||
|
||||
def test_other_success_are_not_reduced():
|
||||
context = get_context()
|
||||
|
||||
value1 = r("evaluators.a", value=Concept("c1", body="1").auto_init())
|
||||
value2 = r("evaluators.a", value=Concept("c2", body="2").auto_init())
|
||||
other_success = r("other")
|
||||
return_values = [
|
||||
value1,
|
||||
value2,
|
||||
other_success,
|
||||
reduce_requested
|
||||
]
|
||||
|
||||
evaluator = TooManySuccessEvaluator()
|
||||
matches = evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert matches
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.body, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||
assert res.body.body == [value1, value2]
|
||||
assert len(res.parents) == 3
|
||||
assert other_success not in res.parents
|
||||
@@ -1,171 +0,0 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
import core.builtin_helpers
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def test_i_can_use_expect_one_when_empty():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), [])
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.IS_EMPTY)
|
||||
|
||||
|
||||
def test_i_can_use_expect_one_when_too_many_success():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", True, "value1"),
|
||||
ReturnValueConcept("who", True, "value2"),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||
assert res.value.body == items
|
||||
assert res.parents == items
|
||||
|
||||
|
||||
def test_i_can_use_expect_one_when_same_success():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", True, "value"),
|
||||
ReturnValueConcept("who", True, "value"),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||
assert res.status
|
||||
assert res.value == items[0].value
|
||||
assert res.parents == items
|
||||
|
||||
|
||||
def test_i_can_use_expect_when_only_errors_1():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", False, sheerka.new(BuiltinConcepts.ERROR)),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||
assert not res.status
|
||||
assert res.value, items[0]
|
||||
assert res.parents == items
|
||||
|
||||
|
||||
def test_i_can_use_expect_when_only_errors_2():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", False, None),
|
||||
ReturnValueConcept("who", False, None),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
assert res.value.body == items
|
||||
assert res.parents == items
|
||||
|
||||
|
||||
def test_i_can_use_expect_one_when_one_success_1():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", True, None),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||
assert res.status
|
||||
assert res.body == items[0].body
|
||||
assert res.parents == items
|
||||
|
||||
|
||||
def test_i_can_use_expect_one_when_one_success_2():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
items = [
|
||||
ReturnValueConcept("who", False, None),
|
||||
ReturnValueConcept("who", True, None),
|
||||
ReturnValueConcept("who", False, None),
|
||||
]
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||
assert res.status
|
||||
assert res.body == items[1].body
|
||||
assert res.parents == items
|
||||
|
||||
|
||||
def test_i_can_use_expect_one_when_not_a_list_true():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
item = ReturnValueConcept("who", True, None)
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), item)
|
||||
assert res.status
|
||||
assert res == item
|
||||
|
||||
|
||||
def test_i_can_use_expect_one_when_not_a_list_false():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
item = ReturnValueConcept("who", False, None)
|
||||
res = core.builtin_helpers.expect_one(get_context(sheerka), item)
|
||||
|
||||
assert not res.status
|
||||
assert res == item
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, vars_to_include, vars_to_exclude, expected_expr", [
|
||||
("a == 1", [], [], []),
|
||||
("a == 1", ["a"], [], ["a == 1"]),
|
||||
("a == 1", [], ["a"], []),
|
||||
("predicate(a)", [], [], []),
|
||||
("predicate(a)", ["a"], [], ["predicate(a)"]),
|
||||
("predicate(a, b)", ["a"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["b"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["a", "b"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["a"], ["b"], []),
|
||||
("a + b == 1", [], [], []),
|
||||
("a + b == 1", ["a"], [], ["a + b == 1"]),
|
||||
("a + b == 1", ["a"], ["b"], []),
|
||||
("a + b == 1", ["b"], [], ["a + b == 1"]),
|
||||
("a + b == 1", ["a", "b"], [], ["a + b == 1"]),
|
||||
("a == 1 and b == 2", [], [], []),
|
||||
("a == 1 and b == 2", ["a"], [], ["a == 1"]),
|
||||
("a == 1 and b == 2", ["b"], [], ["b == 2"]),
|
||||
("a == 1 and b == 2", ["a"], ["b"], ["a == 1"]),
|
||||
("a == 1 and b == 2", ["a", "b"], [], ["a == 1 and b == 2"]),
|
||||
("predicate(a,c) and predicate(b,c)", ["a", "b"], [], ["predicate(a,c) and predicate(b,c)"]),
|
||||
("not(a == 1)", [], [], []),
|
||||
("not(a == 1)", ["a"], [], ["not(a==1)"]),
|
||||
("a == 1 or b == 2", [], [], []),
|
||||
("a == 1 or b == 2", ["a"], [], ["a == 1"]),
|
||||
("a == 1 or b == 2", ["b"], [], ["b == 2"]),
|
||||
("a == 1 or b == 2", ["a", "b"], [], ["a == 1 or b == 2"]),
|
||||
("predicate(a,c) or predicate(b,c)", ["a", "b"], [], ["predicate(a,c) or predicate(b,c)"]),
|
||||
])
|
||||
def test_i_can_extract_predicates(expression, vars_to_include, vars_to_exclude, expected_expr):
|
||||
sheerka = get_sheerka()
|
||||
expected = [ast.parse(expr, mode="eval") for expr in expected_expr]
|
||||
|
||||
actual = core.builtin_helpers.extract_predicates(sheerka, expression, vars_to_include, vars_to_exclude)
|
||||
assert len(actual) == len(expected)
|
||||
for i in range(len(actual)):
|
||||
assert dump_ast(actual[i]) == dump_ast(expected[i])
|
||||
|
||||
|
||||
def get_sheerka():
|
||||
sheerka = Sheerka(skip_builtins_in_db=True)
|
||||
sheerka.initialize("mem://")
|
||||
|
||||
return sheerka
|
||||
|
||||
|
||||
def get_context(sheerka):
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def dump_ast(node):
|
||||
dump = ast.dump(node)
|
||||
for to_remove in [", ctx=Load()", ", kind=None", ", type_ignores=[]"]:
|
||||
dump = dump.replace(to_remove, "")
|
||||
return dump
|
||||
@@ -1,955 +0,0 @@
|
||||
import pytest
|
||||
import os
|
||||
from os import path
|
||||
import shutil
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept, ConceptAlreadyInSet, \
|
||||
ParserResultConcept
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property, ConceptParts, DoNotResolve, simplec
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event
|
||||
|
||||
tests_root = path.abspath("../build/tests")
|
||||
root_folder = "init_folder"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def init_test():
|
||||
if path.exists(tests_root):
|
||||
shutil.rmtree(tests_root)
|
||||
|
||||
if not path.exists(tests_root):
|
||||
os.makedirs(tests_root)
|
||||
current_pwd = os.getcwd()
|
||||
os.chdir(tests_root)
|
||||
|
||||
yield None
|
||||
|
||||
os.chdir(current_pwd)
|
||||
|
||||
|
||||
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=skip_builtins_in_db)
|
||||
sheerka.initialize(root)
|
||||
|
||||
return sheerka
|
||||
|
||||
|
||||
def get_context(sheerka):
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_default_concept():
|
||||
concept = Concept(
|
||||
name="a + b",
|
||||
where="isinstance(a, int) and isinstance(b, int)",
|
||||
pre="isinstance(a, int) and isinstance(b, int)",
|
||||
post="isinstance(res, int)",
|
||||
body="def func(x,y):\n return x+y\nfunc(a,b)",
|
||||
desc="specific description")
|
||||
concept.def_prop("a", "value1")
|
||||
concept.def_prop("b", "value2")
|
||||
|
||||
return concept
|
||||
|
||||
|
||||
class ConceptWithGetValue(Concept):
|
||||
def get_value(self):
|
||||
return self.get_prop("my_prop")
|
||||
|
||||
|
||||
def test_root_folder_is_created_after_initialization():
|
||||
return_value = Sheerka().initialize(root_folder)
|
||||
assert return_value.status, "initialisation should be successful"
|
||||
assert os.path.exists(root_folder), "init folder should be created"
|
||||
|
||||
|
||||
def test_i_can_list_builtin_concepts():
|
||||
sheerka = get_sheerka()
|
||||
builtins = list(sheerka.get_builtins_classes_as_dict())
|
||||
|
||||
assert str(BuiltinConcepts.ERROR) in builtins
|
||||
assert str(BuiltinConcepts.RETURN_VALUE) in builtins
|
||||
|
||||
|
||||
def test_builtin_concepts_are_initialized():
|
||||
sheerka = get_sheerka(skip_builtins_in_db=False)
|
||||
assert len(sheerka.cache_by_key) == len(BuiltinConcepts)
|
||||
for concept_name in BuiltinConcepts:
|
||||
assert str(concept_name) in sheerka.cache_by_key
|
||||
assert sheerka.sdp.get_safe(sheerka.CONCEPTS_ENTRY, str(concept_name)) is not None
|
||||
|
||||
for key, concept_class in sheerka.get_builtins_classes_as_dict().items():
|
||||
assert isinstance(sheerka.cache_by_key[key], concept_class)
|
||||
|
||||
|
||||
def test_builtin_concepts_can_be_updated():
|
||||
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, False)
|
||||
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
||||
|
||||
assert loaded_sheerka.metadata.desc == "I have a description"
|
||||
|
||||
|
||||
def test_i_can_add_a_concept():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
|
||||
res = sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
concept_found = res.value.body
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_found.metadata, prop) == getattr(concept.metadata, prop)
|
||||
|
||||
assert concept_found.key == "__var__0 + __var__1"
|
||||
assert concept_found.id == "1001"
|
||||
|
||||
assert concept.key in sheerka.cache_by_key
|
||||
assert concept.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_found.get_digest()))
|
||||
|
||||
|
||||
def test_i_cannot_add_the_same_concept_twice():
|
||||
"""
|
||||
Checks that duplicated concepts are managed by sheerka, not by sheerka.sdp
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
res = sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
|
||||
assert res.value.body == concept
|
||||
|
||||
|
||||
def test_i_can_get_a_builtin_concept_by_their_enum_or_the_string():
|
||||
"""
|
||||
Checks that a concept can be found its name
|
||||
even when there are variables in the name (ex 'hello + a' or 'a + b' )
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
for key in sheerka.get_builtins_classes_as_dict():
|
||||
assert sheerka.get(key) is not None
|
||||
assert sheerka.get(str(key)) is not None
|
||||
|
||||
|
||||
def test_i_can_get_a_newly_created_concept():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
from_cache = sheerka.get(concept.key)
|
||||
assert from_cache is not None
|
||||
assert from_cache == concept
|
||||
|
||||
from_cache = sheerka.get_by_id(concept.id)
|
||||
assert from_cache is not None
|
||||
assert from_cache == concept
|
||||
|
||||
|
||||
def test_i_first_look_in_local_cache():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
sheerka.cache_by_key[concept.key].pre = "I have modified the concept in cache"
|
||||
|
||||
from_cache = sheerka.get(concept.key)
|
||||
assert from_cache is not None
|
||||
assert from_cache.key == concept.key
|
||||
assert from_cache.pre == "I have modified the concept in cache"
|
||||
|
||||
|
||||
def test_i_can_get_a_known_concept_when_not_in_cache():
|
||||
"""
|
||||
When not in cache, uses sdp
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
loaded = sheerka.get(concept.key)
|
||||
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
# I can also get it by its id
|
||||
loaded = sheerka.sdp.get(sheerka.CONCEPTS_BY_ID_ENTRY, concept.id)
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
|
||||
def test_i_can_get_a_concept_by_its_id():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
loaded = sheerka.get_by_id(concept.id)
|
||||
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
|
||||
def test_i_can_get_list_of_concept_when_same_key_when_no_cache():
|
||||
sheerka = get_sheerka()
|
||||
concept1 = get_default_concept()
|
||||
concept2 = get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
|
||||
result = sheerka.get(concept1.key)
|
||||
assert len(result) == 2
|
||||
assert result[0] == concept1
|
||||
assert result[1] == concept2
|
||||
|
||||
|
||||
def test_i_can_get_list_of_concept_when_same_key_when_cache():
|
||||
sheerka = get_sheerka()
|
||||
concept1 = get_default_concept()
|
||||
concept2 = get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
# sheerka.cache_by_key = {} # Do not reset the cache
|
||||
|
||||
result = sheerka.get(concept1.key)
|
||||
assert len(result) == 2
|
||||
assert result[0] == concept1
|
||||
assert result[1] == concept2
|
||||
|
||||
|
||||
def test_i_can_get_the_correct_concept_using_the_id_when_same_key_when_no_cache():
|
||||
sheerka = get_sheerka()
|
||||
concept1 = get_default_concept()
|
||||
concept2 = get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
result = sheerka.get(concept1.key, res2.body.body.id)
|
||||
assert result.name == "a + b"
|
||||
assert result.metadata.body == "a+b"
|
||||
|
||||
|
||||
def test_i_can_get_the_correct_concept_using_the_id__when_same_key_when_cache():
|
||||
sheerka = get_sheerka()
|
||||
concept1 = get_default_concept()
|
||||
concept2 = get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
result = sheerka.get(concept1.key, res2.body.body.id)
|
||||
assert result.name == "a + b"
|
||||
assert result.metadata.body == "a+b"
|
||||
|
||||
|
||||
def test_i_cannot_get_the_correct_concept_id_the_id_is_wrong():
|
||||
sheerka = get_sheerka()
|
||||
concept1 = get_default_concept()
|
||||
concept2 = get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
result = sheerka.get(concept1.key, "wrong id")
|
||||
assert sheerka.isinstance(result, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
|
||||
|
||||
def test_i_cannot_get_when_key_is_none():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
res = sheerka.get(None)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.ERROR)
|
||||
assert res.body == "Concept key is undefined."
|
||||
|
||||
|
||||
def test_unknown_concept_is_return_when_the_concept_key_is_not_found():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
loaded = sheerka.get("key_that_does_not_exist")
|
||||
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == ("key", "key_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_unknown_concept_is_return_when_the_concept_id_is_not_found():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
loaded = sheerka.get_by_id("id_that_does_not_exist")
|
||||
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == ("id", "id_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_instantiate_a_builtin_concept_when_it_has_its_own_class():
|
||||
sheerka = get_sheerka()
|
||||
ret = sheerka.new(BuiltinConcepts.RETURN_VALUE, who="who", status="status", value="value", message="message")
|
||||
|
||||
assert isinstance(ret, ReturnValueConcept)
|
||||
assert ret.key == str(BuiltinConcepts.RETURN_VALUE)
|
||||
assert ret.who == "who"
|
||||
assert ret.status == "status"
|
||||
assert ret.value == "value"
|
||||
assert ret.message == "message"
|
||||
|
||||
|
||||
def test_i_can_instantiate_a_builtin_concept_when_no_specific_class():
|
||||
sheerka = get_sheerka()
|
||||
ret = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body="fake_concept")
|
||||
|
||||
assert isinstance(ret, Concept)
|
||||
assert ret.key == str(BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert ret.body == "fake_concept"
|
||||
|
||||
|
||||
def test_i_can_instantiate_a_concept():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
new = sheerka.new(concept.key, a=10, b="value")
|
||||
|
||||
assert sheerka.isinstance(new, concept)
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(new.metadata, prop) == getattr(concept.metadata, prop)
|
||||
|
||||
assert new.props["a"].value == 10
|
||||
assert new.props["b"].value == "value"
|
||||
|
||||
|
||||
def test_i_can_instantiate_with_the_name_and_the_id():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
|
||||
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo2"))
|
||||
|
||||
concepts = sheerka.new("foo")
|
||||
assert len(concepts) == 2
|
||||
|
||||
foo1 = sheerka.new(("foo", "1001"))
|
||||
assert foo1.metadata.body == "foo1"
|
||||
|
||||
foo2 = sheerka.new(("foo", "1002"))
|
||||
assert foo2.metadata.body == "foo2"
|
||||
|
||||
|
||||
def test_instances_are_different_when_asking_for_new():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
new1 = sheerka.new(concept.key, a=10, b="value")
|
||||
new2 = sheerka.new(concept.key, a=10, b="value")
|
||||
|
||||
assert new1 == new2
|
||||
assert id(new1) != id(new2)
|
||||
|
||||
|
||||
def test_i_get_the_same_instance_when_is_unique_is_true():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept(name="unique", is_unique=True)
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
new1 = sheerka.new(concept.key, a=10, b="value")
|
||||
new2 = sheerka.new(concept.key, a=10, b="value")
|
||||
|
||||
assert new1 == new2
|
||||
assert id(new1) == id(new2)
|
||||
|
||||
|
||||
def test_i_cannot_instantiate_an_unknown_concept():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
new = sheerka.new("fake_concept")
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == ('key', 'fake_concept')
|
||||
|
||||
|
||||
def test_i_cannot_instantiate_with_invalid_id():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
|
||||
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo2"))
|
||||
|
||||
new = sheerka.new(("foo", "invalid_id"))
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == [('key', 'foo'), ('id', 'invalid_id')]
|
||||
|
||||
|
||||
def test_i_cannot_instantiate_with_invalid_key():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
|
||||
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo2"))
|
||||
|
||||
new = sheerka.new(("invalid_key", "1001"))
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == [('key', 'invalid_key'), ('id', '1001')]
|
||||
|
||||
|
||||
def test_concept_id_is_irrelevant_when_only_one_concept():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
|
||||
|
||||
new = sheerka.new(("foo", "invalid_id"))
|
||||
|
||||
assert sheerka.isinstance(new, "foo")
|
||||
assert new.metadata.body == "foo1"
|
||||
|
||||
|
||||
def test_i_cannot_instantiate_when_properties_are_not_recognized():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
new = sheerka.new(concept.key, a=10, c="value")
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_PROPERTY)
|
||||
assert new.property_name == "c"
|
||||
assert sheerka.isinstance(new.concept, concept)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("concept, reduce_simple_list, expected", [
|
||||
(None, False, None),
|
||||
(3.14, False, 3.14),
|
||||
("foo", False, "foo"),
|
||||
(True, False, True),
|
||||
(Concept("name", body="foo"), False, "foo"),
|
||||
(Concept("name"), False, Concept("name")),
|
||||
(ConceptWithGetValue("name").set_prop("my_prop", "my_value"), False, "my_value"),
|
||||
(ReturnValueConcept(value="return_value"), False, "return_value"),
|
||||
(ReturnValueConcept(value=Concept(key=BuiltinConcepts.USER_INPUT, body="text"), status=True), False, "text"),
|
||||
(ReturnValueConcept(value=UserInputConcept("text"), status=True), False, "text"),
|
||||
(Concept("name", body=["foo", "bar"]), False, ["foo", "bar"]),
|
||||
(Concept("name", body=["foo"]), True, "foo"),
|
||||
(Concept("name", body=Concept("foo")), False, Concept("foo")),
|
||||
(Concept("name", body=Concept("foo", body="value")), False, "value"),
|
||||
(Concept("name", body=Concept("foo", body=Concept("bar", body="value"))), False, "value"),
|
||||
(Concept("name", body=Concept("foo", body=ReturnValueConcept(value="return_value"))), False, "return_value"),
|
||||
])
|
||||
def test_i_can_get_value(concept, reduce_simple_list, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
# I use auto_init() instead of evaluate_concept() to be quicker
|
||||
c = concept
|
||||
while isinstance(c, Concept):
|
||||
c.auto_init()
|
||||
c = c.body
|
||||
|
||||
assert sheerka.value(concept, reduce_simple_list) == expected
|
||||
|
||||
|
||||
def test_list_of_concept_is_sorted_by_id():
|
||||
sheerka = get_sheerka(False, False)
|
||||
concepts = sheerka.concepts()
|
||||
|
||||
assert concepts[0].id < concepts[-1].id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("body, expected", [
|
||||
# (None, None),
|
||||
# ("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
("'one'", "one"),
|
||||
("'one' + 'two'", "onetwo"),
|
||||
("True", True),
|
||||
("1 > 2", False),
|
||||
])
|
||||
def test_i_can_evaluate_a_concept_with_simple_body(body, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo", body=body)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == expected
|
||||
assert evaluated.metadata.body == body
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.props == {}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert len(evaluated.values) == 0 if body is None else 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
("'one'", "one"),
|
||||
("'one' + 'two'", "onetwo"),
|
||||
("True", True),
|
||||
("1 > 2", False),
|
||||
])
|
||||
def test_i_can_evaluate_the_other_metadata(expr, expected):
|
||||
"""
|
||||
I only test WHERE, it's the same for the others
|
||||
:param expr:
|
||||
:param expected:
|
||||
:return:
|
||||
"""
|
||||
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo", where=expr)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.metadata.body is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where == expr
|
||||
assert evaluated.get_metadata_value(ConceptParts.WHERE) == expected
|
||||
assert evaluated.props == {}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert len(evaluated.values) == 0 if expr is None else 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
(None, None),
|
||||
("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
("'one'", "one"),
|
||||
("'one' + 'two'", "onetwo"),
|
||||
("True", True),
|
||||
("1 > 2", False),
|
||||
])
|
||||
def test_i_can_evaluate_a_concept_with_prop(expr, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo").def_prop("a", expr)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.props == {"a": Property("a", expected)}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_evaluate_metadata_using_do_not_resolve():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept("foo")
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_evaluate_property_using_do_not_resolve():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept("foo").def_prop("a")
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.get_prop("a") == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_original_value_is_overridden_when_using_do_no_resolve():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept("foo", body="original value").set_prop("a", "original value")
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.get_prop("a") == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_props_are_evaluated_before_body():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo", body="a+1").def_prop("a", "10").init_key()
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 11
|
||||
|
||||
|
||||
def test_i_can_evaluate_when_another_concept_is_referenced():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = Concept("a")
|
||||
sheerka.add_in_cache(concept_a)
|
||||
|
||||
concept = Concept("foo", body="a").init_key()
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated == simplec("foo", simplec("a", None))
|
||||
assert id(evaluated.body) != id(concept_a)
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.body.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_evaluate_when_the_referenced_concept_has_a_body():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = Concept("a", body="1")
|
||||
sheerka.add_in_cache(concept_a)
|
||||
|
||||
concept = Concept("foo", body="a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == simplec("a", 1)
|
||||
assert not concept_a.metadata.is_evaluated
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_evaluate_concept_of_concept_when_the_leaf_has_a_body():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="'a'"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="a"))
|
||||
sheerka.add_in_cache(Concept(name="c", body="b"))
|
||||
concept_d = sheerka.add_in_cache(Concept(name="d", body="c"))
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept_d)
|
||||
|
||||
assert evaluated.key == concept_d.key
|
||||
expected = simplec("c", simplec("b", simplec("a", "a")))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.value(evaluated) == 'a'
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_evaluate_concept_of_concept_does_not_have_a_body():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="a"))
|
||||
sheerka.add_in_cache(Concept(name="c", body="b"))
|
||||
concept_d = sheerka.add_in_cache(Concept(name="d", body="c"))
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept_d)
|
||||
|
||||
assert evaluated.key == concept_d.key
|
||||
expected = simplec("c", simplec("b", simplec("a", None)))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.value(evaluated) == Concept(name="a").init_key()
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_reference_others_concepts():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a").init_key())
|
||||
|
||||
concept = Concept("foo", body="a").def_prop("a", "a").init_key()
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
# first prop a is evaluated to concept_a
|
||||
# then body is evaluated to prop a -> concept_a
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == concept_a
|
||||
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_reference_others_concepts_2():
|
||||
"""
|
||||
Same test,
|
||||
but the name of the property and the name of the concept are different
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a"))
|
||||
|
||||
concept = Concept("foo", body="concept_a").def_prop("concept_a", "a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == concept_a
|
||||
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_reference_others_concepts_with_body():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="1"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="2"))
|
||||
|
||||
concept = Concept("foo", body="propA + propB").def_prop("propA", "a").def_prop("propB", "b")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
|
||||
def test_i_can_evaluate_concept_when_properties_is_a_concept():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a", body="'a'").init_key())
|
||||
|
||||
concept = Concept("foo").def_prop("a")
|
||||
concept.compiled["a"] = concept_a
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.get_prop("a") == simplec("a", "a")
|
||||
|
||||
|
||||
def test_i_can_evaluate_when_property_asts_is_a_list():
|
||||
sheerka = get_sheerka()
|
||||
foo = Concept("foo", body="1")
|
||||
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = [foo, DoNotResolve("1")]
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
props = evaluated.get_prop("prop")
|
||||
assert len(props) == 2
|
||||
assert props[0] == simplec("foo", 1)
|
||||
assert props[1] == "1"
|
||||
|
||||
|
||||
def test_i_can_evaluate_when_compiled_is_set_up_with_return_value():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
python_node = PythonNode("1 +1 ")
|
||||
parser_result = ParserResultConcept(parser="who", value=python_node)
|
||||
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = [ReturnValueConcept("who", True, parser_result)]
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.get_prop("prop") == 2
|
||||
|
||||
# also works when only one return value
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = ReturnValueConcept("who", True, parser_result)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.get_prop("prop") == 2
|
||||
|
||||
|
||||
def test_i_can_reference_sheerka():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo", body="sheerka.test()").init_key()
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == sheerka.test()
|
||||
|
||||
|
||||
def test_properties_values_takes_precedence_over_the_outside_world():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="'concept_a'"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="'concept_b'"))
|
||||
|
||||
concept = Concept("foo", body="a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == simplec("a", "concept_a") # this test was already done
|
||||
|
||||
# so check this one.
|
||||
concept = Concept("foo", body="a").def_prop("a", "'property_a'")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 'property_a'
|
||||
|
||||
# or this one.
|
||||
concept = Concept("foo", body="a").def_prop("a", "b")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == simplec(name="b", body="concept_b")
|
||||
|
||||
|
||||
def test_properties_values_takes_precedence():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="a", body="'concept_a'"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="'concept_b'"))
|
||||
|
||||
concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 'prop_aconcept_b'
|
||||
|
||||
|
||||
def test_i_can_reference_sub_property_of_a_property():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="concept_a").def_prop("subProp", "'sub_a'"))
|
||||
|
||||
concept = Concept("foo", body="a.props['subProp'].value").def_prop("a", "concept_a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated == simplec(concept.key, "sub_a")
|
||||
|
||||
|
||||
def test_i_cannot_evaluate_concept_if_property_is_in_error():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept(name="concept_a").def_prop("subProp", "undef_concept")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
|
||||
|
||||
def test_key_is_initialized_by_evaluation():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.init_key().key
|
||||
|
||||
|
||||
def test_builtin_error_concept_are_errors():
|
||||
# only test a random one, it will be the same for the others
|
||||
sheerka = get_sheerka()
|
||||
assert not sheerka.is_success(sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS))
|
||||
|
||||
|
||||
def test_i_can_add_concept_to_set():
|
||||
sheerka = get_sheerka(False, False)
|
||||
|
||||
foo = Concept("foo")
|
||||
sheerka.set_id_if_needed(foo, False)
|
||||
|
||||
all_foos = Concept("all_foos")
|
||||
sheerka.set_id_if_needed(all_foos, False)
|
||||
|
||||
context = get_context(sheerka)
|
||||
res = sheerka.add_concept_to_set(context, foo, all_foos)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
all_entries = get_sheerka(False, False).sdp.get("All_" + all_foos.id, None, False)
|
||||
assert len(all_entries) == 1
|
||||
assert foo.id in all_entries
|
||||
|
||||
|
||||
def test_i_can_add_several_concepts_to_set():
|
||||
sheerka = get_sheerka(False, False)
|
||||
|
||||
foo1 = Concept("foo1")
|
||||
sheerka.set_id_if_needed(foo1, False)
|
||||
|
||||
foo2 = Concept("foo1")
|
||||
sheerka.set_id_if_needed(foo2, False)
|
||||
|
||||
all_foos = Concept("all_foos")
|
||||
sheerka.set_id_if_needed(all_foos, False)
|
||||
|
||||
context = get_context(sheerka)
|
||||
sheerka.add_concept_to_set(context, foo1, all_foos)
|
||||
res = sheerka.add_concept_to_set(context, foo2, all_foos)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
all_entries = get_sheerka(False, False).sdp.get("All_" + all_foos.id, None, False)
|
||||
assert len(all_entries) == 2
|
||||
assert foo1.id in all_entries
|
||||
assert foo2.id in all_entries
|
||||
|
||||
|
||||
def test_i_cannot_add_the_same_concept_twice_in_a_set():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
foo = Concept("foo")
|
||||
sheerka.set_id_if_needed(foo, False)
|
||||
|
||||
all_foos = Concept("all_foos")
|
||||
sheerka.set_id_if_needed(all_foos, False)
|
||||
|
||||
context = get_context(sheerka)
|
||||
sheerka.add_concept_to_set(context, foo, all_foos)
|
||||
res = sheerka.add_concept_to_set(context, foo, all_foos)
|
||||
|
||||
assert not res.status
|
||||
assert res.body == ConceptAlreadyInSet(foo, all_foos)
|
||||
|
||||
all_entries = sheerka.sdp.get("All_" + all_foos.id, None, False)
|
||||
assert len(all_entries) == 1
|
||||
assert foo.id in all_entries
|
||||
|
||||
|
||||
def test_i_get_elements_from_a_set():
|
||||
sheerka = get_sheerka(False, False)
|
||||
|
||||
one = Concept("one")
|
||||
two = Concept("two")
|
||||
three = Concept("three")
|
||||
number = Concept("number")
|
||||
|
||||
for c in [one, two, three, number]:
|
||||
sheerka.set_id_if_needed(c, False)
|
||||
sheerka.add_in_cache(c)
|
||||
|
||||
context = get_context(sheerka)
|
||||
for c in [one, two, three]:
|
||||
sheerka.add_concept_to_set(context, c, number)
|
||||
|
||||
elements = sheerka.get_set_elements(number)
|
||||
|
||||
assert set(elements) == set([one, two, three])
|
||||
|
||||
|
||||
def test_i_cannot_get_elements_if_not_a_set():
|
||||
sheerka = get_sheerka(False, False)
|
||||
one = Concept("one")
|
||||
sheerka.set_id_if_needed(one, False)
|
||||
sheerka.add_in_cache(one)
|
||||
|
||||
error = sheerka.get_set_elements(one)
|
||||
|
||||
assert sheerka.isinstance(error, BuiltinConcepts.NOT_A_SET)
|
||||
assert error.body == one
|
||||
|
||||
|
||||
def test_isa_and_isa_group():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
group = Concept("group").init_key()
|
||||
group.metadata.id = "1001"
|
||||
assert not sheerka.isagroup(group)
|
||||
|
||||
foo = Concept("foo").init_key()
|
||||
foo.metadata.id = "1002"
|
||||
assert not sheerka.isa(foo, group)
|
||||
|
||||
context = get_context(sheerka)
|
||||
sheerka.add_concept_to_set(context, foo, group)
|
||||
assert sheerka.isagroup(group)
|
||||
assert sheerka.isa(foo, group)
|
||||
@@ -1,399 +0,0 @@
|
||||
# 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, AllReturnValuesEvaluator
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_sheerka():
|
||||
sheerka = Sheerka()
|
||||
sheerka.initialize("mem://")
|
||||
return sheerka
|
||||
|
||||
|
||||
def get_context(sheerka):
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_ret_val(sheerka, concept, who="who"):
|
||||
concept.init_key()
|
||||
if concept.key not in sheerka.cache_by_key:
|
||||
sheerka.cache_by_key[concept.key] = concept
|
||||
return sheerka.ret(who, True, sheerka.new(concept.key))
|
||||
|
||||
|
||||
class Out:
|
||||
debug_out = []
|
||||
|
||||
def out(self, method, name, context, return_value):
|
||||
name = name[len(BaseEvaluator.PREFIX):]
|
||||
if isinstance(return_value, list):
|
||||
target = [str(r.body.key) for r in return_value]
|
||||
else:
|
||||
target = str(return_value.body.key)
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
text += f"{name} - {method} - target={target}"
|
||||
self.debug_out.append(text)
|
||||
|
||||
def out_all(self, method, name, context, return_values):
|
||||
name = name[len(BaseEvaluator.PREFIX):]
|
||||
target = [str(r.body.key) for r in return_values]
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
text += f"{name} - {method} - target={target}"
|
||||
self.debug_out.append(text)
|
||||
|
||||
|
||||
class OneReturnValueEvaluatorForTestingPurpose(OneReturnValueEvaluator, Out):
|
||||
def __init__(self, name, steps, priority):
|
||||
super().__init__(name, steps, priority)
|
||||
|
||||
def matches(self, context, return_value):
|
||||
self.out("matches", self.name, context, return_value)
|
||||
return True
|
||||
|
||||
def eval(self, context, return_value):
|
||||
self.out("eval", self.name, context, return_value)
|
||||
|
||||
|
||||
class AllReturnValueEvaluatorForTestingPurpose(AllReturnValuesEvaluator, Out):
|
||||
def __init__(self, name, steps, priority):
|
||||
super().__init__(name, steps, priority)
|
||||
|
||||
def matches(self, context, return_values):
|
||||
self.out("matches", self.name, context, return_values)
|
||||
return True
|
||||
|
||||
def eval(self, context, return_values):
|
||||
self.out("eval", self.name, context, return_values)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority(OneReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self, name, priority):
|
||||
super().__init__(name, [BuiltinConcepts.EVALUATION], priority)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority10(EvaluatorOneWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority10", 10)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority15(EvaluatorOneWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority15", 15)
|
||||
|
||||
|
||||
class EvaluatorOneWithPriority20(EvaluatorOneWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("priority20", 20)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority(AllReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self, name, priority):
|
||||
super().__init__(name, [BuiltinConcepts.EVALUATION], priority)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority10(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_priority10", 10)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority15(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_priority15", 15)
|
||||
|
||||
|
||||
class EvaluatorAllWithPriority20(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_priority20", 20)
|
||||
|
||||
|
||||
class EvaluatorOneModifyFoo(EvaluatorOneWithPriority):
|
||||
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 EvaluatorOneModifyBar(EvaluatorOneWithPriority):
|
||||
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"))
|
||||
|
||||
|
||||
class EvaluatorOnePreEvaluation(OneReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self):
|
||||
super().__init__("preEval", [BuiltinConcepts.BEFORE_EVALUATION], 10)
|
||||
|
||||
|
||||
class EvaluatorOneMultiSteps(OneReturnValueEvaluatorForTestingPurpose):
|
||||
def __init__(self):
|
||||
super().__init__("multiStep", [BuiltinConcepts.EVALUATION, BuiltinConcepts.BEFORE_EVALUATION], 10)
|
||||
|
||||
|
||||
class EvaluatorAllReduceFooBar(EvaluatorAllWithPriority):
|
||||
def __init__(self):
|
||||
super().__init__("all_reduce_foobar", 10)
|
||||
|
||||
def matches(self, context, return_values):
|
||||
super().matches(context, return_values)
|
||||
keys = [c.body.key for c in return_values]
|
||||
return "foo" in keys and "bar" in keys
|
||||
|
||||
def eval(self, context, return_values):
|
||||
super().eval(context, return_values)
|
||||
ret = get_ret_val(context.sheerka, context.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||
ret.parents = return_values
|
||||
return ret
|
||||
|
||||
|
||||
class EvaluatorAllSuppressFooEntry(EvaluatorAllWithPriority):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("suppress", 100)
|
||||
|
||||
def matches(self, context, return_values):
|
||||
super().matches(context, return_values)
|
||||
return True
|
||||
|
||||
def eval(self, context, return_values):
|
||||
super().eval(context, return_values)
|
||||
foo = None
|
||||
for ret in return_values:
|
||||
if ret.body.name == "foo":
|
||||
foo = ret
|
||||
|
||||
if foo:
|
||||
return context.sheerka.ret(self.name, False, Concept("does not matter"), parents=[foo])
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
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():
|
||||
"""
|
||||
No evaluator
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = []
|
||||
|
||||
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 = [EvaluatorOneModifyFoo]
|
||||
|
||||
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 = [
|
||||
EvaluatorAllWithPriority10,
|
||||
EvaluatorOneWithPriority20,
|
||||
EvaluatorAllWithPriority15,
|
||||
EvaluatorOneWithPriority10,
|
||||
EvaluatorOneWithPriority15,
|
||||
EvaluatorAllWithPriority20, ]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_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] all_priority20 - matches - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority20 - eval - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority15 - matches - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority15 - eval - target=['foo', '__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] all_priority10 - matches - target=['foo', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_priority10 - eval - target=['foo', '__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_for_one_return():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo")), get_ret_val(sheerka, Concept("baz"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_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_that_predicate_is_checked_before_evaluation_for_all_return():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorAllReduceFooBar]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo")), get_ret_val(sheerka, Concept("bar"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
"__EVALUATION [0] all_reduce_foobar - matches - target=['foo', 'bar', '__EVALUATION']",
|
||||
"__EVALUATION [0] all_reduce_foobar - eval - target=['foo', 'bar', '__EVALUATION']",
|
||||
"__EVALUATION [1] all_reduce_foobar - matches - target=['__SUCCESS']"
|
||||
]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
"__EVALUATION [0] all_reduce_foobar - matches - target=['foo', '__EVALUATION']"
|
||||
]
|
||||
|
||||
|
||||
def test_evaluation_continue_until_no_more_modification():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo, EvaluatorOneModifyBar]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo")), get_ret_val(sheerka, Concept("baz"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_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'
|
||||
]
|
||||
|
||||
|
||||
def test_evaluation_steps_are_respected():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneWithPriority10, EvaluatorOnePreEvaluation]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.BEFORE_EVALUATION])
|
||||
|
||||
assert Out.debug_out == [
|
||||
'__BEFORE_EVALUATION [0] preEval - matches - target=foo',
|
||||
'__BEFORE_EVALUATION [0] preEval - eval - target=foo',
|
||||
'__BEFORE_EVALUATION [0] preEval - matches - target=__BEFORE_EVALUATION',
|
||||
'__BEFORE_EVALUATION [0] preEval - eval - target=__BEFORE_EVALUATION']
|
||||
|
||||
|
||||
def test_evaluation_multi_steps_are_respected():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneMultiSteps]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.BEFORE_EVALUATION, BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert Out.debug_out == [
|
||||
'__BEFORE_EVALUATION [0] multiStep - matches - target=foo',
|
||||
'__BEFORE_EVALUATION [0] multiStep - eval - target=foo',
|
||||
'__BEFORE_EVALUATION [0] multiStep - matches - target=__BEFORE_EVALUATION',
|
||||
'__BEFORE_EVALUATION [0] multiStep - eval - target=__BEFORE_EVALUATION',
|
||||
'__EVALUATION [0] multiStep - matches - target=foo',
|
||||
'__EVALUATION [0] multiStep - eval - target=foo',
|
||||
'__EVALUATION [0] multiStep - matches - target=__EVALUATION',
|
||||
'__EVALUATION [0] multiStep - eval - target=__EVALUATION'
|
||||
]
|
||||
|
||||
|
||||
def test_evaluators_can_be_pre_processed():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
|
||||
entries = [get_ret_val(sheerka, Concept("foo"))]
|
||||
|
||||
# disable evaluator
|
||||
context = get_context(sheerka)
|
||||
context.add_preprocess(EvaluatorOneModifyFoo().name, enabled=False) # disabled for this exec context
|
||||
Out.debug_out = []
|
||||
sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == []
|
||||
|
||||
# other contextes are not impacted
|
||||
Out.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
'__EVALUATION [0] modifyFoo - matches - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - eval - target=foo',
|
||||
'__EVALUATION [0] modifyFoo - matches - target=__EVALUATION',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=bar',
|
||||
'__EVALUATION [1] modifyFoo - matches - target=__EVALUATION'
|
||||
]
|
||||
@@ -1,380 +0,0 @@
|
||||
from core.builtin_concepts import ReturnValueConcept, UserInputConcept, BuiltinConcepts, ParserResultConcept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from parsers.BaseParser import BaseParser
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_sheerka():
|
||||
sheerka = Sheerka()
|
||||
sheerka.initialize("mem://")
|
||||
return sheerka
|
||||
|
||||
|
||||
def get_context(sheerka):
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_ret_val(text, who="who"):
|
||||
return ReturnValueConcept(who, True, UserInputConcept(text, "user_name"))
|
||||
|
||||
|
||||
class BaseTestParser(BaseParser):
|
||||
debug_out = []
|
||||
|
||||
def __init__(self, name, priority, status=None, parser_result=None):
|
||||
super().__init__(name, priority)
|
||||
self.status = status
|
||||
self.parser_result = parser_result
|
||||
|
||||
@staticmethod
|
||||
def _get_name(name):
|
||||
return name[8:] if name.startswith("parsers.") else name
|
||||
|
||||
@staticmethod
|
||||
def _get_source(text_):
|
||||
return text_ if isinstance(text_, str) else text_.body
|
||||
|
||||
def _out(self, name, priority, status, source):
|
||||
debug = f"name={name}"
|
||||
debug += f", priority={priority}"
|
||||
debug += f", status={status}"
|
||||
debug += f", source={source}"
|
||||
self.debug_out.append(debug)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
value = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body)
|
||||
parser_result = ParserResultConcept(parser=self, value=value)
|
||||
return ReturnValueConcept(self, self.status, self.parser_result or parser_result)
|
||||
|
||||
|
||||
class Enabled90FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled90False", 90, False)
|
||||
|
||||
|
||||
class Enabled80FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled80False", 80, False)
|
||||
|
||||
|
||||
class Enabled80MultipleFalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled80MultipleFalse", 80, False)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
value1 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_1"
|
||||
value2 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_2"
|
||||
return [
|
||||
ReturnValueConcept(self, self.status, ParserResultConcept(parser=self, value=value1)),
|
||||
ReturnValueConcept(self, self.status, ParserResultConcept(parser=self, value=value2)),
|
||||
]
|
||||
|
||||
|
||||
class Enabled80MultipleTrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled80MultipleTrue", 80)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
value1 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_1"
|
||||
value2 = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body) + "_2"
|
||||
return [
|
||||
ReturnValueConcept(self, True, ParserResultConcept(parser=self, value=value1)),
|
||||
ReturnValueConcept(self, False, ParserResultConcept(parser=self, value=value2)),
|
||||
]
|
||||
|
||||
|
||||
class Enabled70FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled70False", 70, False, "Not a ParserResult")
|
||||
|
||||
|
||||
class Enabled50TrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled50True", 50, True)
|
||||
|
||||
def parse(self, context, text):
|
||||
source = self._get_source(text)
|
||||
status = isinstance(text, ParserResultConcept) and source == "Enabled80False:Enabled90False:hello world"
|
||||
self._out(self._get_name(self.name), self.priority, status, source)
|
||||
|
||||
value = self._get_name(self.name) + ":" + (text if isinstance(text, str) else text.body)
|
||||
return_value = ParserResultConcept(parser=self, value=value)
|
||||
return ReturnValueConcept(self, status, return_value)
|
||||
|
||||
|
||||
class Enabled50bisTrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled50BisTrue", 50, True)
|
||||
|
||||
|
||||
class Enabled50FalseParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled50False", 50, False)
|
||||
|
||||
|
||||
class Enabled10TrueParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Enabled10True", 10, True)
|
||||
|
||||
|
||||
class DisabledParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("Disabled", 90, True)
|
||||
self.enabled = False
|
||||
|
||||
|
||||
class NoneParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("None", 90, True, None)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
return None
|
||||
|
||||
|
||||
class ListOfNoneParser(BaseTestParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("ListOfNone", 90, True, None)
|
||||
|
||||
def parse(self, context, text):
|
||||
self._out(self._get_name(self.name), self.priority, self.status, self._get_source(text))
|
||||
return [None, None]
|
||||
|
||||
|
||||
def test_disabled_parsers_are_not_executed():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled": Enabled10TrueParser,
|
||||
"Disabled": DisabledParser
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == ['name=Enabled10True, priority=10, status=True, source=hello world']
|
||||
|
||||
|
||||
def test_parser_are_executed_by_priority():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled90False, priority=90, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=True, source=Enabled80False:Enabled90False:hello world',
|
||||
]
|
||||
|
||||
|
||||
def test_parsing_stop_at_the_first_success():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50bisTrue": Enabled50bisTrueParser,
|
||||
"Enabled10True": Enabled10TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled50BisTrue, priority=50, status=True, source=hello world',
|
||||
]
|
||||
|
||||
|
||||
def test_parsing_stop_at_the_first_success_2():
|
||||
"""
|
||||
Same test than before, but Enabled50True takes more time to find a match
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
"Enabled10True": Enabled10TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled90False, priority=90, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=True, source=Enabled80False:Enabled90False:hello world',
|
||||
]
|
||||
|
||||
|
||||
def test_all_parsers_of_a_given_priority_are_executed():
|
||||
"""
|
||||
Make sure that all parsers with priority 50 are executed
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
"Enabled50bisTrue": Enabled50bisTrueParser,
|
||||
"Enabled50False": Enabled50FalseParser,
|
||||
"Enabled10True": Enabled10TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled90False, priority=90, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled80False, priority=80, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=True, source=Enabled80False:Enabled90False:hello world',
|
||||
'name=Enabled50BisTrue, priority=50, status=True, source=hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=Enabled90False:hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50False, priority=50, status=False, source=Enabled80False:Enabled90False:hello world',
|
||||
]
|
||||
|
||||
|
||||
def test_a_parser_has_access_to_the_output_of_its_predecessors():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled90False": Enabled90FalseParser,
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
|
||||
res = sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
res_as_tuple = [(str(r.who)[8:], r.status, r.body.body) for r in res]
|
||||
assert res_as_tuple == [
|
||||
('Enabled90False', False, 'Enabled90False:hello world'),
|
||||
('Enabled80False', False, 'Enabled80False:hello world'),
|
||||
('Enabled80False', False, 'Enabled80False:Enabled90False:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled90False:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled80False:hello world'),
|
||||
('Enabled50True', True, 'Enabled50True:Enabled80False:Enabled90False:hello world'),
|
||||
]
|
||||
|
||||
|
||||
def test_none_return_values_are_discarded():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"NoneParser": NoneParser,
|
||||
"ListOfNone": ListOfNoneParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
assert res == []
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=None, priority=90, status=True, source=hello world',
|
||||
'name=ListOfNone, priority=90, status=True, source=hello world'
|
||||
]
|
||||
|
||||
|
||||
def test_following_priorities_can_only_see_parser_result_return_values():
|
||||
"""
|
||||
Normally, lower priority parsers can see the result of the higher priority parsers
|
||||
This is true only if the higher priority parser return a ParserResultConcept
|
||||
:return:
|
||||
"""
|
||||
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80False": Enabled80FalseParser,
|
||||
"Enabled70False": Enabled70FalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80False, priority=80, status=False, source=hello world',
|
||||
'name=Enabled70False, priority=70, status=False, source=hello world',
|
||||
'name=Enabled70False, priority=70, status=False, source=Enabled80False:hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80False:hello world',
|
||||
]
|
||||
|
||||
|
||||
def test_i_can_manage_parser_with_multiple_results():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80MultipleFalse": Enabled80MultipleFalseParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80MultipleFalse, priority=80, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=hello world',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80MultipleFalse:hello world_1',
|
||||
'name=Enabled50True, priority=50, status=False, source=Enabled80MultipleFalse:hello world_2',
|
||||
]
|
||||
|
||||
res_as_tuple = [(str(r.who)[8:], r.status, r.body.body) for r in res]
|
||||
assert res_as_tuple == [
|
||||
('Enabled80MultipleFalse', False, 'Enabled80MultipleFalse:hello world_1'),
|
||||
('Enabled80MultipleFalse', False, 'Enabled80MultipleFalse:hello world_2'),
|
||||
('Enabled50True', False, 'Enabled50True:hello world'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled80MultipleFalse:hello world_1'),
|
||||
('Enabled50True', False, 'Enabled50True:Enabled80MultipleFalse:hello world_2'),
|
||||
]
|
||||
|
||||
|
||||
def test_i_can_manage_parser_with_multiple_results_and_a_sucess():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80MultipleTrue": Enabled80MultipleTrueParser,
|
||||
"Enabled50True": Enabled50TrueParser,
|
||||
}
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert BaseTestParser.debug_out == [
|
||||
'name=Enabled80MultipleTrue, priority=80, status=None, source=hello world',
|
||||
]
|
||||
|
||||
res_as_tuple = [(str(r.who)[8:], r.status, r.body.body) for r in res]
|
||||
assert res_as_tuple == [
|
||||
('Enabled80MultipleTrue', True, 'Enabled80MultipleTrue:hello world_1'),
|
||||
('Enabled80MultipleTrue', False, 'Enabled80MultipleTrue:hello world_2'),
|
||||
]
|
||||
@@ -1,696 +0,0 @@
|
||||
import os
|
||||
import shutil
|
||||
from os import path
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property, simplec
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
|
||||
from parsers.ConceptLexerParser import Sequence, StrMatch, OrderedChoice, Optional, ConceptExpression
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event
|
||||
|
||||
tests_root = path.abspath("../build/tests")
|
||||
root_folder = "init_folder"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def init_test():
|
||||
if path.exists(tests_root):
|
||||
shutil.rmtree(tests_root)
|
||||
|
||||
if not path.exists(tests_root):
|
||||
os.makedirs(tests_root)
|
||||
current_pwd = os.getcwd()
|
||||
os.chdir(tests_root)
|
||||
|
||||
yield None
|
||||
|
||||
os.chdir(current_pwd)
|
||||
|
||||
|
||||
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=skip_builtins_in_db)
|
||||
sheerka.initialize(root)
|
||||
|
||||
return sheerka
|
||||
|
||||
|
||||
def get_context(sheerka):
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def get_default_concept():
|
||||
concept = Concept(
|
||||
name="a + b",
|
||||
where="isinstance(a, int) and isinstance(b, int)",
|
||||
pre="isinstance(a, int) and isinstance(b, int)",
|
||||
post="isinstance(res, int)",
|
||||
body="def func(x,y):\n return x+y\nfunc(a,b)",
|
||||
desc="specific description")
|
||||
concept.def_prop("a", "value1")
|
||||
concept.def_prop("b", "value2")
|
||||
|
||||
return concept
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("1 + 1", 2),
|
||||
("sheerka.test()", 'I have access to Sheerka !')
|
||||
])
|
||||
def test_i_can_eval_python_expressions_with_no_variable(text, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == expected
|
||||
|
||||
|
||||
def test_i_can_eval_concept_with_python_body():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept(name="one", body="1")
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == simplec("one", 1) # by default, the concept is returned
|
||||
|
||||
|
||||
def test_i_can_eval_concept_with_concept_body():
|
||||
sheerka = get_sheerka()
|
||||
concept_one = Concept(name="one")
|
||||
concept_un = Concept(name="un", body="one")
|
||||
sheerka.add_in_cache(concept_one)
|
||||
sheerka.add_in_cache(concept_un)
|
||||
|
||||
res = sheerka.evaluate_user_input("un")
|
||||
return_value = res[0].value
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert return_value == simplec("un", simplec("one", None))
|
||||
|
||||
|
||||
def test_i_can_eval_concept_with_no_body():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept(name="one")
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == concept
|
||||
assert id(res[0].value) != id(concept)
|
||||
|
||||
|
||||
def test_is_unique_property_is_used_when_evaluating():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept(name="one", is_unique=True)
|
||||
sheerka.add_in_cache(concept)
|
||||
|
||||
text = "one"
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value == concept
|
||||
assert id(res[0].value) == id(concept)
|
||||
|
||||
|
||||
def test_i_can_eval_def_concept_request():
|
||||
text = """
|
||||
def concept a + b
|
||||
where isinstance(a, int) and isinstance(b, int)
|
||||
pre isinstance(a, int) and isinstance(b, int)
|
||||
post isinstance(res, int)
|
||||
as:
|
||||
def func(x,y):
|
||||
return x+y
|
||||
func(a,b)
|
||||
"""
|
||||
|
||||
expected = get_default_concept()
|
||||
expected.metadata.id = "1001"
|
||||
expected.metadata.desc = None
|
||||
expected.metadata.props = [("a", None), ("b", None)]
|
||||
expected.init_key()
|
||||
|
||||
sheerka = get_sheerka()
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
concept_saved = res[0].value.body
|
||||
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||
|
||||
assert concept_saved.key in sheerka.cache_by_key
|
||||
assert concept_saved.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_digest()))
|
||||
|
||||
|
||||
def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept():
|
||||
"""
|
||||
In this test, we test that the properties of 'concept a xx b' (which are 'a' and 'b')
|
||||
are correctly detected, thanks to the source code 'a plus b' in its body
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
|
||||
# concept 'a plus b' is known
|
||||
concept_a_plus_b = Concept(name="a plus b").def_prop("a").def_prop("b")
|
||||
sheerka.add_in_cache(concept_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").def_prop("a").def_prop("b").init_key()
|
||||
expected.metadata.id = "1001"
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
concept_saved = res[0].value.body
|
||||
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||
|
||||
assert concept_saved.key in sheerka.cache_by_key
|
||||
assert concept_saved.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_digest()))
|
||||
|
||||
|
||||
def test_i_cannot_eval_the_same_def_concept_twice():
|
||||
text = """
|
||||
def concept a + b
|
||||
where isinstance(a, int) and isinstance(b, int)
|
||||
pre isinstance(a, int) and isinstance(b, int)
|
||||
post isinstance(res, int)
|
||||
as:
|
||||
def func(x,y):
|
||||
return x+y
|
||||
func(a,b)
|
||||
"""
|
||||
|
||||
sheerka = get_sheerka()
|
||||
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)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"",
|
||||
" ",
|
||||
"\n",
|
||||
])
|
||||
def test_i_can_eval_a_empty_input(text):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NOP)
|
||||
|
||||
|
||||
def test_i_can_eval_concept_with_variable():
|
||||
sheerka = get_sheerka()
|
||||
concept_hello = Concept(name="hello a").def_prop("a")
|
||||
concept_foo = Concept(name="foo")
|
||||
sheerka.add_in_cache(concept_hello)
|
||||
sheerka.add_in_cache(concept_foo)
|
||||
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
return_value = res[0].value
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(return_value, concept_hello)
|
||||
assert return_value.props["a"].value == concept_foo
|
||||
|
||||
|
||||
def test_i_can_eval_concept_with_variable_and_python_as_body():
|
||||
sheerka = get_sheerka()
|
||||
hello_a = sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
|
||||
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, hello_a)
|
||||
assert res[0].value.body == "hello foo"
|
||||
assert res[0].value.metadata.is_evaluated
|
||||
assert res[0].value.props["a"].value == simplec("foo", "foo")
|
||||
assert res[0].value.props["a"].value.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_eval_duplicate_concepts_with_same_value():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.add_in_cache(Concept(name="hello foo", body="'hello foo'"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
|
||||
|
||||
res = sheerka.evaluate_user_input("hello foo")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value.body == "hello foo"
|
||||
assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME)
|
||||
|
||||
|
||||
def test_i_cannot_manage_duplicate_concepts_when_the_values_are_different():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.add_in_cache(Concept(name="hello foo", body="'hello foo'"))
|
||||
sheerka.add_in_cache(Concept(name="foo", body="'another value'"))
|
||||
|
||||
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)
|
||||
|
||||
concepts = res[0].value.body
|
||||
assert len(concepts) == 2
|
||||
sorted_values = sorted(concepts, key=lambda x: x.value.body)
|
||||
assert sorted_values[0].value.body == "hello another value"
|
||||
assert sorted_values[1].value.body == "hello foo"
|
||||
|
||||
|
||||
def test_i_can_manage_concepts_with_the_same_key_when_values_are_the_same():
|
||||
sheerka = get_sheerka()
|
||||
context = get_context(sheerka)
|
||||
|
||||
sheerka.create_new_concept(context, Concept(name="hello a", body="'hello ' + a").def_prop("a"))
|
||||
sheerka.create_new_concept(context, Concept(name="hello b", body="'hello ' + b").def_prop("b"))
|
||||
|
||||
res = sheerka.evaluate_user_input("hello 'foo'")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].value.body == "hello foo" # I don't know yet the one to choose
|
||||
assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME)
|
||||
|
||||
|
||||
def test_i_can_create_concepts_with_python_code_as_body():
|
||||
sheerka = get_sheerka()
|
||||
context = get_context(sheerka)
|
||||
|
||||
sheerka.create_new_concept(context, Concept(name="concepts", body="sheerka.concepts()"))
|
||||
res = sheerka.evaluate_user_input("concepts")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert isinstance(res[0].value.body, list)
|
||||
|
||||
|
||||
def test_i_can_create_concept_with_bnf_definition():
|
||||
sheerka = get_sheerka(False, False)
|
||||
a = Concept("a")
|
||||
sheerka.add_in_cache(a)
|
||||
sheerka.concepts_definition_cache = {a: OrderedChoice("one", "two")}
|
||||
|
||||
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)
|
||||
|
||||
saved_concept = sheerka.sdp.get_safe(sheerka.CONCEPTS_ENTRY, "plus")
|
||||
assert saved_concept.key == "plus"
|
||||
assert saved_concept.metadata.definition == "a ('plus' plus)?"
|
||||
assert "a" in saved_concept.props
|
||||
assert "plus" in saved_concept.props
|
||||
|
||||
saved_definitions = sheerka.sdp.get_safe(sheerka.CONCEPTS_DEFINITIONS_ENTRY)
|
||||
expected_bnf = Sequence(
|
||||
a, Optional(Sequence(StrMatch("plus"), ConceptExpression("plus", rule_name="plus"))))
|
||||
assert saved_definitions[saved_concept] == expected_bnf
|
||||
|
||||
new_concept = res[0].value.body
|
||||
assert new_concept.metadata.name == "plus"
|
||||
assert new_concept.metadata.definition == "a ('plus' plus)?"
|
||||
assert new_concept.bnf == expected_bnf
|
||||
assert "a" in new_concept.props
|
||||
assert "plus" in new_concept.props
|
||||
|
||||
|
||||
def test_i_can_eval_bnf_definitions():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body
|
||||
|
||||
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.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.evaluate_user_input("one three")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
return_value = res[0].value
|
||||
|
||||
assert sheerka.isinstance(return_value, concept_b)
|
||||
assert return_value.body == "one three"
|
||||
assert return_value.metadata.is_evaluated
|
||||
|
||||
assert return_value.props["a"] == Property("a", sheerka.new(concept_a.key, body="one").init_key())
|
||||
assert return_value.props["a"].value.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_eval_bnf_definitions_from_separate_instances():
|
||||
"""
|
||||
Same test then before,
|
||||
but make sure that the BNF are correctly persisted and loaded
|
||||
"""
|
||||
sheerka = get_sheerka(False)
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' 'two'")[0].body.body
|
||||
|
||||
res = get_sheerka(False).evaluate_user_input("one two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
# add another bnf definition
|
||||
concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body
|
||||
|
||||
res = get_sheerka(False).evaluate_user_input("one two") # previous one still works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
res = get_sheerka(False).evaluate_user_input("one two three") # new one works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_b)
|
||||
assert res[0].value.body == "one two three"
|
||||
assert res[0].value.props["a"] == Property("a", sheerka.new(concept_a.key, body="one two").init_key())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("desc, definitions", [
|
||||
("Simple form", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit"
|
||||
]),
|
||||
("When twenty is a concept", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenty as 20",
|
||||
"def concept twenties from bnf twenty (one|two)=unit as twenty + unit"
|
||||
]),
|
||||
("When digit is a concept", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenty as 20",
|
||||
"def concept digit from bnf one|two",
|
||||
"def concept twenties from bnf twenty digit as twenty + digit"
|
||||
]),
|
||||
("When using isa and concept twenty", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"two isa number",
|
||||
"def concept twenties from bnf 'twenty' number as 20 + number"
|
||||
]),
|
||||
("When using isa and concept twenty", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenty as 20",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"two isa number",
|
||||
"def concept twenties from bnf twenty number as 20 + number"
|
||||
]),
|
||||
])
|
||||
def test_i_can_mix_concept_with_python_to_define_numbers(desc, definitions):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
for definition in definitions:
|
||||
sheerka.evaluate_user_input(definition)
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, "twenties")
|
||||
assert res[0].body.body == 21
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + twenty two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 43
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + 1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 23
|
||||
|
||||
|
||||
def test_i_can_mix_bnf_and_isa():
|
||||
"""
|
||||
if 'one' isa 'number, twenty number should be recognized
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("def concept two as 2")
|
||||
sheerka.evaluate_user_input("def concept number")
|
||||
sheerka.evaluate_user_input("one isa number")
|
||||
sheerka.evaluate_user_input("two isa number")
|
||||
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' number as 20 + number")
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == simplec("twenties", 21)
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + twenty two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 43
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + 1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 23
|
||||
|
||||
|
||||
def test_i_can_mix_concept_of_concept():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
definitions = [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit",
|
||||
"def concept a plus b as a + b"
|
||||
]
|
||||
|
||||
for definition in definitions:
|
||||
sheerka.evaluate_user_input(definition)
|
||||
|
||||
res = sheerka.evaluate_user_input("1 plus 2")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("1 plus one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 2
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + 1 plus 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("1 plus twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("one plus 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 2
|
||||
|
||||
res = sheerka.evaluate_user_input("one plus two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("one plus twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one plus 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one plus one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one plus twenty two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body == 43
|
||||
|
||||
|
||||
# def test_i_can_evaluate_concept_of_concept_when_multiple_choices():
|
||||
# sheerka = get_sheerka()
|
||||
#
|
||||
# definitions = [
|
||||
# "def concept little a where a",
|
||||
# "def concept blue a where a",
|
||||
# "def concept little blue a where a",
|
||||
# "def concept house"
|
||||
# ]
|
||||
#
|
||||
# for definition in definitions:
|
||||
# sheerka.evaluate_user_input(definition)
|
||||
#
|
||||
# ### CAUTION ####
|
||||
# # this test cannot work !!
|
||||
# # it is just to hint the result that I would like to achieve
|
||||
#
|
||||
# res = sheerka.evaluate_user_input("little blue house")
|
||||
# assert len(res) == 2
|
||||
# assert res[0].status
|
||||
# assert res[0].body == "little(blue(house))"
|
||||
#
|
||||
# assert res[1].status
|
||||
# assert res[1].body == "little blue(house)"
|
||||
|
||||
|
||||
def test_i_can_say_that_a_concept_isa_another_concept():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept foo")
|
||||
sheerka.evaluate_user_input("def concept bar")
|
||||
|
||||
res = sheerka.evaluate_user_input("foo isa bar")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
|
||||
def test_eval_does_not_break_valid_result():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("def concept two as 2")
|
||||
|
||||
res = sheerka.evaluate_user_input("one + two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 3
|
||||
|
||||
res = sheerka.evaluate_user_input("eval one + two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"'hello",
|
||||
'"foo" + "string',
|
||||
"c::",
|
||||
"c:foo\nbar:",
|
||||
"c:foo",
|
||||
"def concept 'name",
|
||||
"def concept name from bnf 'name"
|
||||
])
|
||||
def test_i_can_manage_tokenizer_error(text):
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept("foo"))
|
||||
|
||||
res = sheerka.evaluate_user_input(text)
|
||||
|
||||
assert len(res) > 1
|
||||
for r in [r for r in res if r.who.startswith("parsers.")]:
|
||||
assert not r.status
|
||||
|
||||
|
||||
def test_i_can_recognize_concept_from_string():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept("one", body="1"))
|
||||
|
||||
res = sheerka.evaluate_user_input("'one'")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == "one"
|
||||
|
||||
res = sheerka.evaluate_user_input("eval 'one'")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == "one"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression", [
|
||||
"def concept twenties from bnf 'twenty' (one | two)=unit as 20 + unit",
|
||||
"def concept twenties from bnf 'twenty' (one | two)=unit as twenty + unit",
|
||||
"def concept twenties from bnf twenty (one | two)=unit as 20 + unit",
|
||||
"def concept twenties from bnf twenty (one | two)=unit as twenty + unit",
|
||||
])
|
||||
def test_i_can_evaluate_bnf_concepts(expression):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("def concept two as 2")
|
||||
sheerka.evaluate_user_input("def concept twenty as 20")
|
||||
sheerka.evaluate_user_input(expression)
|
||||
res = sheerka.evaluate_user_input("eval twenty one")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 21
|
||||
@@ -1,336 +0,0 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts
|
||||
from core.sheerka import Sheerka, ExecutionContext, ExecutionContextIdManager
|
||||
from core.sheerka_transform import SheerkaTransform, OBJ_TYPE_KEY, SheerkaTransformType, OBJ_ID_KEY
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def get_sheerka():
|
||||
sheerka = Sheerka()
|
||||
sheerka.initialize("mem://")
|
||||
return sheerka
|
||||
|
||||
|
||||
def get_context(sheerka):
|
||||
return ExecutionContext("test", Event(), sheerka)
|
||||
|
||||
|
||||
def test_i_can_transform_an_unknown_concept():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
foo = Concept("foo", body="body")
|
||||
concept_with_sub = Concept("concept_with_sub", body=foo)
|
||||
|
||||
concept = Concept(
|
||||
name="concept_name",
|
||||
is_builtin=True,
|
||||
is_unique=True,
|
||||
key="concept_key",
|
||||
body=concept_with_sub,
|
||||
where=[foo, 1, "1", True, 1.0],
|
||||
pre=foo,
|
||||
post=None, # will not appear
|
||||
definition="it is a definition",
|
||||
definition_type="def type",
|
||||
desc="this this the desc"
|
||||
).def_prop("a", "10").def_prop("b", "foo").def_prop("c", "concept_with_sub")
|
||||
|
||||
# add values and props
|
||||
concept.values[ConceptParts.BODY] = Concept().update_from(concept_with_sub).auto_init()
|
||||
concept.values[ConceptParts.WHERE] = [foo, 1, "1", True, 1.0]
|
||||
concept.values[ConceptParts.PRE] = Concept().update_from(foo).auto_init()
|
||||
concept.values[ConceptParts.POST] = "a value for POST"
|
||||
concept.set_prop("a", 10).set_prop("b", foo).set_prop("c", concept_with_sub)
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(concept)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
'meta.name': 'concept_name',
|
||||
'meta.key': 'concept_key',
|
||||
'meta.is_builtin': True,
|
||||
'meta.is_unique': True,
|
||||
'meta.definition': 'it is a definition',
|
||||
'meta.definition_type': 'def type',
|
||||
'meta.desc': 'this this the desc',
|
||||
'meta.where': [{OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 1,
|
||||
'meta.body': 'body',
|
||||
'meta.name': 'foo'}, 1, '1', True, 1.0],
|
||||
'meta.pre': {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1},
|
||||
'meta.body': {
|
||||
'__type__': SheerkaTransformType.Concept,
|
||||
'__id__': 2,
|
||||
'meta.name': 'concept_with_sub',
|
||||
'meta.body': {
|
||||
'__type__': SheerkaTransformType.Reference,
|
||||
'__id__': 1}},
|
||||
'meta.props': [['a', '10'], ['b', 'foo'], ['c', 'concept_with_sub']],
|
||||
'pre': {'__type__': SheerkaTransformType.Concept,
|
||||
'__id__': 4,
|
||||
'meta.body': 'body',
|
||||
'meta.name': 'foo',
|
||||
'body': 'body'},
|
||||
'post': "a value for POST",
|
||||
'body': {'__type__': SheerkaTransformType.Concept,
|
||||
'__id__': 3,
|
||||
'meta.body': {'__id__': 1, '__type__': SheerkaTransformType.Reference},
|
||||
'meta.name': 'concept_with_sub',
|
||||
'body': {'__id__': 1, '__type__': SheerkaTransformType.Reference}},
|
||||
'where': [{OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}, 1, '1', True, 1.0],
|
||||
'props': [('a', 10),
|
||||
('b', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}),
|
||||
('c', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 2})],
|
||||
}
|
||||
|
||||
|
||||
def test_i_can_transform_unknown_concept_with_almost_same_value():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept("foo")
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(concept)
|
||||
|
||||
assert to_dict == {OBJ_TYPE_KEY: SheerkaTransformType.Concept, OBJ_ID_KEY: 0, 'meta.name': 'foo'}
|
||||
|
||||
|
||||
def test_i_can_transform_known_concept_when_the_values_are_the_same():
|
||||
"""
|
||||
Values are the same means that we are serializing a concept which has kept all its default values
|
||||
There is not diff between the concept to serialize and the one which was registered with create_new_concept()
|
||||
We serialize only the id of the concept
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept(
|
||||
name="concept_name",
|
||||
is_builtin=True,
|
||||
is_unique=False,
|
||||
key="concept_key",
|
||||
body="body definition",
|
||||
where="where definition",
|
||||
pre="pre definition",
|
||||
post="post definition",
|
||||
definition="it is a definition",
|
||||
definition_type="def type",
|
||||
desc="this this the desc"
|
||||
).def_prop("a").def_prop("b")
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
new_concept = sheerka.new(concept.key)
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(new_concept)
|
||||
|
||||
assert to_dict == {OBJ_TYPE_KEY: SheerkaTransformType.Concept, OBJ_ID_KEY: 0, "id": "1001"}
|
||||
|
||||
|
||||
def test_i_can_transform_known_concept_when_the_values_are_different():
|
||||
"""
|
||||
Values are the different means the concept was modified.
|
||||
It's different from the one which was registered with create_new_concept()
|
||||
We serialize only the differences
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept(
|
||||
name="concept_name",
|
||||
is_builtin=True,
|
||||
is_unique=False,
|
||||
key="concept_key",
|
||||
body="body definition",
|
||||
where="where definition",
|
||||
pre="pre definition",
|
||||
post="post definition",
|
||||
definition="it is a definition",
|
||||
definition_type="def type",
|
||||
desc="this this the desc"
|
||||
).def_prop("a").def_prop("b")
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
new_concept = sheerka.new(concept.key, body="another", a=10, pre="another pre")
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(new_concept)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
"id": "1001",
|
||||
'pre': 'another pre',
|
||||
"body": "another",
|
||||
'props': [('a', 10)]
|
||||
}
|
||||
|
||||
|
||||
def test_i_can_transform_concept_with_circular_reference():
|
||||
sheerka = get_sheerka()
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar", body=foo)
|
||||
foo.metadata.body = bar
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(foo)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
'meta.name': 'foo',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 1,
|
||||
'meta.name': 'bar',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
|
||||
OBJ_ID_KEY: 0},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_i_can_transform_concept_with_circular_reference_2():
|
||||
sheerka = get_sheerka()
|
||||
foo = Concept("foo")
|
||||
bar = Concept("foo", body=foo)
|
||||
foo.metadata.body = bar
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(foo)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 0,
|
||||
'meta.name': 'foo',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: 1,
|
||||
'meta.name': 'foo',
|
||||
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
|
||||
OBJ_ID_KEY: 0},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_i_can_transform_the_unknown_concept():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
unknown = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(unknown)
|
||||
|
||||
assert len(to_dict) == 3
|
||||
assert to_dict[OBJ_TYPE_KEY] == SheerkaTransformType.Concept
|
||||
assert to_dict[OBJ_ID_KEY] == 0
|
||||
assert "id" in to_dict
|
||||
|
||||
|
||||
def test_i_can_transform_simple_execution_context():
|
||||
sheerka = get_sheerka()
|
||||
ExecutionContextIdManager.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(context)
|
||||
|
||||
assert to_dict == {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.ExecutionContext,
|
||||
OBJ_ID_KEY: 0,
|
||||
'_parent': None,
|
||||
'_id': 0,
|
||||
'_tab': '',
|
||||
'_bag': {},
|
||||
'_start': 0,
|
||||
'_stop': 0,
|
||||
'who': 'requester',
|
||||
'event': {OBJ_TYPE_KEY: SheerkaTransformType.Event, OBJ_ID_KEY: 1, 'digest': 'xxx'},
|
||||
'desc': 'this is the desc',
|
||||
'children': [],
|
||||
'preprocess': None,
|
||||
'inputs': {},
|
||||
'values': {},
|
||||
'obj': None,
|
||||
'concepts': {}
|
||||
}
|
||||
|
||||
|
||||
def test_i_can_transform_list():
|
||||
sheerka = get_sheerka()
|
||||
ExecutionContextIdManager.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict([context])
|
||||
|
||||
assert len(to_dict) == 1
|
||||
assert isinstance(to_dict, list)
|
||||
assert to_dict[0]["who"] == "requester"
|
||||
assert to_dict[0]["desc"] == "this is the desc"
|
||||
|
||||
|
||||
def test_i_can_transform_set():
|
||||
sheerka = get_sheerka()
|
||||
ExecutionContextIdManager.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict({context})
|
||||
|
||||
assert len(to_dict) == 1
|
||||
assert isinstance(to_dict, list)
|
||||
assert to_dict[0]["who"] == "requester"
|
||||
assert to_dict[0]["desc"] == "this is the desc"
|
||||
|
||||
|
||||
def test_i_can_transform_dict():
|
||||
sheerka = get_sheerka()
|
||||
ExecutionContextIdManager.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
known_concept = Concept("foo", body="foo").set_prop("a", "value_of_a").init_key()
|
||||
sheerka.create_new_concept(get_context(sheerka), known_concept)
|
||||
unknown_concept = Concept("bar")
|
||||
known = sheerka.new("foo")
|
||||
|
||||
bag = {
|
||||
"context": context,
|
||||
"known_concept": known_concept,
|
||||
"unknown_concept": unknown_concept,
|
||||
"True": True,
|
||||
"Number": 1.1,
|
||||
"String": "a string value",
|
||||
"None": None,
|
||||
unknown_concept: "hello",
|
||||
known: "world"
|
||||
}
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(bag)
|
||||
|
||||
assert isinstance(to_dict, dict)
|
||||
assert to_dict['Number'] == 1.1
|
||||
assert to_dict['String'] == 'a string value'
|
||||
assert to_dict['True']
|
||||
assert to_dict['None'] is None
|
||||
assert to_dict["context"][OBJ_TYPE_KEY] == SheerkaTransformType.ExecutionContext
|
||||
assert to_dict["known_concept"][OBJ_TYPE_KEY] == SheerkaTransformType.Concept
|
||||
assert to_dict["known_concept"]["id"] == '1001'
|
||||
assert to_dict["unknown_concept"][OBJ_TYPE_KEY] == SheerkaTransformType.Concept
|
||||
assert to_dict["(None)bar"] == "hello"
|
||||
assert to_dict["(1001)foo"] == "world"
|
||||
|
||||
|
||||
def test_i_can_transform_when_circular_references():
|
||||
sheerka = get_sheerka()
|
||||
ExecutionContextIdManager.ids = {}
|
||||
context = ExecutionContext("requester", Event(), sheerka, 'this is the desc')
|
||||
context.push("another requester", "another desc")
|
||||
|
||||
st = SheerkaTransform(sheerka)
|
||||
to_dict = st.to_dict(context)
|
||||
|
||||
assert isinstance(to_dict, dict)
|
||||
assert to_dict[OBJ_TYPE_KEY] == SheerkaTransformType.ExecutionContext
|
||||
assert len(to_dict["children"]) == 1
|
||||
assert to_dict["children"][0][OBJ_TYPE_KEY] == SheerkaTransformType.ExecutionContext
|
||||
assert to_dict["children"][0]['_parent'][OBJ_TYPE_KEY] == SheerkaTransformType.Reference
|
||||
assert to_dict["children"][0]['_parent'][OBJ_ID_KEY] == 0
|
||||
assert to_dict["children"][0]['event'][OBJ_TYPE_KEY] == SheerkaTransformType.Reference
|
||||
assert to_dict["children"][0]['event'][OBJ_ID_KEY] == 1
|
||||
Reference in New Issue
Block a user