Refactored Caching, Refactored BnfNodeParser, Introduced Sphinx

This commit is contained in:
2020-05-12 17:21:10 +02:00
parent 7d3a490bc5
commit 6e343ba996
110 changed files with 13865 additions and 7540 deletions
+39 -10
View File
@@ -1,8 +1,9 @@
import ast
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import Concept, DEFINITION_TYPE_BNF
from core.concept import Concept, DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
from core.sheerka.ExecutionContext import ExecutionContext
from parsers.BnfNodeParser import StrMatch
from parsers.BnfParser import BnfParser
from sdp.sheerkaDataProvider import Event
@@ -28,8 +29,8 @@ class BaseTest:
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")
concept.def_var("a", "value1")
concept.def_var("b", "value2")
return concept
@@ -41,15 +42,17 @@ class BaseTest:
def init_concepts(self, *concepts, **kwargs):
sheerka = self.get_sheerka(**kwargs)
context = self.get_context(sheerka)
create_new = kwargs.get("create_new", False)
context_args = dict([(k, v) for k, v in kwargs.items() if k in ["sheerka", "eval_body", "eval_where"]])
context = self.get_context(sheerka, **context_args)
create_new = kwargs.get("create_new", None)
result = []
for c in concepts:
if isinstance(c, str):
c = Concept(c)
if c.metadata.definition:
if c.metadata.definition and c.metadata.definition_type != DEFINITION_TYPE_DEF:
bnf_parser = BnfParser()
res = bnf_parser.parse(context, c.metadata.definition)
if res.status:
@@ -57,8 +60,8 @@ class BaseTest:
c.metadata.definition_type = DEFINITION_TYPE_BNF
else:
raise Exception(f"Error in bnf definition '{c.metadata.definition}'", sheerka.get_error(res))
sheerka.create_new_concept(context, c)
elif create_new:
if create_new:
sheerka.create_new_concept(context, c)
else:
c.init_key()
@@ -79,8 +82,8 @@ class BaseTest:
"""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
if sheerka.has_key(obj.key):
sheerka.add_in_cache(obj)
return sheerka.ret(who, True, obj)
@staticmethod
@@ -93,3 +96,29 @@ class BaseTest:
source=source or concept.name,
value=concept,
try_parsed=concept))
@staticmethod
def create_concept_lite(sheerka, name, variables=None, bnf=None):
concept = Concept(name) if isinstance(name, str) else name
if variables:
for v in variables:
concept.def_var(v)
if bnf:
concept.bnf = bnf
concept.metadata.definition_type = DEFINITION_TYPE_BNF
concept.init_key()
sheerka.set_id_if_needed(concept, False)
sheerka.add_in_cache(concept)
return concept
@staticmethod
def bnf_concept(concept, expression=None):
if isinstance(concept, Concept):
name = concept.name
else:
name = concept
concept = Concept(concept)
concept.bnf = expression or StrMatch(name)
concept.metadata.definition_type = DEFINITION_TYPE_BNF
return concept
+10 -6
View File
@@ -4,11 +4,11 @@ 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"
@@ -26,11 +26,15 @@ class TestUsingFileBasedSheerka(BaseTest):
os.chdir(current_pwd)
def get_sheerka(self, **kwargs):
use_dict = kwargs.get("use_dict", True)
skip_builtins_in_db = kwargs.get("skip_builtins_in_db", True)
def get_sheerka(self, **kwargs):
# use dictionary based io instead of file
# If you do so, information between two different instances of sheerka
# won't be shared
use_dict = kwargs.get("use_dict", False)
root = "mem://" if use_dict else self.root_folder
sheerka = Sheerka(skip_builtins_in_db=skip_builtins_in_db)
sheerka.initialize(root)
sheerka = Sheerka()
sheerka.initialize(root, save_execution_context=False)
return sheerka
+12 -12
View File
@@ -1,20 +1,21 @@
from core.sheerka.Sheerka import Sheerka
from tests.BaseTest import BaseTest
class TestUsingMemoryBasedSheerka(BaseTest):
singleton_instance = None
builtin_concepts = {}
dump = None
@staticmethod
def _inner_get_sheerka(skip_builtins_in_db):
sheerka = Sheerka(skip_builtins_in_db=skip_builtins_in_db)
sheerka.initialize("mem://")
def _inner_get_sheerka(cache_only):
sheerka = Sheerka(cache_only=cache_only)
sheerka.initialize("mem://", save_execution_context=False)
return sheerka
def get_sheerka(self, **kwargs):
skip_builtins_in_db = kwargs.get("skip_builtins_in_db", True)
use_singleton = kwargs.get("singleton", False)
cache_only = kwargs.get("cache_only", True)
use_singleton = kwargs.get("singleton", True)
sheerka = kwargs.get("sheerka", None)
if sheerka:
@@ -23,14 +24,13 @@ class TestUsingMemoryBasedSheerka(BaseTest):
if use_singleton:
singleton_instance = TestUsingMemoryBasedSheerka.singleton_instance
if singleton_instance:
singleton_instance.reset()
singleton_instance.cache_by_key.update(TestUsingMemoryBasedSheerka.builtin_concepts) # quicker ?
# singleton_instance.cache_by_key = TestUsingMemoryBasedSheerka.builtin_concepts
singleton_instance.reset(cache_only)
singleton_instance.cache_manager.init_from(TestUsingMemoryBasedSheerka.dump)
return singleton_instance
else:
new_instance = self._inner_get_sheerka(skip_builtins_in_db)
TestUsingMemoryBasedSheerka.builtin_concepts.update(new_instance.cache_by_key)
new_instance = self._inner_get_sheerka(cache_only)
TestUsingMemoryBasedSheerka.dump = new_instance.cache_manager.dump()
TestUsingMemoryBasedSheerka.singleton_instance = new_instance
return TestUsingMemoryBasedSheerka.singleton_instance
return self._inner_get_sheerka(skip_builtins_in_db)
return self._inner_get_sheerka(cache_only)
View File
+534
View File
@@ -0,0 +1,534 @@
import pytest
from cache.Cache import Cache
from cache.CacheManager import CacheManager
from cache.DictionaryCache import DictionaryCache
from cache.IncCache import IncCache
from cache.ListCache import ListCache
from cache.ListIfNeededCache import ListIfNeededCache
from cache.SetCache import SetCache
from core.concept import Concept
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestCache(TestUsingMemoryBasedSheerka):
def test_i_can_get_an_retrieve_value_from_cache(self):
cache = Cache()
cache.put("key", "value")
assert cache.get("key") == "value"
assert len(cache) == 1
cache.put("key", "another value") # another value in the cache replace the previous one
assert cache.get("key") == "another value"
assert len(cache) == 1
cache.put("key2", "value2") # another key
assert cache.get("key2") == "value2"
assert len(cache) == 2
assert cache.copy() == {"key": "another value", "key2": "value2"}
def test_i_can_evict(self):
maxsize = 5
cache = Cache(max_size=5)
for key in range(maxsize):
cache.put(key, key)
assert len(cache) == maxsize
assert cache.has(0)
for key in range(maxsize, maxsize * 2):
cache.put(key, key)
assert len(cache) == maxsize
assert not cache.has(key - maxsize)
def test_i_can_get_default_value_from_simple_cache(self):
cache = Cache()
assert cache.get("key") is None
cache = Cache(default=10)
assert cache.get("key") == 10
assert "key" not in cache # default value are not put in cache
cache = Cache(default=lambda key: key + "_not_found")
assert cache.get("key") == "key_not_found"
assert "key" in cache # default callable are put in cache
def test_i_can_put_and_retrieve_value_from_list_cache(self):
cache = ListCache()
cache.put("key", "value")
assert cache.get("key") == ["value"]
assert len(cache) == 1
cache.put("key", "value2") # we can append to this list
assert cache.get("key") == ["value", "value2"]
assert len(cache) == 2
cache.put("key2", "value")
assert cache.get("key2") == ["value"]
assert len(cache) == 3
# duplicates are allowed
cache.put("key", "value")
assert cache.get("key") == ["value", "value2", "value"]
assert len(cache) == 4
assert cache.copy() == {'key': ['value', 'value2', 'value'], 'key2': ['value']}
def test_i_can_put_and_retrieve_value_from_list_if_needed_cache(self):
cache = ListIfNeededCache()
cache.put("key", "value")
assert cache.get("key") == "value"
# second time with the same key creates a list
cache.put("key", "value2")
assert cache.get("key") == ["value", "value2"]
assert len(cache) == 2
# third time, we now have a list
cache.put("key", "value3")
assert cache.get("key") == ["value", "value2", "value3"]
assert len(cache) == 3
# other keys are not affected
cache.put("key2", "value")
assert cache.get("key2") == "value"
assert len(cache) == 4
# duplicates are allowed
cache.put("key", "value")
assert cache.get("key") == ["value", "value2", "value3", "value"]
assert len(cache) == 5
def test_i_can_put_and_retrieve_values_from_set_cache(self):
cache = SetCache()
cache.put("key", "value")
assert cache.get("key") == {"value"}
assert len(cache) == 1
# we can add to this set
cache.put("key", "value2")
assert cache.get("key") == {"value", "value2"}
assert len(cache) == 2
# other keys are not affected
cache.put("key2", "value")
assert cache.get("key2") == {"value"}
assert len(cache) == 3
# duplicates are removed
cache.put("key", "value")
assert cache.get("key") == {"value", "value2"}
assert len(cache) == 3
assert cache.copy() == {'key': {'value', 'value2'}, 'key2': {'value'}}
def test_i_can_put_and_retrieve_value_from_dictionary_cache(self):
cache = DictionaryCache()
# # key must be None
# with pytest.raises(KeyError):
# cache.put("key", None)
#
# # value must be a dictionary
# with pytest.raises(ValueError):
# cache.put(True, "value")
entry = {"key": "value", "key2": ["value21", "value22"]}
cache.put(False, entry)
assert len(cache) == 3
assert id(cache._cache) == id(entry)
assert cache.get("key") == "value"
assert cache.get("key2") == ["value21", "value22"]
# I can append values
cache.put(True, {"key": "another_value", "key3": "value3"})
assert len(cache) == 4
assert cache.get("key") == "another_value"
assert cache.get("key2") == ["value21", "value22"]
assert cache.get("key3") == "value3"
# I can reset
entry = {"key": "value", "key2": ["value21", "value22"]}
cache.put(False, entry)
assert len(cache) == 3
assert id(cache._cache) == id(entry)
assert cache.get("key") == "value"
assert cache.get("key2") == ["value21", "value22"]
assert cache.copy() == {'key': 'value', 'key2': ['value21', 'value22']}
def test_i_can_put_and_retrieve_values_from_inc_cache(self):
cache = IncCache()
assert cache.get("key") == 1
assert cache.get("key") == 2
assert cache.get("key") == 3
assert cache.get("key2") == 1
assert cache.get("key2") == 2
cache.put("key", 100)
assert cache.get("key") == 101
assert cache.copy() == {'key': 101, 'key2': 2}
@pytest.mark.parametrize("key", [
None,
"something"
])
def test_keys_have_constraints_when_dictionary_cache(self, key):
cache = DictionaryCache()
with pytest.raises(KeyError):
cache.put(key, None)
@pytest.mark.parametrize("value", [
None,
"something"
])
def test_values_have_constraints_when_dictionary_cache(self, value):
cache = DictionaryCache()
with pytest.raises(ValueError):
cache.put(True, value)
def test_i_can_append_to_a_dictionary_cache_even_if_it_s_new(self):
cache = DictionaryCache()
entry = {"key": "value", "key2": ["value21", "value22"]}
cache.put(True, entry)
assert len(cache) == 3
assert id(cache._cache) != id(entry)
assert cache.get("key") == "value"
assert cache.get("key2") == ["value21", "value22"]
def test_i_can_update_from_simple_cache(self):
cache = Cache()
cache.put("key", "value")
cache.update("key", "value", "key", "new_value")
assert len(cache._cache) == 1
assert len(cache) == 1
assert cache.get("key") == "new_value"
cache.update("key", "new_value", "another_key", "another_value")
assert len(cache._cache) == 1
assert len(cache) == 1
assert cache.get("key") is None
assert cache.get("another_key") == "another_value"
with pytest.raises(KeyError):
cache.update("wrong key", "value", "key", "value")
def test_i_can_update_from_list_cache(self):
cache = ListCache()
cache.put("key", "value")
cache.put("key", "value2")
cache.put("key", "value")
cache.update("key", "value", "key", "another value")
assert len(cache._cache) == 1
assert len(cache) == 3
assert cache.get("key") == ["another value", "value2", "value"] # only the first one is affected
cache.update("key", "value2", "key2", "value2")
assert len(cache._cache) == 2
assert len(cache) == 3
assert cache.get("key") == ["another value", "value"]
assert cache.get("key2") == ["value2"]
cache.update("key2", "value2", "key3", "value2")
assert len(cache._cache) == 2
assert len(cache) == 3
assert cache.get("key") == ["another value", "value"]
assert cache.get("key3") == ["value2"]
assert cache.get("key2") is None
with pytest.raises(KeyError):
cache.update("wrong key", "value", "key", "value")
def test_i_can_update_from_list_if_needed_cache(self):
cache = ListIfNeededCache()
cache.put("key", "value")
cache.put("key", "value2")
cache.put("key", "value")
cache.update("key", "value", "key", "another value")
assert len(cache._cache) == 1
assert len(cache) == 3
assert cache.get("key") == ["another value", "value2", "value"] # only the first one is affected
cache.update("key", "value2", "key2", "value2")
assert len(cache._cache) == 2
assert len(cache) == 3
assert cache.get("key") == ["another value", "value"]
assert cache.get("key2") == "value2"
cache.update("key2", "value2", "key3", "value2")
assert len(cache._cache) == 2
assert len(cache) == 3
assert cache.get("key") == ["another value", "value"]
assert cache.get("key3") == "value2"
assert cache.get("key2") is None
with pytest.raises(KeyError):
cache.update("wrong key", "value", "key", "value")
def test_i_can_update_from_set_cache(self):
cache = SetCache()
cache.put("key", "value")
cache.put("key", "value2")
cache.update("key", "value", "key", "another value")
assert len(cache._cache) == 1
assert len(cache) == 2
assert cache.get("key") == {"another value", "value2"}
cache.update("key", "value2", "key2", "value2")
assert len(cache._cache) == 2
assert len(cache) == 2
assert cache.get("key") == {"another value"}
assert cache.get("key2") == {"value2"}
cache.update("key", "another value", "key3", "another value")
assert len(cache._cache) == 2
assert len(cache) == 2
assert cache.get("key") is None
assert cache.get("key2") == {"value2"}
assert cache.get("key3") == {"another value"}
with pytest.raises(KeyError):
cache.update("wrong key", "value", "key", "value")
@pytest.mark.parametrize("cache", [
Cache(), ListCache(), ListIfNeededCache(), SetCache(), IncCache()
])
def test_i_can_manage_cache_events(self, cache):
cache.put("key", "value")
assert cache.to_add == {"key"}
assert cache.to_remove == set()
cache.update("key", "value", "key", "another value")
assert cache.to_add == {"key"}
assert cache.to_remove == set()
cache.update("key", "another value", "key2", "value2")
assert cache.to_add == {"key2"}
assert cache.to_remove == {"key"}
cache.update("key2", "value2", "key", "value")
assert cache.to_add == {"key"}
assert cache.to_remove == {"key2"}
@pytest.mark.parametrize("cache", [
ListCache(), SetCache(), ListIfNeededCache()
])
def test_i_can_manage_list_and_set_cache_events(self, cache):
cache.put("key", "value")
cache.put("key", "value2")
assert cache.to_add == {"key"}
assert cache.to_remove == set()
cache.update("key", "value", "key", "another value")
assert cache.to_add == {"key"}
assert cache.to_remove == set()
cache.update("key", "value2", "key2", "value2")
assert cache.to_add == {"key", "key2"}
assert cache.to_remove == set()
cache.update("key", "another value", "key3", "another value")
assert cache.to_add == {"key2", "key3"}
assert cache.to_remove == {"key"}
@pytest.mark.parametrize("cache", [
Cache(), ListCache(), SetCache(), ListIfNeededCache(), IncCache()
])
def test_exists(self, cache):
assert not cache.exists("key")
cache.put("key", "value")
assert cache.exists("key")
def test_exists_in_dictionary_cache(self):
cache = DictionaryCache()
assert not cache.exists("key")
cache.put(True, {"key": "value"})
assert cache.exists("key")
def test_exists_extend(self):
cache = Cache(extend_exists=lambda k: True if k == "special_key" else False)
assert not cache.exists("key")
assert cache.exists("special_key")
def test_add_concept_fills_all_dependent_caches(self):
sheerka, context, one, two, two_2, three = self.init_concepts("one", "two", Concept("two"), "three")
cache_manager = CacheManager(None)
cache_manager.register_concept_cache("by_id", Cache(), lambda obj: obj.id, True)
cache_manager.register_concept_cache("by_name", ListCache(), lambda obj: obj.name, True)
cache_manager.register_concept_cache("by_name2", ListIfNeededCache(), lambda obj: obj.name, True)
cache_manager.add_concept(one)
cache_manager.add_concept(two)
cache_manager.add_concept(two_2)
cache_manager.add_concept(three)
assert len(cache_manager.caches) == 3
assert cache_manager.caches["by_id"].cache._cache == {
"1001": one,
"1002": two,
"1003": two_2,
"1004": three,
}
assert cache_manager.caches["by_name"].cache._cache == {
"one": [one],
"two": [two, two_2],
"three": [three]
}
assert cache_manager.caches["by_name2"].cache._cache == {
"one": one,
"two": [two, two_2],
"three": three
}
assert cache_manager.get("by_id", "1002") == two
assert cache_manager.get("by_name", "two") == [two, two_2]
assert cache_manager.get("by_name2", "two") == [two, two_2]
def test_default_for_dictionary_cache(self):
cache = DictionaryCache(default={"key": "value", "key2": "value2"})
assert cache.get("key") == "value"
assert "key2" in cache
assert len(cache) == 2
cache.clear()
assert cache.get("key3") is None
assert len(cache) == 2
assert "key" in cache
assert "key2" in cache
# default is not modified
cache._cache["key"] = "another value" # operation that is normally not possible
cache.clear()
assert cache.get("key") == "value"
def test_default_callable_for_dictionary_cache(self):
cache = DictionaryCache(default=lambda k: {"key": "value", "key2": "value2"})
assert cache.get("key") == "value"
assert "key2" in cache
assert len(cache) == 2
cache.clear()
assert cache.get("key3") is None
assert len(cache) == 2
assert "key" in cache
assert "key2" in cache
def test_dictionary_cache_cannot_be_null(self):
cache = DictionaryCache(default=lambda k: None)
assert cache.get("key") is None
assert cache._cache == {}
cache = DictionaryCache(default=None)
assert cache.get("key") is None
assert cache._cache == {}
@pytest.mark.parametrize("cache, default, new_value, expected", [
(ListCache(), lambda k: None, "value", ["value"]),
(ListCache(), lambda k: ["value"], "value", ["value", "value"]),
(ListIfNeededCache(), lambda k: None, "value", "value"),
(ListIfNeededCache(), lambda k: "value", "value1", ["value", "value1"]),
(ListIfNeededCache(), lambda k: ["value1", "value2"], "value1", ["value1", "value2", "value1"]),
(SetCache(), lambda k: None, "value", {"value"}),
(SetCache(), lambda k: {"value"}, "value", {"value"}),
(SetCache(), lambda k: {"value1"}, "value2", {"value1", "value2"}),
])
def test_default_is_called_before_put_to_keep_in_sync(self, cache, default, new_value, expected):
cache.configure(default=default)
cache.put("key", new_value)
assert cache.get("key") == expected
def test_default_is_called_before_updating_simple_cache(self):
cache = Cache(default=lambda k: None)
with pytest.raises(KeyError):
cache.update("old_key", "old_value", "new_key", "new_value")
cache = Cache(default=lambda k: "old_value")
cache.update("old_key", "old_value", "new_key", "new_value")
assert cache.get("new_key") == "new_value"
def test_default_is_called_before_updating_list_cache(self):
cache = ListCache(default=lambda k: None)
with pytest.raises(KeyError):
cache.update("old_key", "old_value", "new_key", "new_value")
cache = ListCache(default=lambda k: ["old_value", "other old value"])
cache.update("old_key", "old_value", "old_key", "new_value")
assert cache.get("old_key") == ["new_value", "other old value"]
cache = ListCache(default=lambda k: ["old_value", "other old value"] if k == "old_key" else None)
cache.update("old_key", "old_value", "new_key", "new_value")
assert cache.get("old_key") == ["other old value"]
assert cache.get("new_key") == ["new_value"]
cache = ListCache(default=lambda k: ["old_value", "other old value"] if k == "old_key" else ["other new"])
cache.update("old_key", "old_value", "new_key", "new_value")
assert cache.get("old_key") == ["other old value"]
assert cache.get("new_key") == ["other new", "new_value"]
def test_default_is_called_before_updating_list_if_needed_cache(self):
cache = ListIfNeededCache(default=lambda k: None)
with pytest.raises(KeyError):
cache.update("old_key", "old_value", "new_key", "new_value")
cache = ListIfNeededCache(default=lambda k: "old_value")
cache.update("old_key", "old_value", "old_key", "new_value")
assert cache.get("old_key") == "new_value"
cache = ListIfNeededCache(default=lambda k: ["old_value", "other old value"])
cache.update("old_key", "old_value", "old_key", "new_value")
assert cache.get("old_key") == ["new_value", "other old value"]
cache = ListIfNeededCache(default=lambda k: ["old_value", "other old value"] if k == "old_key" else None)
cache.update("old_key", "old_value", "new_key", "new_value")
assert cache.get("old_key") == ["other old value"]
assert cache.get("new_key") == "new_value"
def test_default_is_called_before_updating_set_cache(self):
cache = SetCache(default=lambda k: None)
with pytest.raises(KeyError):
cache.update("old_key", "old_value", "new_key", "new_value")
cache = SetCache(default=lambda k: {"old_value", "other old value"})
cache.update("old_key", "old_value", "old_key", "new_value")
assert cache.get("old_key") == {"new_value", "other old value"}
cache = SetCache(default=lambda k: {"old_value", "other old value"} if k == "old_key" else None)
cache.update("old_key", "old_value", "new_key", "new_value")
assert cache.get("old_key") == {"other old value"}
assert cache.get("new_key") == {"new_value"}
cache = SetCache(default=lambda k: {"old_value", "other old value"} if k == "old_key" else {"other new"})
cache.update("old_key", "old_value", "new_key", "new_value")
assert cache.get("old_key") == {"other old value"}
assert cache.get("new_key") == {"other new", "new_value"}
def test_i_can_delete_an_entry_from_cache(self):
cache = Cache()
cache.put("key", "value")
assert cache.get("key") == "value"
cache.delete("key")
assert cache.get("value") is None
assert cache.to_remove == {"key"}
+111
View File
@@ -0,0 +1,111 @@
from cache.Cache import Cache
from cache.CacheManager import CacheManager
from cache.DictionaryCache import DictionaryCache
from cache.ListCache import ListCache
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestCacheManager(TestUsingMemoryBasedSheerka):
def test_i_do_not_push_into_sdp_when_cache_only(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
cache_manager = CacheManager(True)
cache_manager.register_cache("test", Cache(), persist=True)
cache_manager.put("test", "key", "value")
cache_manager.commit(context)
assert not sheerka.sdp.exists("test", "key")
def test_i_do_not_get_value_from_sdp_when_cache_only_is_true(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
with sheerka.sdp.get_transaction(context.event) as transaction:
transaction.add("test", "key", "value")
cache = Cache(default=lambda k: sheerka.sdp.get("test", k))
cache_manager = CacheManager(True)
cache_manager.register_cache("test", cache, persist=True)
assert cache_manager.get("test", "key") is None
def test_i_can_get_value_from_sdp_when_cache_only_is_false(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
with sheerka.sdp.get_transaction(context.event) as transaction:
transaction.add("test", "key", "value")
cache = Cache(default=lambda k: sheerka.sdp.get("test", k))
cache_manager = CacheManager(False)
cache_manager.register_cache("test", cache, persist=True)
assert cache_manager.get("test", "key") == "value"
def test_i_can_commit_simple_cache(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
cache_manager = CacheManager(False)
cache_manager.register_cache("test", Cache(), persist=True)
cache = cache_manager.caches["test"].cache
cache_manager.put("test", "key", "value")
cache_manager.commit(context)
assert sheerka.sdp.get("test", "key") == "value"
cache.update("key", "value", "key", "another_value")
cache_manager.commit(context)
assert sheerka.sdp.get("test", "key") == "another_value"
cache.update("key", "another_value", "key2", "another_value")
cache_manager.commit(context)
assert sheerka.sdp.get("test", "key") is None
assert sheerka.sdp.get("test", "key2") == "another_value"
def test_i_can_commit_list_cache(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
cache_manager = CacheManager(False)
cache_manager.register_cache("test", ListCache(), persist=True)
cache = cache_manager.caches["test"].cache
cache.put("key", "value")
cache_manager.commit(context)
assert sheerka.sdp.get("test", "key") == ["value"]
cache.put("key", "value2")
cache_manager.commit(context)
assert sheerka.sdp.get("test", "key") == ["value", "value2"]
cache.update("key", "value2", "key2", "value2")
cache_manager.commit(context)
assert sheerka.sdp.get("test", "key") == ["value"]
assert sheerka.sdp.get("test", "key2") == ["value2"]
cache.update("key2", "value2", "key3", "value2")
cache_manager.commit(context)
assert sheerka.sdp.get("test", "key") == ["value"]
assert sheerka.sdp.get("test", "key2") is None
assert sheerka.sdp.get("test", "key3") == ["value2"]
def test_i_can_commit_dictionary_cache(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
cache_manager = CacheManager(False)
cache_manager.register_cache("test", DictionaryCache(), persist=True)
cache = cache_manager.caches["test"].cache
cache.put(False, {"key": "value", "key2": "value2"})
cache_manager.commit(context)
assert sheerka.sdp.get("test") == {"key": "value", "key2": "value2"}
assert sheerka.sdp.get("test", "key") == "value"
cache.put(False, {"key": "value", "key2": "value2", "key3": "value3"})
cache_manager.commit(context)
assert sheerka.sdp.get("test") == {"key": "value", "key2": "value2", "key3": "value3"}
+95 -150
View File
@@ -1,18 +1,20 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import PROPERTIES_TO_SERIALIZE, Concept, DEFINITION_TYPE_DEF
from core.sheerka.Sheerka import Sheerka
from sdp.sheerkaDataProvider import SheerkaDataProvider
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
def test_i_can_add_a_concept(self):
sheerka = self.get_sheerka()
def test_i_can_create_a_concept(self):
sheerka = self.get_sheerka(cache_only=False)
context = self.get_context(sheerka)
concept = self.get_default_concept()
res = sheerka.create_new_concept(self.get_context(sheerka), concept)
res = sheerka.create_new_concept(context, concept)
sheerka.cache_manager.commit(context)
assert res.status
assert sheerka.isinstance(res.value, BuiltinConcepts.NEW_CONCEPT)
@@ -24,22 +26,36 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
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 concept.name in sheerka.cache_by_name
assert sheerka.sdp.io.exists(
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_found.get_origin()))
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_HASH_ENTRY, concept.get_definition_hash())
# saved in cache
assert sheerka.has_id(concept.id)
assert sheerka.has_key(concept.key)
assert sheerka.has_name(concept.name)
assert sheerka.has_hash(concept.get_definition_hash())
# I can get the concept using various index
assert sheerka.get_by_id(concept.id) == concept
assert sheerka.get_by_key(concept.key) == concept
assert sheerka.get_by_name(concept.name) == concept
assert sheerka.get_by_hash(concept.get_definition_hash()) == concept
# I can get by the first entry
assert sheerka.cache_manager.get(sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, "+") == [concept.id]
assert sheerka.cache_manager.get(sheerka.RESOLVED_CONCEPTS_BY_FIRST_KEYWORD_ENTRY, "+") == [concept.id]
# saved in sdp
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_ID_ENTRY, concept.id)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_KEY_ENTRY, concept.key)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_NAME_ENTRY, concept.name)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_ENTRY, concept.key)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_HASH_ENTRY, concept.get_definition_hash())
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, "+")
def test_i_can_add_a_concept_when_name_differs_from_the_key(self):
sheerka = self.get_sheerka()
concept = Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_prop("a")
sheerka = self.get_sheerka(cache_only=False)
context = self.get_context(sheerka)
concept = Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a")
res = sheerka.create_new_concept(self.get_context(sheerka), concept)
sheerka.cache_manager.commit(context)
assert res.status
assert sheerka.isinstance(res.value, BuiltinConcepts.NEW_CONCEPT)
@@ -51,15 +67,24 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
assert concept_found.key == "hello __var__0"
assert concept_found.id == "1001"
assert concept.key in sheerka.cache_by_key
assert concept.id in sheerka.cache_by_id
assert concept.name in sheerka.cache_by_name
assert sheerka.sdp.io.exists(
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_found.get_origin()))
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_HASH_ENTRY, concept.get_definition_hash())
# saved in cache
assert sheerka.has_id(concept.id)
assert sheerka.has_key(concept.key)
assert sheerka.has_name(concept.name)
assert sheerka.has_hash(concept.get_definition_hash())
# I can get the concept using various index
assert sheerka.get_by_id(concept.id) == concept
assert sheerka.get_by_key(concept.key) == concept
assert sheerka.get_by_name(concept.name) == concept
assert sheerka.get_by_hash(concept.get_definition_hash()) == concept
# saved in sdp
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_ID_ENTRY, concept.id)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_KEY_ENTRY, concept.key)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_NAME_ENTRY, concept.name)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_ENTRY, concept.key)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_HASH_ENTRY, concept.get_definition_hash())
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, "hello")
def test_i_cannot_add_the_same_concept_twice(self):
"""
@@ -82,7 +107,7 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
sheerka.create_new_concept(self.get_context(sheerka), concept)
from_cache = sheerka.get(concept.key)
from_cache = sheerka.get_by_key(concept.key)
assert from_cache is not None
assert from_cache == concept
@@ -90,57 +115,7 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
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.reset_cache()
loaded = sheerka.get(concept.key)
assert loaded == concept
# I can also get it by its id
loaded = sheerka.sdp.get(sheerka.CONCEPTS_BY_ID_ENTRY, concept.id)
assert loaded == concept
def test_i_can_instantiate_a_concept_from_sdp(self):
sheerka = self.get_sheerka()
concept = Concept("foo")
sheerka.create_new_concept(self.get_context(sheerka), concept)
sheerka.reset_cache()
loaded = sheerka.new("foo")
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 == concept
def test_i_can_get_list_of_concept_when_same_key_when_no_cache(self):
def test_i_can_get_list_of_concept_when_same_key_using_cache(self):
sheerka = self.get_sheerka()
concept1 = self.get_default_concept()
concept2 = self.get_default_concept()
@@ -149,79 +124,13 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
res1 = sheerka.create_new_concept(self.get_context(sheerka), concept1)
res2 = sheerka.create_new_concept(self.get_context(sheerka), concept2)
assert res1.status
assert res2.status
assert res1.value.body.key == res2.value.body.key # same key
sheerka.cache_by_key = {} # reset the cache
result = sheerka.get(concept1.key)
result = sheerka.get_by_key(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)
def test_concept_that_references_itself_is_correctly_created(self):
sheerka = self.get_sheerka()
concept = Concept("foo", body="foo")
@@ -233,27 +142,63 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
class TestSheerkaCreateNewConceptFileBased(TestUsingFileBasedSheerka):
def test_i_can_add_several_concepts(self):
sheerka, context, hello, greeting = self.init_concepts(
Concept("Hello world a").def_prop("a"),
Concept("Greeting a").def_prop("a"),
use_dict=False
)
res = sheerka.create_new_concept(self.get_context(sheerka), hello)
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
hello = Concept("Hello world a").def_var("a")
res = sheerka.create_new_concept(context, hello)
sheerka.cache_manager.commit(context)
assert res.status
sheerka = self.get_sheerka(use_dict=False)
res = sheerka.create_new_concept(self.get_context(sheerka), greeting)
sheerka = self.get_sheerka() # another instance
context = self.get_context(sheerka)
greeting = Concept("Greeting a").def_var("a")
res = sheerka.create_new_concept(context, greeting)
sheerka.cache_manager.commit(context)
assert res.status
assert sheerka.sdp.exists(Sheerka.CONCEPTS_ENTRY, hello.key)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_ENTRY, greeting.key)
sheerka = self.get_sheerka() # another instance again
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_KEY_ENTRY, hello.key)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_KEY_ENTRY, greeting.key)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_ID_ENTRY, hello.id)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_ID_ENTRY, greeting.id)
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_NAME_ENTRY, "Hello world a")
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_NAME_ENTRY, "Greeting a")
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_HASH_ENTRY, hello.get_definition_hash())
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_HASH_ENTRY, greeting.get_definition_hash())
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, "Hello")
assert sheerka.sdp.exists(Sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, "Greeting")
def test_i_cannot_add_the_same_concept_twice_using_sdp(self):
"""
Checks that duplicated concepts are managed by sheerka, not by sheerka.sdp
:return:
"""
sheerka = self.get_sheerka(cache_only=False)
context = self.get_context(sheerka)
concept = self.get_default_concept()
sheerka.create_new_concept(context, concept)
sheerka.cache_manager.commit(context)
sheerka.cache_manager.clear()
res = sheerka.create_new_concept(context, concept)
assert not res.status
assert sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
assert res.value.body == concept
def test_new_entry_does_not_override_the_previous_ones(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
sheerka.create_new_concept(context, Concept("foo", body="1"))
sheerka.create_new_concept(context, Concept("foo", body="2"))
sheerka.cache_manager.commit(context)
assert len(sheerka.sdp.get(Sheerka.CONCEPTS_BY_KEY_ENTRY, "foo")) == 2
sheerka = self.get_sheerka() # new instance
sheerka.create_new_concept(context, Concept("foo", body="3"))
sheerka.cache_manager.commit(context)
assert len(sheerka.sdp.get(Sheerka.CONCEPTS_BY_KEY_ENTRY, "foo")) == 3
+161 -167
View File
@@ -1,6 +1,6 @@
import pytest
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, ParserResultConcept
from core.concept import Concept, simplec, DoNotResolve, ConceptParts, Property, InfiniteRecursionResolved
from core.concept import Concept, DoNotResolve, ConceptParts, Property, InfiniteRecursionResolved, CB
from parsers.PythonParser import PythonNode
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@@ -9,8 +9,8 @@ from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("body, expected", [
# (None, None),
# ("", ""),
(None, None),
("", ""),
("1", 1),
("1+1", 2),
("'one'", "one"),
@@ -19,10 +19,9 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
("1 > 2", False),
])
def test_i_can_evaluate_a_concept_with_simple_body(self, body, expected):
sheerka = self.get_sheerka()
sheerka, context, concept = self.init_concepts(Concept("foo", body=body), eval_body=True)
concept = Concept("foo", body=body).init_key()
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.body == expected
@@ -30,7 +29,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
assert evaluated.metadata.pre is None
assert evaluated.metadata.post is None
assert evaluated.metadata.where is None
assert evaluated.props == {}
assert evaluated.variables() == {}
assert evaluated.metadata.is_evaluated
assert len(evaluated.values) == 0 if body is None else 1
@@ -51,18 +50,17 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
:return:
"""
sheerka = self.get_sheerka()
sheerka, context, concept = self.init_concepts(Concept("foo", pre=expr))
concept = Concept("foo", pre=expr).init_key()
evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.metadata.body is None
assert evaluated.metadata.pre == expr
assert evaluated.metadata.post is None
assert evaluated.metadata.where is None
assert evaluated.get_metadata_value(ConceptParts.PRE) == expected
assert evaluated.props == {}
assert evaluated.get_value(ConceptParts.PRE) == expected
assert evaluated.variables() == {}
assert not evaluated.metadata.is_evaluated
assert len(evaluated.values) == 0 if expr is None else 1
@@ -77,124 +75,121 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
("1 > 2", False),
])
def test_i_can_evaluate_a_concept_with_prop(self, expr, expected):
sheerka = self.get_sheerka()
sheerka, context, concept = self.init_concepts(Concept("foo").def_var("a", expr), eval_body=True)
concept = Concept("foo").def_prop("a", expr)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka,True), concept)
evaluated = sheerka.evaluate_concept(context, 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.variables() == {"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")
sheerka, context, concept = self.init_concepts(Concept("foo"), eval_body=True)
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, 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")
sheerka, context, concept = self.init_concepts(Concept("foo").def_var("a"), eval_body=True)
concept.compiled["a"] = DoNotResolve("do not resolve")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.get_prop("a") == "do not resolve"
assert evaluated.get_value("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 = Concept("foo", body="original value").def_var("a", "original value")
sheerka, context, concept = self.init_concepts(concept, eval_body=True)
concept.compiled["a"] = DoNotResolve("do not resolve")
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.body == "do not resolve"
assert evaluated.get_prop("a") == "do not resolve"
assert evaluated.get_value("a") == "do not resolve"
assert evaluated.metadata.is_evaluated
def test_props_are_evaluated_before_body(self):
sheerka = self.get_sheerka()
def test_variables_are_evaluated_before_body(self):
sheerka, context, concept = self.init_concepts(Concept("foo", body="a+1").def_var("a", "10"), eval_body=True)
concept = Concept("foo", body="a+1").def_prop("a", "10").init_key()
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.body == 11
assert evaluated == CB(concept, 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)
sheerka, context, concept_a, concept = self.init_concepts(
Concept("a"),
Concept("foo", body="a"),
eval_body=True)
concept = Concept("foo", body="a").init_key()
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated == simplec("foo", simplec("a", None))
assert id(evaluated.body) != id(concept_a)
assert evaluated == CB("foo", CB("a", None))
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)
sheerka, context, concept_a, concept = self.init_concepts(
Concept("a", body="1"),
Concept("foo", body="a"),
eval_body=True)
concept = Concept("foo", body="a")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.body == simplec("a", 1)
assert evaluated.body == CB("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"))
sheerka, context, concept_a, concept_b, concept_c, concept_d = self.init_concepts(
Concept("a", body="'a'"),
Concept("b", body="a"),
Concept("c", body="b"),
Concept("d", body="c"),
eval_body=True)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept_d)
evaluated = sheerka.evaluate_concept(context, concept_d)
assert evaluated.key == concept_d.key
expected = simplec("c", simplec("b", simplec("a", "a")))
expected = CB("c", CB("b", CB("a", "a")))
assert evaluated.body == expected
assert sheerka.value(evaluated) == 'a'
assert sheerka.objvalue(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"))
sheerka, context, concept_a, concept_b, concept_c, concept_d = self.init_concepts(
Concept("a"),
Concept("b", body="a"),
Concept("c", body="b"),
Concept("d", body="c"),
eval_body=True)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept_d)
evaluated = sheerka.evaluate_concept(context, concept_d)
assert evaluated.key == concept_d.key
expected = simplec("c", simplec("b", simplec("a", None)))
expected = CB("c", CB("b", CB("a", None)))
assert evaluated.body == expected
assert sheerka.value(evaluated) == Concept(name="a").init_key()
assert sheerka.objvalue(evaluated) == CB("a", None)
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())
sheerka, context, concept_a, concept = self.init_concepts(
Concept("a"),
Concept("foo", body="a").def_var("a", "a"),
eval_body=True)
concept = Concept("foo", body="a").def_prop("a", "a").init_key()
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
# first prop a is evaluated to concept_a
# 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
@@ -205,49 +200,49 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
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"))
sheerka, context, concept_a = self.init_concepts(Concept(name="a"), eval_body=True)
concept = Concept("foo", body="concept_a").def_prop("concept_a", "a")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
concept = Concept("foo", body="concept_a").def_var("concept_a", "a")
evaluated = sheerka.evaluate_concept(context, 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"))
sheerka, context, *concepts = self.init_concepts(
Concept(name="a", body="1"),
Concept(name="b", body="2"),
eval_body=True
)
concept = Concept("foo", body="propA + propB").def_prop("propA", "a").def_prop("propB", "b")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
concept = Concept("foo", body="propA + propB").def_var("propA", "a").def_var("propB", "b")
evaluated = sheerka.evaluate_concept(context, 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())
sheerka, context, concept_a = self.init_concepts(Concept(name="a", body="'a'"), eval_body=True)
concept = Concept("foo").def_prop("a")
concept = Concept("foo").def_var("a")
concept.compiled["a"] = concept_a
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.get_prop("a") == simplec("a", "a")
assert evaluated.get_value("a") == CB("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 = Concept("to_eval").def_var("prop")
concept.compiled["prop"] = [foo, DoNotResolve("1")]
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
props = evaluated.get_prop("prop")
assert len(props) == 2
assert props[0] == simplec("foo", 1)
assert props[1] == "1"
variables = evaluated.get_value("prop")
assert len(variables) == 2
assert variables[0] == CB("foo", 1)
assert variables[1] == "1"
def test_i_can_evaluate_when_compiled_is_set_up_with_return_value(self):
sheerka = self.get_sheerka()
@@ -255,16 +250,16 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
python_node = PythonNode("1 +1 ")
parser_result = ParserResultConcept(parser="who", value=python_node)
concept = Concept("to_eval").def_prop("prop")
concept = Concept("to_eval").def_var("prop")
concept.compiled["prop"] = [ReturnValueConcept("who", True, parser_result)]
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
assert evaluated.get_prop("prop") == 2
assert evaluated.get_value("prop") == 2
# also works when only one return value
concept = Concept("to_eval").def_prop("prop")
concept = Concept("to_eval").def_var("prop")
concept.compiled["prop"] = ReturnValueConcept("who", True, parser_result)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
assert evaluated.get_prop("prop") == 2
assert evaluated.get_value("prop") == 2
def test_i_can_reference_sheerka(self):
sheerka = self.get_sheerka()
@@ -276,49 +271,55 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
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'"))
sheerka, context, concept_a, concept_b = self.init_concepts(
Concept(name="a", body="'concept_a'"),
Concept(name="b", body="'concept_b'"),
eval_body=True
)
concept = Concept("foo", body="a")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.body == simplec("a", "concept_a") # this test was already done
assert evaluated.body == CB("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, True), concept)
concept = Concept("foo", body="a").def_var("a", "'property_a'")
evaluated = sheerka.evaluate_concept(context, 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, True), concept)
concept = Concept("foo", body="a").def_var("a", "b")
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.body == simplec(name="b", body="concept_b")
assert evaluated.body == CB("b", "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'"))
sheerka, context, concept_a, concept_b = self.init_concepts(
Concept(name="a", body="'concept_a'"),
Concept(name="b", body="'concept_b'"),
eval_body=True
)
concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'").init_key()
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
concept = Concept("foo", body="a + b").def_var("a", "'prop_a'").init_key()
evaluated = sheerka.evaluate_concept(context, 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'"))
sheerka, context, concept_a = self.init_concepts(
Concept(name="concept_a").def_var("subProp", "'sub_a'"),
eval_body=True
)
concept = Concept("foo", body="a.props['subProp'].value").def_prop("a", "concept_a")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
assert evaluated == simplec(concept.key, "sub_a")
concept = Concept("foo", body="a.subProp").def_var("a", "concept_a")
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated == CB(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")
concept = Concept(name="concept_a").def_var("subProp", "undef_concept")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
@@ -340,11 +341,10 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
("a + self > 20", True),
])
def test_i_can_evaluate_simple_where(self, where_clause, expected):
sheerka = self.get_sheerka()
concept = Concept("foo", body="10", where=where_clause).def_prop("a", "20")
sheerka.add_in_cache(concept)
sheerka, context, concept = self.init_concepts(
Concept("foo", body="10", where=where_clause).def_var("a", "20"),
)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, False, True), concept)
if expected:
@@ -354,12 +354,10 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
assert evaluated.body == concept
def test_i_can_evaluate_where_when_using_other_concept(self):
sheerka = self.get_sheerka()
foo_true = Concept("foo_true", body="True").init_key()
foo_false = Concept("foo_false", body="False").init_key()
sheerka.add_in_cache(foo_false)
sheerka.add_in_cache(foo_true)
sheerka, context, foo_true, foo_false = self.init_concepts(
Concept("foo_true", body="True"),
Concept("foo_false", body="False"),
)
concept = Concept("foo", where="foo_true").init_key()
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, False, True), concept)
@@ -375,12 +373,9 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
assert evaluated.key == concept.key
def test_i_can_evaluate_disable_where_clause_evaluation(self):
sheerka = self.get_sheerka()
concept = Concept("foo", body="10", where="a > 10").def_prop("a", None)
sheerka.add_in_cache(concept)
context = self.get_context(sheerka)
sheerka, context, concept = self.init_concepts(
Concept("foo", body="10", where="a > 10").def_var("a", None),
)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
@@ -389,82 +384,84 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
def test_i_can_detect_infinite_recursion_with_numeric_constant(self):
sheerka = self.get_sheerka()
one_str = Concept("one", body="1")
one_digit = Concept("1", body="one")
sheerka, context, one_str, one_digit = self.init_concepts(
Concept("one", body="1"),
Concept("1", body="one"),
eval_body=True
)
sheerka.add_in_cache(one_str)
sheerka.add_in_cache(one_digit)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), one_digit)
evaluated = sheerka.evaluate_concept(context, one_digit)
assert evaluated.key == one_digit.key
assert evaluated.body == InfiniteRecursionResolved(1)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), one_str)
evaluated = sheerka.evaluate_concept(context, one_str)
assert evaluated.key == one_str.key
assert evaluated.body == InfiniteRecursionResolved(1)
def test_i_can_detect_infinite_recursion_with_boolean_constant(self):
sheerka = self.get_sheerka()
sheerka, context, true_str, true_bool = self.init_concepts(
Concept("true", body="True"),
Concept("True", body="true"),
eval_body=True
)
true_str = Concept("true", body="True")
true_bool = Concept("True", body="true")
sheerka.add_in_cache(true_str)
sheerka.add_in_cache(true_bool)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), true_str)
evaluated = sheerka.evaluate_concept(context, true_str)
assert evaluated.key == true_str.key
assert evaluated.body == InfiniteRecursionResolved(True)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), true_bool)
evaluated = sheerka.evaluate_concept(context, true_bool)
assert evaluated.key == true_bool.key
assert evaluated.body == InfiniteRecursionResolved(True)
def test_i_can_detect_infinite_recursion_with_constant_with_more_concepts(self):
sheerka = self.get_sheerka()
c1 = sheerka.add_in_cache(Concept("one", body="1"))
c2 = sheerka.add_in_cache(Concept("1", body="2"))
c3 = sheerka.add_in_cache(Concept("2", body="3"))
c4 = sheerka.add_in_cache(Concept("3", body="one"))
sheerka, context, c1, c2, c3, c4 = self.init_concepts(
Concept("one", body="1"),
Concept("1", body="2"),
Concept("2", body="3"),
Concept("3", body="one"),
eval_body=True
)
for concept in (c1, c2, c3, c4):
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
assert evaluated.body == InfiniteRecursionResolved(3)
def test_i_can_detect_infinite_recursion_when_no_constant(self):
sheerka = self.get_sheerka()
sheerka, context, foo, bar, baz, qux = self.init_concepts(
Concept("foo", body="bar"),
Concept("bar", body="baz"),
Concept("baz", body="qux"),
Concept("qux", body="foo"),
eval_body=True
)
foo = sheerka.add_in_cache(Concept("foo", body="bar"))
bar = sheerka.add_in_cache(Concept("bar", body="baz"))
baz = sheerka.add_in_cache(Concept("baz", body="qux"))
qux = sheerka.add_in_cache(Concept("qux", body="foo"))
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), foo)
evaluated = sheerka.evaluate_concept(context, foo)
assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG)
assert evaluated.body == {foo, bar, baz, qux}
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), bar)
evaluated = sheerka.evaluate_concept(context, bar)
assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG)
assert evaluated.body == {foo, bar, baz, qux}
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), baz)
evaluated = sheerka.evaluate_concept(context, baz)
assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG)
assert evaluated.body == {foo, bar, baz, qux}
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), qux)
evaluated = sheerka.evaluate_concept(context, qux)
assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG)
assert evaluated.body == {foo, bar, baz, qux}
def test_i_can_detect_auto_recursion(self):
sheerka = self.get_sheerka()
sheerka, context, foo = self.init_concepts(
Concept("foo", body="foo"),
eval_body=True
)
foo = sheerka.add_in_cache(Concept("foo", body="foo"))
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), foo)
evaluated = sheerka.evaluate_concept(context, foo)
assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG)
assert evaluated.body == {foo}
@@ -475,6 +472,3 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), one)
assert evaluated.key == one.key
assert evaluated.body == 1
+2 -1
View File
@@ -4,7 +4,8 @@ from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaHistoryManager(TestUsingMemoryBasedSheerka):
def test_i_can_retrieve_history(self):
sheerka = self.get_sheerka(skip_builtins_in_db=False, singleton=False)
sheerka = self.get_sheerka(singleton=False)
sheerka.save_execution_context = True
sheerka.evaluate_user_input("def concept one as 1")
sheerka.evaluate_user_input("one")
+63 -68
View File
@@ -1,96 +1,79 @@
import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, ConceptParts
from core.sheerka.Sheerka import Sheerka
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaModifyConcept(TestUsingMemoryBasedSheerka):
def test_i_can_modify_a_concept(self):
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True)
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True, cache_only=False)
foo_instance = sheerka.new("foo")
foo_instance.metadata.body = "value" # modify metadata
foo_instance.set_prop(BuiltinConcepts.ISA, bar) # modify property
foo_instance.set_metadata_value(ConceptParts.BODY, "body value") # modify value
foo_instance.metadata.body = "metadata value" # modify metadata
foo_instance.def_var("var_name", "default value") # modify definition of variables
foo_instance.add_prop(BuiltinConcepts.ISA, bar) # modify property
foo_instance.set_value(ConceptParts.BODY, "body value") # modify value
foo_instance.set_value("var_name", "var value") # modify value
res = sheerka.modify_concept(context, foo_instance)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_CONCEPT)
assert res.body.body.metadata.body == "value"
assert res.body.body.get_prop(BuiltinConcepts.ISA) == bar
assert res.body.body.metadata.body == "metadata value"
assert res.body.body.metadata.variables == [("var_name", "default value")]
assert res.body.body.get_prop(BuiltinConcepts.ISA) == {bar}
assert res.body.body.body == "body value"
assert res.body.body.get_value("var_name") == "var value"
# test that object
sheerka.reset_cache()
foo_from_sheerka = sheerka.new("foo")
assert foo_from_sheerka.metadata.body == "value"
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == bar
foo_from_sheerka = sheerka.get_by_key("foo")
assert foo_from_sheerka.metadata.body == "metadata value"
assert foo_from_sheerka.metadata.variables == [("var_name", "default value")]
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == {bar}
assert foo_from_sheerka.body == "body value"
assert foo_from_sheerka.get_value("var_name") == "var value"
# test that ref by id is updated
sheerka.reset_cache()
foo_from_sheerka = sheerka.get_by_id(foo.id)
assert foo_from_sheerka.metadata.body == "value"
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == bar
assert foo_from_sheerka.body == "body value"
# other caches are also updated
assert sheerka.get_by_id(foo.id).metadata.body == "metadata value"
assert sheerka.get_by_name(foo.name).metadata.body == "metadata value"
assert sheerka.get_by_hash(foo_instance.get_definition_hash()).metadata.body == "metadata value"
# test that ref by name is updated
sheerka.reset_cache()
foo_from_sheerka = sheerka.get_by_name(foo.name)
assert foo_from_sheerka.metadata.body == "value"
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == bar
assert foo_from_sheerka.body == "body value"
# test that ref by hash is updated
foo_from_sdp = sheerka.sdp.get(Sheerka.CONCEPTS_BY_HASH_ENTRY, foo_instance.get_definition_hash())
assert foo_from_sdp.metadata.body == "value"
assert foo_from_sdp.get_prop(BuiltinConcepts.ISA) == bar
assert foo_from_sdp.body == "body value"
# previous ref by hash is removed (since that definition hash has changed)
with pytest.raises(IndexError):
sheerka.sdp.get(Sheerka.CONCEPTS_BY_HASH_ENTRY, foo_instance.get_original_definition_hash())
def test_i_can_modify_concept_modifying_only_properties_and_body(self):
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True)
foo_instance = sheerka.new("foo")
foo_instance.set_prop(BuiltinConcepts.ISA, bar)
foo_instance.set_metadata_value(ConceptParts.BODY, "body value")
res = sheerka.modify_concept(context, foo_instance)
assert res.status
foo_from_sheerka = sheerka.new("foo")
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == bar
assert foo_from_sheerka.body == "body value"
def test_cache_is_updated_when_a_concept_is_modified(self):
sheerka, context, foo = self.init_concepts("foo", create_new=True)
foo_instance = sheerka.new("foo")
foo_instance.metadata.body = "value"
res = sheerka.modify_concept(context, foo_instance)
assert res.status
foo_from_sheerka = sheerka.get("foo")
assert foo_from_sheerka.metadata.body == "value"
foo_by_id_from_sheerka = sheerka.get_by_id(foo.id)
assert foo_by_id_from_sheerka.metadata.body == "value"
# sdp can be updated
sheerka.cache_manager.commit(context)
from_sdp = sheerka.sdp.get(sheerka.CONCEPTS_BY_ID_ENTRY, foo.id)
assert from_sdp.metadata.body == "metadata value"
assert from_sdp.metadata.variables == [("var_name", "default value")]
assert from_sdp.get_prop(BuiltinConcepts.ISA) == {bar}
assert from_sdp.body == "body value"
assert from_sdp.get_value("var_name") == "var value"
def test_i_cannot_modify_a_concept_that_does_not_exists(self):
sheerka, context, foo = self.init_concepts("foo", create_new=False)
sheerka, context = self.init_concepts()
foo_instance = sheerka.new("foo")
foo_instance.metadata.body = "value"
res = sheerka.modify_concept(context, foo_instance)
foo = Concept("foo").init_key()
sheerka.set_id_if_needed(foo, False)
res = sheerka.modify_concept(context, foo)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.UNKNOWN_CONCEPT)
assert res.body.body.key == foo.key
assert res.body.body == ("id", foo.id)
def test_i_cannot_modify_a_concept_that_returns_an_error(self):
sheerka, context = self.init_concepts()
foo = Concept("foo").init_key()
res = sheerka.modify_concept(context, foo)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
def test_i_cannot_modify_if_the_concept_has_not_changed(self):
sheerka, context, foo = self.init_concepts("foo", create_new=True)
res = sheerka.modify_concept(context, foo)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
def test_i_can_modify_a_concept_that_is_in_a_list(self):
sheerka, context, foo1, foo2 = self.init_concepts(
@@ -105,7 +88,19 @@ class TestSheerkaModifyConcept(TestUsingMemoryBasedSheerka):
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_CONCEPT)
assert res.body.body.metadata.body == "value"
sheerka.reset_cache()
foo_from_sheerka = sheerka.new("foo")
assert foo_from_sheerka[0].metadata.body == "1"
assert foo_from_sheerka[1].metadata.body == "value"
class TestSheerkaModifyConceptUsingFile(TestUsingFileBasedSheerka):
def test_i_can_modify_a_concept_from_a_new_sheerka(self):
sheerka, context, foo = self.init_concepts("foo", create_new=True)
sheerka.cache_manager.commit(context)
sheerka = self.get_sheerka()
foo.add_prop("a", "b")
res = sheerka.modify_concept(context, foo)
assert res.status
+175 -101
View File
@@ -1,79 +1,65 @@
from core.builtin_concepts import ConceptAlreadyInSet, BuiltinConcepts
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
class TestSheerkaSetsManager(TestUsingMemoryBasedSheerka):
# def init(self, use_dict, *concepts):
# sheerka = self.get_sheerka(use_dict, True)
# for c in concepts:
# sheerka.set_id_if_needed(c, False)
# sheerka.add_in_cache(c)
#
# context = self.get_context(sheerka)
# return sheerka, context
def test_i_can_add_a_concept_to_a_set(self):
sheerka, context, foo, group = self.init_concepts(
Concept("foo"),
Concept("group"),
cache_only=False
)
assert sheerka.add_concept_to_set(context, foo, group).status
def test_i_can_add_concept_to_set(self):
sheerka, context, foo, all_foos = self.init_concepts(Concept("foo"), Concept("all_foo"), use_dict=False)
group_elements = sheerka.cache_manager.get(sheerka.CONCEPTS_GROUPS_ENTRY, group.id)
assert group_elements == {foo.id}
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(use_dict=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, context, foo1, foo2, all_foos = self.init_concepts(
Concept("foo1"),
Concept("foo2"),
Concept("all_foo"), use_dict=False)
res = sheerka.sets_handler.add_concepts_to_set(context, (foo1, foo2), all_foos)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
all_entries = self.get_sheerka(use_dict=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
# I can add another elements
foo3 = Concept("foo3")
foo4 = Concept("foo4")
for c in [foo3, foo4]:
sheerka.set_id_if_needed(c, False)
sheerka.add_in_cache(c)
res = sheerka.sets_handler.add_concepts_to_set(context, (foo3, foo4), all_foos)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
all_entries = self.get_sheerka(use_dict=False).sdp.get("All_" + all_foos.id, None, False)
assert len(all_entries) == 4
assert foo1.id in all_entries
assert foo2.id in all_entries
assert foo3.id in all_entries
assert foo4.id in all_entries
# it can be persisted
sheerka.cache_manager.commit(context)
assert sheerka.sdp.get(sheerka.CONCEPTS_GROUPS_ENTRY, group.id) == {foo.id}
def test_i_cannot_add_the_same_concept_twice_in_a_set(self):
sheerka, context, foo, all_foos = self.init_concepts(Concept("foo"), Concept("all_foos"))
sheerka, context, foo, group = self.init_concepts(Concept("foo"), Concept("group"))
sheerka.add_concept_to_set(context, foo, group)
sheerka.add_concept_to_set(context, foo, all_foos)
res = sheerka.add_concept_to_set(context, foo, all_foos)
# add again
res = sheerka.add_concept_to_set(context, foo, group)
assert not res.status
assert res.body == ConceptAlreadyInSet(foo, all_foos)
assert sheerka.isinstance(res.body, BuiltinConcepts.CONCEPT_ALREADY_IN_SET)
assert res.body.body == foo
assert res.body.concept_set == group
all_entries = sheerka.sdp.get("All_" + all_foos.id, None, False)
assert len(all_entries) == 1
assert foo.id in all_entries
all_entries = sheerka.cache_manager.get(sheerka.CONCEPTS_GROUPS_ENTRY, group.id)
assert all_entries == {foo.id}
def test_i_can_have_multiple_groups(self):
sheerka, context, foo, bar, baz, group1, group2 = self.init_concepts(
Concept("foo"),
Concept("bar"),
Concept("baz"),
Concept("group1"),
Concept("group2"),
cache_only=False
)
assert sheerka.add_concept_to_set(context, foo, group1).status
assert sheerka.add_concept_to_set(context, bar, group1).status
assert sheerka.add_concept_to_set(context, bar, group2).status
assert sheerka.add_concept_to_set(context, baz, group2).status
assert sheerka.cache_manager.get(sheerka.CONCEPTS_GROUPS_ENTRY, group1.id) == {foo.id, bar.id}
assert sheerka.cache_manager.get(sheerka.CONCEPTS_GROUPS_ENTRY, group2.id) == {baz.id, bar.id}
# I can save in db
sheerka.cache_manager.commit(context)
assert sheerka.sdp.get(sheerka.CONCEPTS_GROUPS_ENTRY) == {
'1004': {'1001', '1002'}, '1005': {'1002', '1003'}
}
def test_i_get_elements_from_a_set(self):
sheerka, context, one, two, three, number = self.init_concepts(
@@ -83,7 +69,6 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
sheerka.add_concept_to_set(context, c, number)
elements = sheerka.get_set_elements(context, number)
assert set(elements) == {one, two, three}
def test_i_cannot_get_elements_if_not_a_set(self):
@@ -100,8 +85,9 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
assert not sheerka.isaset(context, group)
assert not sheerka.isinset(foo, group)
context = self.get_context(sheerka)
context = self.get_context(sheerka) # another context ?
sheerka.add_concept_to_set(context, foo, group)
assert sheerka.isaset(context, group)
assert sheerka.isinset(foo, group)
@@ -112,7 +98,7 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
sheerka.sets_handler.add_concepts_to_set(context, [foo, bar], group1)
assert sheerka.isaset(context, group2)
assert sheerka.get_set_elements(context, group2) == [foo, bar]
assert set(sheerka.get_set_elements(context, group2)) == {foo, bar}
def test_i_can_define_subset_of_another_group(self):
sheerka, context, one, two, three, four, five, number, sub_number = self.init_concepts(
@@ -122,15 +108,30 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
Concept("four", body="4"),
Concept("five", body="5"),
Concept("number"),
Concept("sub_number", body="number", where="number < 4"),
create_new=True
Concept("sub_number", body="number", where="number < 4")
)
sheerka.sets_handler.add_concepts_to_set(context, [one, two, three, four, five], number)
assert sheerka.isaset(context, sub_number)
assert sheerka.get_set_elements(context, sub_number) == [one, two, three]
assert set(sheerka.get_set_elements(context, sub_number)) == {one, two, three}
def test_i_can_define_subset_of_another_set_when_some_concept_dont_have_a_defined_body(self):
def test_i_can_define_subset_of_subset(self):
sheerka, context, one, two, three, four, five, number, sub_number, sub_sub_number = self.init_concepts(
Concept("one", body="1"),
Concept("two", body="2"),
Concept("three", body="3"),
Concept("four", body="4"),
Concept("five", body="5"),
Concept("number"),
Concept("sub_number", body="number", where="number < 4"),
Concept("sub_sub_number", body="sub_number", where="sub_number > 2")
)
sheerka.sets_handler.add_concepts_to_set(context, [one, two, three, four, five], number)
assert sheerka.isaset(context, sub_sub_number)
assert set(sheerka.get_set_elements(context, sub_sub_number)) == {three}
def test_i_can_define_subset_of_another_set_when_some_concept_do_not_have_a_defined_body(self):
"""
Example
def concept unit from number where number <10
@@ -151,7 +152,7 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
sheerka.sets_handler.add_concepts_to_set(context, [one, two, three, four, five], number)
assert sheerka.isaset(context, sub_number)
assert sheerka.get_set_elements(context, sub_number) == [one, three]
assert set(sheerka.get_set_elements(context, sub_number)) == {one, three}
def test_i_can_define_subset_of_another_set_when_some_concept_are_bnf(self):
"""
@@ -190,8 +191,9 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
Concept("one", body="1"),
Concept("two", body="2"),
Concept("twenty", body="20"),
Concept("twenties", definition="twenty (one|two)=unit", body="twenty + unit").def_prop("unit"),
Concept("twenties", definition="twenty (one|two)=unit", body="twenty + unit").def_var("unit"),
Concept("number"),
create_new=True
)
sheerka.sets_handler.add_concepts_to_set(context, [one, two, twenty, twenties], number)
@@ -200,39 +202,27 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
twenty_one = sheerka.evaluate_user_input("twenty one", "")[0].body
assert sheerka.isinset(twenty_one, number)
def test_i_can_set_isa(self):
sheerka, context, foo, all_foos = self.init_concepts(
"foo", "all_foo",
create_new=True,
use_dict=False)
assert BuiltinConcepts.ISA not in foo.props
sheerka.set_isa(context, foo, all_foos)
assert foo.get_prop(BuiltinConcepts.ISA) == [all_foos]
assert sheerka.isa(foo, all_foos)
assert sheerka.isinset(foo, all_foos)
assert sheerka.isaset(context, all_foos)
def test_a_concept_can_be_in_multiple_sets(self):
sheerka, context, foo, all_foos, all_bars = self.init_concepts(
sheerka, context, foo, all_foo, all_bar = self.init_concepts(
Concept("foo"),
Concept("all_foo"),
Concept("all_bar"),
use_dict=False)
sheerka.create_new_concept(context, foo)
create_new=True
)
sheerka.set_isa(context, foo, all_foos)
sheerka.set_isa(context, foo, all_bars)
foo = sheerka.new(foo.key) # new instance
sheerka.set_isa(context, foo, all_foo)
assert foo.get_prop(BuiltinConcepts.ISA) == [all_foos, all_bars]
assert sheerka.isa(foo, all_foos)
assert sheerka.isa(foo, all_bars)
assert sheerka.isinset(foo, all_foos)
assert sheerka.isinset(foo, all_bars)
assert sheerka.isaset(context, all_foos)
assert sheerka.isaset(context, all_bars)
foo = sheerka.new(foo.key) # new instance
sheerka.set_isa(context, foo, all_bar)
assert foo.get_prop(BuiltinConcepts.ISA) == {all_foo, all_bar}
assert sheerka.isa(foo, all_foo)
assert sheerka.isa(foo, all_bar)
assert sheerka.isinset(foo, all_foo)
assert sheerka.isinset(foo, all_bar)
assert sheerka.isaset(context, all_foo)
assert sheerka.isaset(context, all_bar)
def test_i_can_manage_isa_transitivity(self):
"""
@@ -244,10 +234,9 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
Concept("foo"),
Concept("bar"),
Concept("baz"),
create_new=True
)
sheerka.create_new_concept(context, foo)
sheerka.create_new_concept(context, bar)
sheerka.create_new_concept(context, baz)
sheerka.set_isa(context, foo, bar)
sheerka.set_isa(context, bar, baz)
@@ -255,3 +244,88 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka):
assert sheerka.isa(foo, bar)
assert sheerka.isa(bar, baz)
assert sheerka.isa(foo, baz)
class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
def test_i_can_add_concept_to_set_and_retrieve_it_in_another_session(self):
sheerka, context, foo, bar, group = self.init_concepts(
Concept("foo"),
Concept("bar"),
Concept("group"),
create_new=True)
assert sheerka.add_concept_to_set(context, foo, group).status
sheerka.cache_manager.commit(context)
sheerka = self.get_sheerka() # another session
assert sheerka.add_concept_to_set(context, bar, group).status
# I can get the elements
assert set(sheerka.get_set_elements(context, group)) == {foo, bar}
sheerka.cache_manager.commit(context) # save in db
all_entries = sheerka.sdp.get(sheerka.CONCEPTS_GROUPS_ENTRY) # check the db
assert all_entries == {
group.id: {foo.id, bar.id}
}
# I can also add a group another elements
sheerka = self.get_sheerka()
foo3 = Concept("foo3")
foo4 = Concept("foo4")
for c in [foo3, foo4]:
sheerka.create_new_concept(context, c)
res = sheerka.sets_handler.add_concepts_to_set(context, (foo3, foo4), group)
assert res.status
# I can get the elements
assert set(sheerka.get_set_elements(context, group)) == {foo, bar, foo3, foo4}
sheerka.cache_manager.commit(context) # save in db
all_entries = sheerka.sdp.get(sheerka.CONCEPTS_GROUPS_ENTRY) # check the db
assert all_entries == {
group.id: {foo.id, bar.id, foo3.id, foo4.id}
}
def test_i_can_set_isa(self):
sheerka, context, foo, bar, group = self.init_concepts(
"foo",
"bar",
"group",
create_new=True, # needed by modify
)
# nothing was previously in ISA
foo = sheerka.new(foo.key)
assert BuiltinConcepts.ISA not in foo.metadata.props
res = sheerka.set_isa(context, foo, group)
assert res.status
sheerka.cache_manager.commit(context)
sheerka = self.get_sheerka()
assert foo.get_prop(BuiltinConcepts.ISA) == {group}
assert sheerka.isa(foo, group)
assert sheerka.isinset(foo, group)
assert sheerka.isaset(context, group)
# I can do the same for bar
sheerka = self.get_sheerka()
res = sheerka.set_isa(context, bar, group)
assert res.status
assert bar.get_prop(BuiltinConcepts.ISA) == {group}
assert sheerka.isa(bar, group)
assert sheerka.isinset(bar, group)
assert sheerka.isaset(context, group)
sheerka.cache_manager.commit(context)
# they are both in the same group
sheerka = self.get_sheerka()
all_entries = sheerka.sdp.get(sheerka.CONCEPTS_GROUPS_ENTRY)
assert all_entries == {
group.id: {foo.id, bar.id}
}
elements = sheerka.get_set_elements(context, group)
assert set(elements) == {foo, bar}
+50 -34
View File
@@ -1,20 +1,23 @@
from core.concept import Concept, ConceptParts
from core.sheerka.Services.SheerkaVariableManager import SheerkaVariableManager
from core.sheerka.Sheerka import Sheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
def test_i_can_record_and_load_a_constant(self):
sheerka = self.get_sheerka()
sheerka = self.get_sheerka(cache_only=False)
context = self.get_context(sheerka)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
res = sheerka.load("TestSheerkaVariable", "my_variable")
assert res == 1
assert sheerka.sdp.exists(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
# I can persist in db
sheerka.cache_manager.commit(context)
assert sheerka.sdp.exists(Sheerka.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
loaded = sheerka.sdp.get(Sheerka.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
assert loaded.event_id == context.event.get_digest()
assert loaded.key == "my_variable"
assert loaded.value == 1
@@ -25,47 +28,60 @@ class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
concept = Concept("foo").set_prop("a", "alpha").set_metadata_value(ConceptParts.BODY, 3.14)
concept = Concept("foo").set_value("a", "alpha").set_value(ConceptParts.BODY, 3.14)
sheerka.record(context, "TestSheerkaVariable", "my_variable", concept)
res = sheerka.load("TestSheerkaVariable", "my_variable")
assert res == concept
assert res.body == concept.body
assert res.a == concept.a
def test_i_can_get_the_parent_when_modified(self):
def test_i_can_delete_an_entry(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 2)
res = sheerka.load("TestSheerkaVariable", "my_variable")
assert res == 2
concept = Concept("foo")
loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
assert loaded.event_id == context.event.get_digest()
assert loaded.key == "my_variable"
assert loaded.value == 2
assert loaded.who == "TestSheerkaVariable"
assert loaded.parents == ['8c9ada7bf488d84229f6539f76042431638f16d600fe3b7ec7e7161043a40d59']
sheerka.record(context, "TestSheerkaVariable", "my_variable", concept)
assert sheerka.load("TestSheerkaVariable", "my_variable") is not None
parent = sheerka.sdp.load_obj(loaded.parents[0])
assert parent.event_id == context.event.get_digest()
assert parent.key == "my_variable"
assert parent.value == 1
assert parent.who == "TestSheerkaVariable"
assert parent.parents is None
sheerka.delete(context, "TestSheerkaVariable", "my_variable")
assert sheerka.load("TestSheerkaVariable", "my_variable") is None
def test_variable_is_not_persisted_if_the_value_is_the_same(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
# def test_i_can_get_the_parent_when_modified(self):
# sheerka = self.get_sheerka()
# context = self.get_context(sheerka)
#
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 2)
# res = sheerka.load("TestSheerkaVariable", "my_variable")
# assert res == 2
#
# loaded = sheerka.sdp.get(Sheerka.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
# assert loaded.event_id == context.event.get_digest()
# assert loaded.key == "my_variable"
# assert loaded.value == 2
# assert loaded.who == "TestSheerkaVariable"
# assert loaded.parents == ['8c9ada7bf488d84229f6539f76042431638f16d600fe3b7ec7e7161043a40d59']
#
# parent = sheerka.sdp.load_obj(loaded.parents[0])
# assert parent.event_id == context.event.get_digest()
# assert parent.key == "my_variable"
# assert parent.value == 1
# assert parent.who == "TestSheerkaVariable"
# assert parent.parents is None
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
assert loaded.event_id == context.event.get_digest()
assert loaded.key == "my_variable"
assert loaded.value == 1
assert loaded.who == "TestSheerkaVariable"
assert loaded.parents is None
# def test_variable_is_not_persisted_if_the_value_is_the_same(self):
# sheerka = self.get_sheerka(singleton=True)
# context = self.get_context(sheerka)
#
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
#
# loaded = sheerka.sdp.get(Sheerka.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
# assert loaded.event_id == context.event.get_digest()
# assert loaded.key == "my_variable"
# assert loaded.value == 1
# assert loaded.who == "TestSheerkaVariable"
# assert loaded.parents is None
+18 -19
View File
@@ -1,16 +1,15 @@
import ast
import pytest
from core.ast.nodes import NodeParent, GenericNodeConcept
import core.ast.nodes
import pytest
from core.ast.nodes import NodeParent, GenericNodeConcept
from core.ast.visitors import ConceptNodeVisitor, UnreferencedNamesVisitor
from core.builtin_concepts import BuiltinConcepts
from core.sheerka.Sheerka import Sheerka
def get_sheerka():
sheerka = Sheerka(skip_builtins_in_db=True)
sheerka = Sheerka(cache_only=True)
sheerka.initialize("mem://")
return sheerka
@@ -40,32 +39,32 @@ def my_function(a,b):
sheerka = get_sheerka()
assert tree_as_concept.node_type == "Module"
assert sheerka.isinstance(tree_as_concept.get_prop("body"), BuiltinConcepts.LIST)
assert sheerka.isinstance(tree_as_concept.get_value("body"), BuiltinConcepts.LIST)
def_func = tree_as_concept.get_prop("body").body[0]
def_func = tree_as_concept.get_value("body").body[0]
assert sheerka.isinstance(def_func, BuiltinConcepts.GENERIC_NODE)
assert def_func.node_type == "FunctionDef"
assert def_func.parent == NodeParent(tree_as_concept, "body")
assert def_func.get_prop("name") == "my_function"
assert def_func.get_value("name") == "my_function"
def_func_args = def_func.get_prop("args")
def_func_args = def_func.get_value("args")
assert sheerka.isinstance(def_func_args, BuiltinConcepts.GENERIC_NODE)
assert def_func_args.node_type == "arguments"
def_func_args_real_args = def_func_args.get_prop("args")
def_func_args_real_args = def_func_args.get_value("args")
assert sheerka.isinstance(def_func_args_real_args, BuiltinConcepts.LIST)
assert len(def_func_args_real_args.body) == 2
assert sheerka.isinstance(def_func_args_real_args.body[0], BuiltinConcepts.GENERIC_NODE)
assert def_func_args_real_args.body[0].node_type == "arg"
assert def_func_args_real_args.body[0].parent == NodeParent(def_func_args, "args")
assert def_func_args_real_args.body[0].get_prop("arg") == "a"
assert def_func_args_real_args.body[0].get_value("arg") == "a"
assert sheerka.isinstance(def_func_args_real_args.body[1], BuiltinConcepts.GENERIC_NODE)
assert def_func_args_real_args.body[1].node_type == "arg"
assert def_func_args_real_args.body[1].parent == NodeParent(def_func_args, "args")
assert def_func_args_real_args.body[1].get_prop("arg") == "b"
assert def_func_args_real_args.body[1].get_value("arg") == "b"
def_fun_body = def_func.get_prop("body")
def_fun_body = def_func.get_value("body")
assert sheerka.isinstance(def_fun_body, BuiltinConcepts.LIST)
assert len(def_fun_body.body) == 2
@@ -95,13 +94,13 @@ def my_function(a,b):
visitor.visit(concept_node)
sheerka = get_sheerka()
assert sheerka.value(visitor.names[0]) == "i"
assert sheerka.value(visitor.names[1]) == "range"
assert sheerka.value(visitor.names[2]) == "b"
assert sheerka.value(visitor.names[3]) == "a"
assert sheerka.value(visitor.names[4]) == "a"
assert sheerka.value(visitor.names[5]) == "b"
assert sheerka.value(visitor.names[6]) == "a"
assert sheerka.objvalue(visitor.names[0]) == "i"
assert sheerka.objvalue(visitor.names[1]) == "range"
assert sheerka.objvalue(visitor.names[2]) == "b"
assert sheerka.objvalue(visitor.names[3]) == "a"
assert sheerka.objvalue(visitor.names[4]) == "a"
assert sheerka.objvalue(visitor.names[5]) == "b"
assert sheerka.objvalue(visitor.names[6]) == "a"
def test_i_can_get_unreferenced_variables():
+2 -2
View File
@@ -1,7 +1,7 @@
import ast
import pytest
import core.builtin_helpers
import core.builtin_helpers
import pytest
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
+47 -24
View File
@@ -3,7 +3,7 @@ import pytest
from core.concept import Concept, ConceptParts, DEFINITION_TYPE_DEF
@pytest.mark.parametrize("name, properties, expected", [
@pytest.mark.parametrize("name, variables, expected", [
("foo", [], "foo"),
("foo(bar)", [], "foo ( bar )"),
("foo a", ["a"], "foo __var__0"),
@@ -20,21 +20,20 @@ from core.concept import Concept, ConceptParts, DEFINITION_TYPE_DEF
("a b a c", ["a", "b"], "__var__0 __var__1 __var__0 c"),
("a b a c", ["b", "a"], "__var__1 __var__0 __var__1 c"),
])
def test_i_can_compute_the_key(name, properties, expected):
def test_i_can_compute_the_key(name, variables, expected):
concept = Concept(name)
for prop in properties:
concept.metadata.props.append((prop, None))
for var_name in variables:
concept.metadata.variables.append((var_name, None))
concept.init_key()
assert concept.key == expected
def test_i_can_compute_the_key_when_from_definition():
# if definition is not defined, use the name
concept = Concept()
concept.metadata.name = "hello a"
concept.metadata.props = [("a", None)]
concept.metadata.variables = [("a", None)]
concept.init_key()
assert concept.key == "hello __var__0"
@@ -43,13 +42,13 @@ def test_i_can_compute_the_key_when_from_definition():
concept.metadata.name = "greetings"
concept.metadata.definition = "hello a"
concept.metadata.definition_type = DEFINITION_TYPE_DEF
concept.metadata.props = [("a", None)]
concept.metadata.variables = [("a", None)]
concept.init_key()
assert concept.key == "hello __var__0"
def test_key_does_not_use_variable_when_definition_is_set():
concept = Concept("plus").def_prop('plus')
concept = Concept("plus").def_var('plus')
concept.init_key()
assert concept.metadata.key == "plus"
@@ -73,7 +72,7 @@ def test_i_can_serialize():
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
).def_var("a", "10").def_var("b", None)
to_dict = concept.to_dict()
assert to_dict == {
@@ -88,7 +87,8 @@ def test_i_can_serialize():
'name': 'concept_name',
'post': 'definition of the post',
'pre': 'definition of the pre',
'props': [('a', "10"), ('b', None)],
'props': {},
'variables': [('a', "10"), ('b', None)],
'where': 'definition of the where'
}
@@ -111,7 +111,8 @@ def test_i_can_deserialize():
'name': 'concept_name',
'post': 'definition of the post',
'pre': 'definition of the pre',
'props': [('a', "10"), ('b', None)],
'props': {},
'variables': [('a', "10"), ('b', None)],
'where': 'definition of the where'
}
@@ -130,16 +131,16 @@ def test_i_can_deserialize():
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
).def_var("a", "10").def_var("b", None)
def test_i_can_deserialize_props_coming_from_sdp():
def test_i_can_deserialize_variables_coming_from_sdp():
from_dict = {
'props': [['a', "10"], ['b', None]], # JSON transform set into list
'variables': [['a', "10"], ['b', None]], # JSON transform set into list
}
concept = Concept().from_dict(from_dict)
assert concept == Concept().def_prop("a", "10").def_prop("b", None)
assert concept == Concept().def_var("a", "10").def_var("b", None)
def test_i_can_compare_concepts():
@@ -156,7 +157,7 @@ def test_i_can_compare_concepts():
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
).def_var("a", "10").def_var("b", None).add_prop("prop", "prop_val")
concept_b = Concept(
name="concept_name",
@@ -171,11 +172,33 @@ def test_i_can_compare_concepts():
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
).def_var("a", "10").def_var("b", None).add_prop("prop", "prop_val")
assert concept_a == concept_b
def test_i_can_detect_concept_differences():
assert Concept(name="concept_name") != Concept()
assert Concept(is_builtin=True) != Concept()
assert Concept(is_unique=True) != Concept()
assert Concept(key="concept_key") != Concept()
assert Concept(body="concept_body") != Concept()
assert Concept(where="concept_where") != Concept()
assert Concept(pre="concept_pre") != Concept()
assert Concept(post="concept_post") != Concept()
assert Concept(definition="def") != Concept()
assert Concept(definition_type="def type") != Concept()
assert Concept(desc="desc") != Concept()
assert Concept(id="concept_id") != Concept()
assert Concept().def_var("a") != Concept()
assert Concept().add_prop("a", "b") != Concept()
assert Concept().set_value("a", "b") != Concept()
concept = Concept()
concept.compiled["foo"] = "value"
assert concept == Concept() # compiled is not used in the comparison
def test_i_can_compare_concept_with_circular_reference():
foo = Concept("foo")
foo.metadata.body = foo
@@ -215,17 +238,17 @@ def test_i_can_update_from():
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
).def_var("a", "10").def_var("b", None)
# make sure origin is preserved
setattr(template, "##origin##", "digest")
template.values[ConceptParts.BODY] = "value in body"
template.values[ConceptParts.WHERE] = "value in where"
template.values[ConceptParts.PRE] = "value in pre"
template.values[ConceptParts.POST] = "value in post"
template.set_prop("a", 10)
template.set_prop("b", 20)
template.set_value(ConceptParts.BODY, "value in body")
template.set_value(ConceptParts.WHERE, "value in where")
template.set_value(ConceptParts.PRE, "value in pre")
template.set_value(ConceptParts.POST, "value in post")
template.set_value("a", 10)
template.set_value("b", 20)
concept = Concept().update_from(template)
+218 -103
View File
@@ -1,24 +1,33 @@
import pytest
import os
import pytest
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
from core.concept import Concept, PROPERTIES_TO_SERIALIZE
from core.sheerka.Sheerka import Sheerka
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, ConceptParts
from core.sheerka.Sheerka import Sheerka, BASE_NODE_PARSER_CLASS
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class ConceptWithGetValue(Concept):
def get_value(self):
return self.get_prop("my_prop")
class ConceptWithGetObjValue(Concept):
def get_obj_value(self):
return self.get_value("my_prop")
class TestSheerka(TestUsingFileBasedSheerka):
class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
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_initialize_builtin_parsers(self):
sheerka = self.get_sheerka()
# test existence of some parser (not all)
assert "parsers.DefaultParser.DefaultParser" in sheerka.parsers
assert "parsers.BnfNodeParser.BnfNodeParser" in sheerka.parsers
assert "parsers.SyaNodeParser.SyaNodeParser" in sheerka.parsers
assert "parsers.AtomNodeParser.AtomNodeParser" in sheerka.parsers
# make sure BaseNodeParser is properly initialized
assert BASE_NODE_PARSER_CLASS not in sheerka.parsers
assert sheerka.bnp is not None
def test_i_can_list_builtin_concepts(self):
sheerka = self.get_sheerka()
@@ -27,27 +36,6 @@ class TestSheerka(TestUsingFileBasedSheerka):
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(use_dict=False, skip_builtins_in_db=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(use_dict=False, skip_builtins_in_db=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
@@ -56,27 +44,27 @@ class TestSheerka(TestUsingFileBasedSheerka):
"""
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
assert sheerka.get_by_key(key) is not None
assert sheerka.get_by_key(str(key)) is not None
def test_i_cannot_get_when_key_is_none(self):
sheerka = self.get_sheerka()
res = sheerka.get(None)
res = sheerka.get_by_key(None)
assert sheerka.isinstance(res, BuiltinConcepts.ERROR)
assert res.body == "Concept key is undefined."
assert res.body == "Concept 'None' is undefined."
def test_unknown_concept_is_return_when_the_concept_key_is_not_found(self):
def test_i_cannot_get_when_key_is_not_found(self):
sheerka = self.get_sheerka()
loaded = sheerka.get("key_that_does_not_exist")
loaded = sheerka.get_by_key("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):
def test_i_cannot_get_when_id_is_not_found(self):
sheerka = self.get_sheerka()
loaded = sheerka.get_by_id("id_that_does_not_exist")
@@ -97,6 +85,10 @@ class TestSheerka(TestUsingFileBasedSheerka):
assert ret.value == "value"
assert ret.message == "message"
# check the others
for key, concept_class in sheerka.get_builtins_classes_as_dict().items():
assert isinstance(sheerka.get_by_key(key), concept_class)
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")
@@ -106,9 +98,7 @@ class TestSheerka(TestUsingFileBasedSheerka):
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)
sheerka, context, concept = self.init_concepts(self.get_default_concept(), create_new=True)
new = sheerka.new(concept.key, a=10, b="value")
@@ -116,27 +106,33 @@ class TestSheerka(TestUsingFileBasedSheerka):
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"
assert new.get_value("a") == 10
assert new.get_value("b") == "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"))
def test_i_can_instantiate_multiple_when_same_key(self):
sheerka, context, *concepts = self.init_concepts(
Concept("foo", body="foo1"),
Concept("foo", body="foo2"),
create_new=True)
# when no id, i get two instances
concepts = sheerka.new("foo")
assert len(concepts) == 2
assert concepts[0].id == "1001"
assert concepts[0].metadata.body == "foo1"
assert concepts[1].id == "1002"
assert concepts[1].metadata.body == "foo2"
# only one instance if the id is given
foo1 = sheerka.new(("foo", "1001"))
assert foo1.metadata.body == "foo1"
# only one instance if the id is given
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)
sheerka, context, concept = self.init_concepts(self.get_default_concept(), create_new=True)
new1 = sheerka.new(concept.key, a=10, b="value")
new2 = sheerka.new(concept.key, a=10, b="value")
@@ -144,17 +140,50 @@ class TestSheerka(TestUsingFileBasedSheerka):
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)
def test_new_instance_does_not_impact_each_others(self):
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True)
new1 = sheerka.new(concept.key, a=10, b="value")
new2 = sheerka.new(concept.key, a=10, b="value")
new_foo = sheerka.new("foo")
new_foo.metadata.body = "metadata value" # modify metadata
new_foo.def_var("var_name", "default value") # modify definition of variables
new_foo.add_prop(BuiltinConcepts.ISA, bar) # modify property
new_foo.compiled["var_name"] = "'var value'"
new_foo.set_value(ConceptParts.BODY, "body value") # modify value
new_foo.set_value("var_name", "var value") # modify value
assert new_foo.metadata.body != foo.metadata.body
assert new_foo.metadata.variables != foo.metadata.variables
assert new_foo.metadata.props != foo.metadata.props
assert new_foo.values != foo.values
assert new_foo.compiled != foo.compiled
def test_i_get_the_same_instance_when_is_unique_is_true(self):
sheerka, context, concept = self.init_concepts(Concept(name="unique", is_unique=True), create_new=True)
new1 = sheerka.new(concept.key)
new2 = sheerka.new(concept.key, a=10, b="value") # not that variables are simply discareded
assert new1 == new2
assert id(new1) == id(new2)
def test_values_are_reset_when_asking_for_a_new_instance(self):
sheerka, context, template = self.init_concepts(
Concept("foo", body="'foo body'"),
create_new=True,
eval_body=True)
sheerka.evaluate_concept(context, sheerka.get_by_id(template.id))
assert template.metadata.is_evaluated
assert template.body == "foo body"
new = sheerka.new(template.key)
assert not new.metadata.is_evaluated
assert not new.body
new = sheerka.new((None, template.id))
assert not new.metadata.is_evaluated
assert not new.body
def test_i_cannot_instantiate_an_unknown_concept(self):
sheerka = self.get_sheerka()
@@ -164,9 +193,10 @@ class TestSheerka(TestUsingFileBasedSheerka):
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"))
sheerka, context, *concepts = self.init_concepts(
Concept("foo", body="foo1"),
Concept("foo", body="foo2"),
create_new=True)
new = sheerka.new(("foo", "invalid_id"))
@@ -174,9 +204,10 @@ class TestSheerka(TestUsingFileBasedSheerka):
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"))
sheerka, context, *concepts = self.init_concepts(
Concept("foo", body="foo1"),
Concept("foo", body="foo2"),
create_new=True)
new = sheerka.new(("invalid_key", "1001"))
@@ -184,8 +215,9 @@ class TestSheerka(TestUsingFileBasedSheerka):
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"))
sheerka, context, *concepts = self.init_concepts(
Concept("foo", body="foo1"),
create_new=True)
new = sheerka.new(("foo", "invalid_id"))
@@ -193,9 +225,7 @@ class TestSheerka(TestUsingFileBasedSheerka):
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)
sheerka, context, concept = self.init_concepts(self.get_default_concept(), create_new=True)
new = sheerka.new(concept.key, a=10, c="value")
@@ -210,7 +240,7 @@ class TestSheerka(TestUsingFileBasedSheerka):
(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"),
(ConceptWithGetObjValue("name").set_value("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"),
@@ -230,53 +260,138 @@ class TestSheerka(TestUsingFileBasedSheerka):
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(use_dict=False, skip_builtins_in_db=False)
concepts = sheerka.concepts()
assert concepts[0].id < concepts[-1].id
assert sheerka.objvalue(concept, reduce_simple_list) == expected
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))
def test_cache_is_updated_after_get(self):
sheerka = self.get_sheerka(skip_builtins_in_db=False)
# updated when by_key returns one element
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="1"))
sheerka.reset_cache()
sheerka.get("foo")
assert "foo" in sheerka.cache_by_key
assert "1001" in sheerka.cache_by_id
class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
# updated when by_key returns two elements
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="2"))
sheerka.reset_cache()
sheerka.get("foo")
assert "foo" in sheerka.cache_by_key
assert "1001" in sheerka.cache_by_id
assert "1002" in sheerka.cache_by_id
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_builtin_concepts_are_initialized(self):
sheerka = self.get_sheerka()
for concept_name in BuiltinConcepts:
assert sheerka.has_key(str(concept_name))
assert sheerka.sdp.get(sheerka.CONCEPTS_BY_KEY_ENTRY, str(concept_name)) is not None
# I can get back data from the sdp when the cache is empty
sheerka.cache_manager.clear()
# caches are empty
assert not sheerka.has_id("1")
assert not sheerka.has_key(str(BuiltinConcepts.SHEERKA))
assert sheerka.get_by_id("1") == sheerka # use sdp
# assert sheerka.has_key(str(BuiltinConcepts.SHEERKA)) # auto update the other caches
def test_builtin_concepts_can_be_updated(self):
sheerka = self.get_sheerka()
before_parsing = sheerka.get_by_key(BuiltinConcepts.BEFORE_PARSING)
before_parsing.metadata.desc = "I have a description"
before_parsing.metadata.full_serialization = True
with sheerka.sdp.get_transaction("Test") as transac:
transac.add(sheerka.CONCEPTS_BY_KEY_ENTRY, before_parsing.key, before_parsing, use_ref=True)
sheerka = self.get_sheerka() # another fresh new instance
before_parsing = sheerka.get_by_key(BuiltinConcepts.BEFORE_PARSING)
assert before_parsing.metadata.desc == "I have a description"
def test_i_first_look_in_local_cache(self):
sheerka, context, concept = self.init_concepts("foo", create_new=True)
sheerka.cache_manager.commit(context)
sheerka.get_by_key(concept.key).new_property = "I have modified the concept in cache"
from_cache = sheerka.get_by_key(concept.key)
assert from_cache is not None
assert from_cache.key == concept.key
assert from_cache.new_property == "I have modified the concept in cache"
# sdp instance is not modified
sheerka.cache_manager.clear()
from_sdp = sheerka.get_by_key(concept.key)
assert from_sdp is not None
assert from_sdp.key == concept.key
assert not hasattr(from_sdp, "new_property")
def test_i_can_retrieve_from_sdp_when_cache_is_reset(self):
sheerka, context, concept = self.init_concepts(Concept("foo", body="1"))
sheerka.cache_manager.commit(context)
sheerka.cache_manager.clear()
sheerka.get_by_key("foo")
assert sheerka.has_key("foo")
# It's also updated when sdp returns more than one element
concept2 = Concept("foo", body="2")
sheerka.create_new_concept(context, concept2)
sheerka.cache_manager.commit(context)
sheerka.cache_manager.clear()
assert len(sheerka.get_by_key("foo")) == 2
assert sheerka.has_key("foo")
# updated when by_id
sheerka.reset_cache()
sheerka.get_by_id("1001")
assert "1001" in sheerka.cache_by_id
assert "foo" not in sheerka.cache_by_key # cache_by_key not updated as "1001" is not the only one
sheerka.cache_manager.clear()
assert sheerka.get_by_id("1001") == concept
assert sheerka.has_id("1001")
def test_i_can_get_by_key_several_times(self):
sheerka = self.get_sheerka()
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="1"))
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="2"))
sheerka.cache_manager.clear()
assert sheerka.get_by_name("foo") == [concept, concept2]
assert sheerka.has_name("foo")
sheerka.reset_cache()
sheerka.get("foo", "1001") # only one element requested. But the cache must be updated with two elements
sheerka.cache_manager.clear()
assert sheerka.get_by_hash(concept.get_definition_hash()) == concept
assert sheerka.has_hash(concept.get_definition_hash())
# let's check it
concepts = sheerka.get("foo")
def test_get_by_key_retrieve_all_elements(self):
sheerka, context, *concepts = self.init_concepts(
Concept("foo", body="1"),
Concept("foo", body="2"),
create_new=True)
sheerka.cache_manager.commit(context)
sheerka.cache_manager.clear()
sheerka.get_by_key("foo", "1001") # I ask only for the one with id = "1001"
# but the two keys are returned
concepts = sheerka.get_by_key("foo")
assert len(concepts) == 2
assert concepts[0].id == "1001"
assert concepts[1].id == "1002"
def test_concept_node_parsing_is_initialized_at_startup(self):
sheerka, context, foo, bar, baz = self.init_concepts(
"foo",
"bar",
Concept("baz", definition="foo"),
create_new=True)
sheerka.cache_manager.commit(context)
assert sheerka.cache_manager.copy(sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY) == {
'bar': ['1002'],
'c:|1001:': ['1003'],
'foo': ['1001']}
assert sheerka.cache_manager.copy(sheerka.RESOLVED_CONCEPTS_BY_FIRST_KEYWORD_ENTRY) == {
'bar': ['1002'],
'foo': ['1001', '1003']
}
sheerka = self.get_sheerka() # another instance
assert sheerka.cache_manager.copy(sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY) == {
'bar': ['1002'],
'c:|1001:': ['1003'],
'foo': ['1001']}
assert sheerka.cache_manager.copy(sheerka.RESOLVED_CONCEPTS_BY_FIRST_KEYWORD_ENTRY) == {
'bar': ['1002'],
'foo': ['1001', '1003']
}
@@ -189,6 +189,12 @@ class EvaluatorAllSuppressFooEntry(EvaluatorAllWithPriority):
class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
@classmethod
def teardown_class(cls):
# At the end of the tests, sheerka singleton instance will be corrupted
# Ask for a new one
TestUsingMemoryBasedSheerka.singleton_instance = None
def test_that_return_values_is_unchanged_when_no_evaluator(self):
sheerka = self.get_sheerka()
sheerka.evaluators = []
+5
View File
@@ -135,6 +135,11 @@ class ListOfNoneParser(BaseTestParser):
class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
@classmethod
def teardown_class(cls):
# At the end of the tests, sheerka singleton instance will be corrupted
# Ask for a new one
TestUsingMemoryBasedSheerka.singleton_instance = None
def test_disabled_parsers_are_not_executed(self):
sheerka = self.get_sheerka()
+15 -14
View File
@@ -22,6 +22,7 @@ class ObjLongProp:
class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("text, expected", [
("Hello world!", "Hello world!\n"),
("%black%%red%%green%%yellow%%reset%", "\x1b[30m\x1b[31m\x1b[32m\x1b[33m\x1b[0m\n"),
@@ -45,7 +46,7 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
def test_i_can_print_concept(self, capsys):
sheerka = self.get_sheerka()
foo = Concept("foo a b").def_prop("a").def_prop("b")
foo = Concept("foo a b").def_var("a").def_var("b")
sheerka.print(foo)
captured = capsys.readouterr()
@@ -53,11 +54,11 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
def test_i_can_use_custom_format(self, capsys):
sheerka = self.get_sheerka()
foo = Concept("foo a b").def_prop("a").def_prop("b").init_key()
foo = Concept("foo a b").def_var("a").def_var("b").init_key()
sheerka.printer_handler.register_custom_printer(
foo,
lambda printer, instr, item: printer.fp(instr, f"foo a={item.a}, b={item.b}"))
foo.set_prop("a", "value a").set_prop("b", "value b")
foo.set_value("a", "value a").set_value("b", "value b")
sheerka.print(foo)
captured = capsys.readouterr()
@@ -66,8 +67,8 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
def test_i_can_print_and_recurse(self, capsys):
sheerka = self.get_sheerka()
level3 = Concept("level3")
level2 = Concept("level2").set_metadata_value(ConceptParts.BODY, level3)
level1 = Concept("level1").set_metadata_value(ConceptParts.BODY, level2)
level2 = Concept("level2").set_value(ConceptParts.BODY, level3)
level1 = Concept("level1").set_value(ConceptParts.BODY, level2)
sheerka.print(level1)
captured = capsys.readouterr()
@@ -90,9 +91,9 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
level31 = Concept("level31")
level32 = Concept("level32")
level33 = Concept("level33")
level21 = Concept("level21").set_metadata_value(ConceptParts.BODY, [level31, level32])
level22 = Concept("level22").set_metadata_value(ConceptParts.BODY, [level33])
level1 = Concept("level1").set_metadata_value(ConceptParts.BODY, [level21, level22])
level21 = Concept("level21").set_value(ConceptParts.BODY, [level31, level32])
level22 = Concept("level22").set_value(ConceptParts.BODY, [level33])
level1 = Concept("level1").set_value(ConceptParts.BODY, [level21, level22])
sheerka.print(level1)
captured = capsys.readouterr()
@@ -111,9 +112,9 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
level31 = Concept("level31")
level32 = Concept("level32")
level33 = Concept("level33")
level21 = Concept("level21").set_metadata_value(ConceptParts.BODY, [level31, level32])
level22 = Concept("level22").set_metadata_value(ConceptParts.BODY, [level33])
level1 = Concept("level1").set_metadata_value(ConceptParts.BODY, [level21, level22])
level21 = Concept("level21").set_value(ConceptParts.BODY, [level31, level32])
level22 = Concept("level22").set_value(ConceptParts.BODY, [level33])
level1 = Concept("level1").set_value(ConceptParts.BODY, [level21, level22])
instructions = FormatInstructions(no_color=True)
explanation = sheerka.new(
@@ -150,9 +151,9 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
def test_i_can_format_concept(self, capsys):
sheerka = self.get_sheerka()
foo = Concept("foo a b").def_prop("a").def_prop("b").init_key()
foo.set_prop("a", "value a").set_prop("b", "value b")
foo.set_metadata_value(ConceptParts.BODY, "body")
foo = Concept("foo a b").def_var("a").def_var("b").init_key()
foo.set_value("a", "value a").set_value("b", "value b")
foo.set_value(ConceptParts.BODY, "body")
sheerka.set_id_if_needed(foo, False)
sheerka.printer_handler.register_format_l(foo, "{id}-{name}-{key}-{body}-{a}-{b}")
+4 -2
View File
@@ -69,13 +69,13 @@ def test_i_can_get_sub_classes():
default_parser = core.utils.get_class("parsers.DefaultParser.DefaultParser")
exact_concept_parser = core.utils.get_class("parsers.ExactConceptParser.ExactConceptParser")
python_parser = core.utils.get_class("parsers.PythonParser.PythonParser")
concept_lexer_parser = core.utils.get_class("parsers.BnfNodeParser.BnfNodeParser")
bnf_node_parser = core.utils.get_class("parsers.BnfNodeParser.BnfNodeParser")
assert base_parser not in sub_classes
assert default_parser in sub_classes
assert exact_concept_parser in sub_classes
assert python_parser in sub_classes
assert concept_lexer_parser in sub_classes
assert bnf_node_parser in sub_classes
@pytest.mark.parametrize("a,b, expected", [
@@ -170,12 +170,14 @@ def test_i_can_str_concept():
assert core.utils.str_concept((None, "id")) == "c:|id:"
assert core.utils.str_concept(("key", None)) == "c:key:"
assert core.utils.str_concept((None, None)) == ""
assert core.utils.str_concept(("key", "id"), skip_key=True) == "c:|id:"
concept = Concept("foo").init_key()
assert core.utils.str_concept(concept) == "c:foo:"
concept.metadata.id = "1001"
assert core.utils.str_concept(concept) == "c:foo|1001:"
assert core.utils.str_concept(concept, skip_key=True) == "c:|1001:"
@pytest.mark.parametrize("text, expected", [
+16 -16
View File
@@ -142,12 +142,12 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
body="print('hello' + a)")
# sanity. Make sure that the concept does not already exist
from_db = context.sheerka.get("hello " + VARIABLE_PREFIX + "0")
from_db = context.sheerka.get_by_key("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")
from_db = context.sheerka.get_by_key("hello " + VARIABLE_PREFIX + "0")
assert from_db.metadata.key == f"hello {VARIABLE_PREFIX}0"
assert from_db.metadata.name == "hello a"
@@ -157,38 +157,38 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
assert from_db.metadata.body == "print('hello' + a)"
assert from_db.metadata.definition == "hello a"
assert from_db.metadata.definition_type == "bnf"
assert len(from_db.metadata.props) == 1
assert from_db.metadata.props[0] == ("a", None)
assert "a" in from_db.props
assert len(from_db.metadata.variables) == 1
assert from_db.metadata.variables[0] == ("a", None)
assert "a" in from_db.values
assert from_db.compiled == {} # ast is not saved in db
def test_i_can_get_props_from_python_node_when_long_name(self):
def test_i_can_get_variables_from_python_node_when_long_name(self):
ret_val = self.get_concept_part("isinstance(a, str)")
context = self.get_context()
assert AddConceptEvaluator.get_props(context.sheerka, ret_val, ["a", "b"]) == ["a"]
assert AddConceptEvaluator.get_variables(context.sheerka, ret_val, ["a", "b"]) == ["a"]
def test_i_cannot_get_props_from_python_node_when_name_has_only_one_token(self):
def test_i_cannot_get_variables_from_python_node_when_name_has_only_one_token(self):
ret_val = self.get_concept_part("isinstance(a, str)")
context = self.get_context()
assert AddConceptEvaluator.get_props(context.sheerka, ret_val, ["a"]) == []
assert AddConceptEvaluator.get_variables(context.sheerka, ret_val, ["a"]) == []
def test_i_can_get_props_from_another_concept(self):
concept = Concept("hello").def_prop("a").def_prop("b")
def test_i_can_get_variables_from_another_concept(self):
concept = Concept("hello").def_var("a").def_var("b")
ret_val = ReturnValueConcept(who="some_parser",
status=True,
value=ParserResultConcept(value=concept))
assert AddConceptEvaluator.get_props(self.get_sheerka(), ret_val, []) == ["a", "b"]
assert AddConceptEvaluator.get_variables(self.get_sheerka(), ret_val, []) == ["a", "b"]
def test_i_can_get_props_from_definition(self):
def test_i_can_get_variables_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_sheerka(), ret_val, []) == ["add", "mult"]
assert AddConceptEvaluator.get_variables(self.get_sheerka(), ret_val, []) == ["add", "mult"]
def test_concept_that_references_itself_is_correctly_created(self):
context = self.get_context()
@@ -200,5 +200,5 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
new_concept = ret_val.body.body
assert new_concept.name == 'foo'
assert new_concept.metadata.body == 'foo'
assert new_concept.props == {}
assert new_concept.metadata.props == []
assert new_concept.values == {}
assert new_concept.metadata.variables == []
@@ -1,14 +1,14 @@
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):
def get_isa_ret_val(concept_name, concept_set_name):
n1 = NameNode(list(Tokenizer(concept_name)))
n2 = NameNode(list(Tokenizer(concept_set_name)))
@@ -30,7 +30,7 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
def test_i_cannot_add_if_the_concept_does_not_exists(self):
context = self.get_context()
ret_val = get_ret_val("foo", "bar")
ret_val = get_isa_ret_val("foo", "bar")
res = AddConceptInSetEvaluator().eval(context, ret_val)
assert not res.status
@@ -43,7 +43,7 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
context.sheerka.set_id_if_needed(foo, False)
context.sheerka.add_in_cache(foo)
ret_val = get_ret_val("foo", "bar")
ret_val = get_isa_ret_val("foo", "bar")
res = AddConceptInSetEvaluator().eval(context, ret_val)
assert not res.status
@@ -52,10 +52,10 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
def test_i_can_add_concept_to_a_set_of_concept(self):
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True)
ret_val = get_ret_val("foo", "bar")
ret_val = get_isa_ret_val("foo", "bar")
res = AddConceptInSetEvaluator().eval(context, ret_val)
foo = sheerka.new("foo") # reload it
foo = sheerka.new("foo") # get a new instance
assert res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
@@ -63,8 +63,7 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
assert context.sheerka.isinset(foo, bar)
assert context.sheerka.isa(foo, bar)
foo_from_sheerka = context.sheerka.get("foo")
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == [bar]
assert foo.get_prop(BuiltinConcepts.ISA) == {bar}
def test_i_can_add_bnf_concept_to_a_set_of_concept(self):
"""
@@ -76,11 +75,11 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
sheerka, context, one, two, foo, bar = self.init_concepts(
"one",
"two",
Concept("foo", definition="(one|two)=a 'plus' (one|two)=b", body="a + b").def_prop("a").def_prop("b"),
Concept("foo", definition="(one|two)=a 'plus' (one|two)=b", body="a + b").def_var("a").def_var("b"),
"bar",
create_new=True)
ret_val = get_ret_val("foo", "bar")
ret_val = get_isa_ret_val("foo", "bar")
res = AddConceptInSetEvaluator().eval(context, ret_val)
foo = sheerka.new("foo") # reload it
@@ -90,8 +89,8 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
assert context.sheerka.isinset(foo, bar)
assert context.sheerka.isa(foo, bar)
foo_from_sheerka = context.sheerka.get("foo")
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == [bar]
foo_from_sheerka = context.sheerka.get_by_key("foo")
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == {bar}
def test_i_can_add_concept_with_a_body_to_a_set_of_concept(self):
context = self.get_context()
@@ -101,23 +100,18 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
bar = Concept("bar")
context.sheerka.create_new_concept(context, bar)
ret_val = get_ret_val("foo", "bar")
ret_val = get_isa_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.create_new_concept(context, foo)
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True)
bar = Concept("bar")
context.sheerka.create_new_concept(context, bar)
ret_val = get_ret_val("foo", "bar")
ret_val = get_isa_ret_val("foo", "bar")
AddConceptInSetEvaluator().eval(context, ret_val)
res = AddConceptInSetEvaluator().eval(context, ret_val)
res = AddConceptInSetEvaluator().eval(context, ret_val) # again
assert not res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_IN_SET)
+12 -12
View File
@@ -24,7 +24,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
concept = Concept(name="foo",
where="True",
pre="2",
post="3").def_prop("a", "4").def_prop("b", "5")
post="3").def_var("a", "4").def_var("b", "5")
evaluator = ConceptEvaluator()
item = self.pretval(concept)
@@ -33,11 +33,11 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
assert result.who == evaluator.name
assert result.status
assert result.value.name == "foo"
assert result.value.get_metadata_value(ConceptParts.WHERE) == True
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.get_value(ConceptParts.WHERE) == True
assert result.value.get_value(ConceptParts.PRE) == 2
assert result.value.get_value(ConceptParts.POST) == 3
assert result.value.get_value("a") == 4
assert result.value.get_value("b") == 5
assert result.value.key == "foo"
assert result.parents == [item]
@@ -48,7 +48,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
body="'I have a value'",
where="True",
pre="2",
post="3").set_prop("a", "4").set_prop("b", "5")
post="3").set_value("a", "4").set_value("b", "5")
evaluator = ConceptEvaluator(return_body=True)
item = self.pretval(concept)
@@ -65,7 +65,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
body="'I have a value'",
where="True",
pre="2",
post="3").set_prop("a", "4").set_prop("b", "5")
post="3").set_value("a", "4").set_value("b", "5")
evaluator = ConceptEvaluator(return_body=False) # which is the default behaviour
item = self.pretval(concept)
@@ -77,11 +77,11 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
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'")
# If we evaluate Concept("foo", body="a").set_value("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'")
context.obj = Concept("other").set_value("foo", "'some_other_value'")
concept = Concept(name="foo")
item = self.pretval(concept)
@@ -95,8 +95,8 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
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())
.def_var("a", "one")
.def_var("b", "two").init_key())
evaluator = ConceptEvaluator()
item = self.pretval(concept_plus)
+1 -1
View File
@@ -75,4 +75,4 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka):
assert len(evaluated) == 1
assert evaluated[0].status
assert evaluated[0].body == [foo, bar, baz]
assert set(evaluated[0].body) == {foo, bar, baz}
+10 -23
View File
@@ -1,20 +1,21 @@
import ast
import pytest
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import Concept, ConceptParts, DoNotResolve
from evaluators.LexerNodeEvaluator import LexerNodeEvaluator
from parsers.BaseNodeParser import SourceCodeNode
from parsers.BnfNodeParser import ConceptNode, BnfNodeParser, StrMatch, UnrecognizedTokensNode
from parsers.BnfNodeParser import ConceptNode, BnfNodeParser, UnrecognizedTokensNode
from parsers.PythonParser import PythonNode
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestLexerNodeEvaluator(TestUsingMemoryBasedSheerka):
def from_parsing(self, context, grammar, expression):
def init_from_concepts(self, context, concepts, expression):
parser = BnfNodeParser()
parser.initialize(context, grammar)
parser.init_from_concepts(context, concepts)
ret_val = parser.parse(context, expression)
assert ret_val.status
@@ -31,18 +32,6 @@ class TestLexerNodeEvaluator(TestUsingMemoryBasedSheerka):
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),
@@ -60,15 +49,13 @@ class TestLexerNodeEvaluator(TestUsingMemoryBasedSheerka):
(ReturnValueConcept("some_name", True, ConceptNode(Concept(), 0, 0)), False),
])
def test_i_can_match(self, ret_val, expected):
context = self.get_context()
sheerka = self.get_sheerka(singleton=True)
context = self.get_context(sheerka)
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")
sheerka, context, foo = self.init_concepts(self.bnf_concept("foo"), singleton=True)
ret_val = self.init_from_concepts(context, [foo], "foo")
evaluator = LexerNodeEvaluator()
result = evaluator.eval(context, ret_val)
@@ -80,7 +67,7 @@ class TestLexerNodeEvaluator(TestUsingMemoryBasedSheerka):
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 == foo
assert return_value.compiled[ConceptParts.BODY] == DoNotResolve("foo")
assert result.parents == [ret_val]
+1 -1
View File
@@ -40,7 +40,7 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("concept", [
Concept("foo"),
Concept("foo", body="2"),
Concept("foo").set_prop("prop", "'a'"),
Concept("foo").def_var("prop", "'a'"),
Concept("foo", body="bar")
])
def test_i_cannot_eval_simple_concept(self, concept):
+129 -161
View File
@@ -1,15 +1,15 @@
import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property, simplec
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, simplec
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
from parsers.BaseNodeParser import SyaAssociativity
from parsers.BnfNodeParser import Sequence, StrMatch, OrderedChoice, Optional, ConceptExpression
from sdp.sheerkaDataProvider import SheerkaDataProvider
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaNonReg(TestUsingFileBasedSheerka):
class TestSheerkaNonRegMemory(TestUsingMemoryBasedSheerka):
def init_scenario(self, init_expressions):
sheerka = self.get_sheerka()
@@ -105,10 +105,10 @@ as:
expected = self.get_default_concept()
expected.metadata.id = "1001"
expected.metadata.desc = None
expected.metadata.props = [("a", None), ("b", None)]
expected.metadata.variables = [("a", None), ("b", None)]
expected.init_key()
sheerka = self.get_sheerka()
sheerka = self.get_sheerka(cache_only=False)
res = sheerka.evaluate_user_input(text)
assert len(res) == 1
@@ -120,21 +120,15 @@ as:
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_origin()))
# cache is up to date
assert sheerka.has_key(concept_saved.key)
assert sheerka.has_id(concept_saved.id)
assert sheerka.has_name(concept_saved.name)
assert sheerka.has_hash(concept_saved.get_definition_hash())
assert sheerka.cache_manager.copy(sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY) == {'+': ['1001']}
def test_i_can_def_several_concepts(self):
sheerka = self.get_sheerka(use_dict=False)
sheerka.evaluate_user_input("def concept foo")
sheerka = self.get_sheerka(use_dict=False)
res = sheerka.evaluate_user_input("def concept bar")
assert len(res) == 1
assert res[0].status
assert res[0].body.body.id == "1002"
# sdp is up to date
assert sheerka.sdp.exists(sheerka.CONCEPTS_BY_KEY_ENTRY, expected.key)
def test_i_can_evaluate_def_concept_part_when_one_part_is_a_ref_of_another_concept(self):
"""
@@ -145,11 +139,11 @@ as:
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")
concept_a_plus_b = Concept(name="a plus b").def_var("a").def_var("b").init_key()
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 = Concept(name="a xx b", body="a plus b").def_var("a").def_var("b").init_key()
expected.metadata.id = "1001"
assert len(res) == 1
@@ -161,10 +155,7 @@ as:
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_origin()))
assert sheerka.has_key(concept_saved.key)
def test_i_cannot_evaluate_the_same_def_concept_twice(self):
text = """
@@ -202,7 +193,7 @@ as:
def test_i_can_recognize_concept_with_variable(self):
sheerka = self.get_sheerka()
concept_hello = Concept(name="hello a").def_prop("a")
concept_hello = Concept(name="hello a").def_var("a")
concept_foo = Concept(name="foo")
sheerka.add_in_cache(concept_hello)
sheerka.add_in_cache(concept_foo)
@@ -212,15 +203,15 @@ as:
assert len(res) == 1
assert res[0].status
assert sheerka.isinstance(return_value, concept_hello)
assert return_value.metadata.props[0] == ('a', "foo")
assert return_value.metadata.variables[0] == ('a', "foo")
# sanity check
evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), return_value)
assert evaluated.props["a"].value == concept_foo
assert evaluated.get_value("a") == concept_foo
def test_i_can_recognize_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"))
hello_a = sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_var("a"))
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
res = sheerka.evaluate_user_input("hello foo")
@@ -232,15 +223,14 @@ as:
evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value)
assert evaluated.body == "hello foo"
assert evaluated.metadata.is_evaluated
assert evaluated.props["a"].value == simplec("foo", "foo")
assert evaluated.props["a"].value.metadata.is_evaluated
assert evaluated.get_value("a") == simplec("foo", "foo")
assert evaluated.get_value("a").metadata.is_evaluated
def test_i_can_recognize_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'"))
self.create_concept_lite(sheerka, Concept(name="hello a", body="'hello ' + a"), variables=["a"])
self.create_concept_lite(sheerka, Concept(name="hello foo", body="'hello foo'"))
self.create_concept_lite(sheerka, Concept(name="foo", body="'foo'"))
res = sheerka.evaluate_user_input("hello foo")
assert len(res) == 1
@@ -250,10 +240,9 @@ as:
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'"))
self.create_concept_lite(sheerka, Concept(name="hello a", body="'hello ' + a"), variables=["a"])
self.create_concept_lite(sheerka, Concept(name="hello foo", body="'hello foo'"))
self.create_concept_lite(sheerka, Concept(name="foo", body="'another value'"))
res = sheerka.evaluate_user_input("hello foo")
assert len(res) == 1
@@ -270,8 +259,8 @@ as:
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"))
sheerka.create_new_concept(context, Concept(name="hello a", body="'hello ' + a").def_var("a"))
sheerka.create_new_concept(context, Concept(name="hello b", body="'hello ' + b").def_var("b"))
res = sheerka.evaluate_user_input("hello 'foo'")
assert len(res) == 1
@@ -283,42 +272,12 @@ as:
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
sheerka.create_new_concept(context, Concept(name="concepts", body="sheerka.concepts()"))
sheerka.create_new_concept(context, Concept(name="concepts", body="sheerka.test()"))
res = sheerka.evaluate_user_input("eval concepts")
assert len(res) == 1
assert res[0].status
assert isinstance(res[0].value, list)
def test_i_can_create_concept_with_bnf_definition(self):
sheerka = self.get_sheerka(use_dict=False, skip_builtins_in_db=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(
ConceptExpression(a, rule_name="a"),
Optional(Sequence(StrMatch("plus"), ConceptExpression(saved_concept, rule_name="plus"))))
assert saved_definitions["c:plus|1001:"] == "(c:a:=a ('plus' c:plus|1001:=plus)?)"
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
assert res[0].value == sheerka.test()
def test_i_can_recognize_bnf_definitions(self):
sheerka = self.get_sheerka()
@@ -344,41 +303,11 @@ as:
assert sheerka.isinstance(return_value, concept_b)
# sanity check
evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), return_value)
evaluated = sheerka.evaluate_concept(self.get_context(sheerka=sheerka, eval_body=True), return_value)
assert evaluated.body == "one three"
assert evaluated.metadata.is_evaluated
assert evaluated.props["a"] == Property("a", sheerka.new(concept_a.key, body="one").init_key())
assert evaluated.props["a"].value.metadata.is_evaluated
def test_i_can_recognize_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(use_dict=False)
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' 'two'")[0].body.body
res = self.get_sheerka(use_dict=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(use_dict=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(use_dict=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)
evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value)
assert evaluated.body == "one two three"
assert evaluated.props["a"] == Property("a", sheerka.new(concept_a.key, body="one two").init_key())
assert evaluated.get_value("a") == sheerka.new(concept_a.key, body="one").init_key()
assert evaluated.get_value("a").metadata.is_evaluated
@pytest.mark.parametrize("user_input", [
"def concept greetings from def hello a where a",
@@ -393,7 +322,7 @@ as:
assert res[0].status
concept_found = res[0].value
assert sheerka.isinstance(concept_found, greetings)
assert concept_found.get_prop("a") == "foo"
assert concept_found.get_value("a") == "foo"
assert concept_found.metadata.need_validation
res = sheerka.evaluate_user_input("greetings")
@@ -401,10 +330,9 @@ as:
assert res[0].status
concept_found = res[0].value
assert sheerka.isinstance(concept_found, greetings)
assert concept_found.get_prop("a") is None
assert concept_found.get_value("a") is None
assert not concept_found.metadata.need_validation
# @pytest.mark.xfail
@pytest.mark.parametrize("desc, definitions", [
("Simple form", [
"def concept one as 1",
@@ -452,7 +380,7 @@ as:
assert len(res) == 1
assert res[0].status
assert sheerka.isinstance(res[0].body, "twenties")
assert sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].body).body == 21
assert sheerka.evaluate_concept(self.get_context(sheerka=sheerka, eval_body=True), res[0].body).body == 21
res = sheerka.evaluate_user_input("twenty one + 1")
assert len(res) == 1
@@ -479,7 +407,6 @@ as:
assert res[0].status
assert res[0].body == 23
# @pytest.mark.xfail
def test_i_can_mix_bnf_and_isa(self):
"""
if 'one' isa 'number, twenty number should be recognized
@@ -497,7 +424,7 @@ as:
assert len(res) == 1
assert res[0].status
assert sheerka.isinstance(res[0].body, "twenties")
assert sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value).body == 21
assert sheerka.evaluate_concept(self.get_context(sheerka=sheerka, eval_body=True), res[0].value).body == 21
res = sheerka.evaluate_user_input("twenty one + 1")
assert len(res) == 1
@@ -524,7 +451,7 @@ as:
assert res[0].status
assert res[0].body == 23
def test_i_can_mix_bnf_and_isa_when_concept_other_case(self):
def test_i_can_mix_bnf_and_isa_2(self):
sheerka = self.get_sheerka()
init = [
@@ -544,7 +471,6 @@ as:
assert res[0].status
assert res[0].body == 21
# @pytest.mark.xfail
def test_i_can_use_concepts_defined_with_from(self):
sheerka = self.get_sheerka()
@@ -656,31 +582,6 @@ as:
assert res[0].status
assert res[0].body == 3
@pytest.mark.xfail
def test_i_can_recognize_composition_of_concept(self):
sheerka = self.get_sheerka()
definitions = [
"def concept little a where a",
"def concept 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")
@@ -779,36 +680,35 @@ as:
sheerka.evaluate_user_input(exp)
res = sheerka.evaluate_user_input("twenty one")
assert len(res) == 1 and res[0].status and sheerka.isinstance(res[0].body, "twenties")
assert len(res) == 1
assert res[0].status
assert sheerka.isinstance(res[0].body, "twenties")
res = sheerka.evaluate_user_input("eval twenty one")
assert len(res) == 1 and res[0].status and res[0].body == 21
assert len(res) == 1
assert res[0].status
assert res[0].body == 21
res = sheerka.evaluate_user_input("twenty two")
assert len(res) == 1 and res[0].status and sheerka.isinstance(res[0].body, "twenties")
assert len(res) == 1
assert res[0].status
assert sheerka.isinstance(res[0].body, "twenties")
res = sheerka.evaluate_user_input("eval twenty two")
assert len(res) == 1 and res[0].status and res[0].body == 22
assert len(res) == 1
assert res[0].status
assert res[0].body == 22
res = sheerka.evaluate_user_input("twenty three")
assert len(res) == 1
assert not res[0].status
assert sheerka.isinstance(res[0].body, BuiltinConcepts.WHERE_CLAUSE_FAILED)
assert sheerka.isinstance(res[0].body, BuiltinConcepts.MULTIPLE_ERRORS)
assert str(BuiltinConcepts.WHERE_CLAUSE_FAILED) in [error.key for error in sheerka.get_error(res[0].body.body)]
res = sheerka.evaluate_user_input("eval twenty three")
assert len(res) == 1
assert not res[0].status
assert sheerka.isinstance(res[0].body, BuiltinConcepts.WHERE_CLAUSE_FAILED)
# def test_i_can_detect_when_only_one_evaluator_is_in_error(self):
# sheerka = self.get_sheerka()
#
# sheerka.evaluate_user_input("def concept 1 as one")
# res = sheerka.evaluate_user_input("eval 1")
# assert len(res) == 1
# assert not res[0].status
# assert sheerka.isinstance(res[0].body, BuiltinConcepts.CONCEPT_EVAL_ERROR)
assert str(BuiltinConcepts.WHERE_CLAUSE_FAILED) in [error.key for error in sheerka.get_error(res[0].body.body)]
def test_i_can_manage_some_type_of_infinite_recursion(self):
sheerka = self.get_sheerka()
@@ -862,7 +762,7 @@ as:
assert not res[0].status
assert sheerka.isinstance(res[0].body, BuiltinConcepts.WHERE_CLAUSE_FAILED)
@pytest.mark.xfail
@pytest.mark.skip("Not ready for that")
def test_i_can_manage_missing_variables_from_bnf_parsing(self):
definitions = [
"def concept one as 1",
@@ -894,8 +794,8 @@ as:
assert len(res) == 1
assert res[0].status
twenties = sheerka.get("twenties")
number = sheerka.get("number")
twenties = sheerka.get_by_key("twenties")
number = sheerka.get_by_key("number")
assert sheerka.isa(twenties, number)
def test_i_can_mix_sya_concepts_and_bnf_concept(self):
@@ -910,9 +810,9 @@ as:
sheerka = self.init_scenario(definitions)
context = self.get_context(sheerka)
sheerka.set_sya_def(context, [
(sheerka.get("mult").id, 20, SyaAssociativity.Right),
(sheerka.get("plus").id, 10, SyaAssociativity.Right),
sheerka.force_sya_def(context, [
(sheerka.get_by_name("mult").id, 20, SyaAssociativity.Right),
(sheerka.get_by_name("plus").id, 10, SyaAssociativity.Right),
])
res = sheerka.evaluate_user_input("eval one plus two mult three")
@@ -954,3 +854,71 @@ as:
assert len(res) == 1
assert res[0].status
assert res[0].body == 64
class TestSheerkaNonRegFile(TestUsingFileBasedSheerka):
def test_i_can_def_several_concepts(self):
sheerka = self.get_sheerka()
sheerka.evaluate_user_input("def concept foo")
sheerka = self.get_sheerka()
res = sheerka.evaluate_user_input("def concept bar")
assert len(res) == 1
assert res[0].status
assert res[0].body.body.id == "1002"
def test_i_can_create_concept_with_bnf_definition(self):
sheerka = self.get_sheerka()
concept_a = self.bnf_concept("a", expression=OrderedChoice(StrMatch("one"), StrMatch("two")))
sheerka.create_new_concept(self.get_context(sheerka), concept_a)
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(sheerka.CONCEPTS_BY_KEY_ENTRY, "plus")
assert saved_concept.key == "plus"
assert saved_concept.metadata.definition == "a ('plus' plus)?"
assert "a" in saved_concept.values
assert "plus" in saved_concept.values
expected_bnf = Sequence(
ConceptExpression(concept_a, rule_name="a"),
Optional(Sequence(StrMatch("plus"), ConceptExpression("plus"))))
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.values
assert "plus" in new_concept.values
def test_i_can_recognize_bnf_definitions_from_separate_instances(self):
sheerka = self.get_sheerka()
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' 'two'")[0].body.body
sheerka = self.get_sheerka()
res = sheerka.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
sheerka = self.get_sheerka()
res = sheerka.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().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)
evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value)
assert evaluated.body == "one two three"
assert evaluated.get_value("a") == sheerka.new(concept_a.key, body="one two").init_key()
+63 -14
View File
@@ -1,6 +1,7 @@
from core.concept import CC, Concept
from core.concept import CC, Concept, ConceptParts, DoNotResolve
from core.tokenizer import Tokenizer, TokenKind, Token
from parsers.BaseNodeParser import scnode, utnode, cnode, SCWC, CNC, short_cnode, SourceCodeWithConceptNode, CN, UTN
from parsers.BaseNodeParser import scnode, utnode, cnode, SCWC, CNC, short_cnode, SourceCodeWithConceptNode, CN, UTN, \
SCN
from parsers.SyaNodeParser import SyaConceptParserHelper
@@ -43,7 +44,16 @@ def compute_debug_array(res):
return to_compare
def get_node(concepts_map, expression_as_tokens, sub_expr, concept_key=None, skip=0, is_bnf=False, sya=False):
def get_node(
concepts_map,
expression_as_tokens,
sub_expr,
concept_key=None,
skip=0,
is_bnf=False,
sya=False,
init_empty_body=False,
exclude_body=False):
"""
Tries to find sub in expression
When found, transform it to its correct type
@@ -54,6 +64,8 @@ def get_node(concepts_map, expression_as_tokens, sub_expr, concept_key=None, ski
:param skip: number of occurrences of sub_expr to skip
:param is_bnf: True if the concept to search is a bnf definition
:param sya: Return SyaConceptParserHelper instead of a ConceptNode when needed
:param init_empty_body: if True adds the source in the body (actually in compiled.BODY)
:param exclude_body: Ask to not compare body
:return:
"""
if sub_expr == "')'":
@@ -80,23 +92,38 @@ def get_node(concepts_map, expression_as_tokens, sub_expr, concept_key=None, ski
content = [get_node(concepts_map, expression_as_tokens, c, sya=sya) for c in sub_expr.content]
return SourceCodeWithConceptNode(first, last, content).pseudo_fix_source()
if isinstance(sub_expr, SCN):
node = get_node(concepts_map, expression_as_tokens, sub_expr.source, sya=sya)
sub_expr.fix_pos(node)
return sub_expr
if isinstance(sub_expr, (CNC, CC, CN)):
concept_node = get_node(
concepts_map,
expression_as_tokens,
sub_expr.source or sub_expr.concept_key,
sub_expr.concept_key, sya=sya)
if not hasattr(concept_node, "concept"):
raise Exception(f"'{sub_expr.concept_key}' is not a concept. Check your map.")
concept_found = concept_node.concept
sub_expr.concept_key = concept_found.key
sub_expr.concept = concept_found
sub_expr.fix_pos((concept_node.start, concept_node.end if hasattr(concept_node, "end") else concept_node.start))
if hasattr(sub_expr, "compiled"):
for k, v in sub_expr.compiled.items():
node = get_node(concepts_map, expression_as_tokens, v, sya=sya) # need to get start and end positions
new_value = CC(Concept().update_from(concepts_map[v])) if (isinstance(v, str) and v in concepts_map) \
else node
node = get_node(concepts_map, expression_as_tokens, v, sya=sya, exclude_body=exclude_body) # need to get start and end positions
if isinstance(v, str) and v in concepts_map:
new_value_concept = concepts_map[v]
new_value = CC(Concept().update_from(new_value_concept), exclude_body=exclude_body)
if init_empty_body:
init_body(new_value, concept_found, v)
else:
new_value = node
sub_expr.compiled[k] = new_value
sub_expr.fix_pos(node)
if init_empty_body:
init_body(sub_expr, concept_found, sub_expr.source)
if hasattr(sub_expr, "fix_source"):
sub_expr.fix_source(expression_as_tokens[sub_expr.start: sub_expr.end + 1])
@@ -119,32 +146,54 @@ def get_node(concepts_map, expression_as_tokens, sub_expr, concept_key=None, ski
# special case of python source code
if "+" in sub_expr and sub_expr.strip() != "+":
return scnode(start, start + length - 1, sub_expr)
return SCN(sub_expr, start, start + length - 1)
# try to match one of the concept from the map
concept_key = concept_key or sub_expr
concept_found = concepts_map.get(concept_key, None)
if concept_found:
concept_found = Concept().update_from(concept_found) # make a copy when massively used in tests
if not sya or len(concept_found.metadata.props) == 0 or is_bnf:
# if it's an atom, then return a ConceptNode
return CN(concept_found, start, start + length - 1, source=sub_expr)
else:
# else return a ParserHelper
if sya and len(concept_found.metadata.variables) > 0 and not is_bnf:
return SyaConceptParserHelper(concept_found, start)
elif init_empty_body:
node = CNC(concept_found, start, start + length - 1, source=sub_expr, exclude_body=exclude_body)
init_body(node, concept_found, sub_expr)
return node
else:
return CN(concept_found, start, start + length - 1, source=sub_expr)
else:
# else an UnrecognizedTokensNode
return utnode(start, start + length - 1, sub_expr)
def compute_expected_array(concepts_map, expression, expected, sya=False):
def init_body(item, concept, value):
if "body" in item.compiled:
item.compiled[ConceptParts.BODY] = item.compiled["body"]
del (item.compiled["body"])
return
if not concept or concept.metadata.body or ConceptParts.BODY in item.compiled:
return
item.compiled[ConceptParts.BODY] = DoNotResolve(value)
def compute_expected_array(concepts_map, expression, expected, sya=False, init_empty_body=False, exclude_body=False):
"""
Computes a simple but sufficient version of the result of infix_to_postfix()
:param concepts_map:
:param expression:
:param expected:
:param sya: if true, generate an SyaConceptParserHelper instead of a cnode
:param init_empty_body: if True adds the source in the body (actually in compiled.BODY)
:param exclude_body: do not include ConceptParts.BODY in comparison
:return:
"""
expression_as_tokens = [token.value for token in Tokenizer(expression) if token.type != TokenKind.EOF]
return [get_node(concepts_map, expression_as_tokens, sub_expr, sya=sya) for sub_expr in expected]
return [get_node(
concepts_map,
expression_as_tokens,
sub_expr,
sya=sya,
init_empty_body=init_empty_body,
exclude_body=exclude_body) for sub_expr in expected]
+44 -21
View File
@@ -2,18 +2,21 @@ import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from parsers.AtomNodeParser import AtomNodeParser
from parsers.BaseNodeParser import cnode, utnode, CNC
from parsers.BaseNodeParser import cnode, utnode, CNC, scnode, SCN
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array
class TestAtomsParser(TestUsingMemoryBasedSheerka):
def init_parser(self, concepts_map, **kwargs):
sheerka, context, *updated_concepts = self.init_concepts(singleton=True, *concepts_map.values(), **kwargs)
def init_parser(self, my_map, create_new=False, singleton=True):
sheerka, context, *updated_concepts = self.init_concepts(
*my_map.values(),
create_new=create_new,
singleton=singleton)
parser = AtomNodeParser()
parser.initialize(context, updated_concepts)
parser.init_from_concepts(context, updated_concepts)
return sheerka, context, parser
@@ -34,7 +37,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
concepts_map = {
"foo": Concept("foo"),
"bar": Concept("bar"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map)
@@ -57,7 +60,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
concepts_map = {
"foo bar": Concept("foo bar"),
"one two three": Concept("one two three"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map)
@@ -75,27 +78,27 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
("foo bar suffixed one", False, ["foo bar", " suffixed ", "one"]),
("foo bar one prefixed", False, ["foo bar", "one", " prefixed"]),
("foo bar one infix two", False, ["foo bar", "one", " infix ", "two"]),
("foo bar 1 + 1", True, ["foo bar", " 1 + 1"]),
("foo bar 1 + 1", False, ["foo bar", " 1 + 1"]),
("foo bar twenty one", False, ["foo bar", " twenty ", "one"]),
("foo bar x$!#", False, ["foo bar", " x$!#"]),
("suffixed one foo bar", False, ["suffixed ", "one", "foo bar"]),
("one prefixed foo bar", False, ["one", " prefixed ", "foo bar"]),
("one infix two foo bar", False, ["one", " infix ", "two", "foo bar"]),
("1 + 1 foo bar", True, ["1 + 1 ", "foo bar"]),
("1 + 1 foo bar", False, ["1 + 1 ", "foo bar"]),
("twenty one foo bar", False, ["twenty ", "one", "foo bar"]),
("x$!# foo bar", False, ["x$!# ", "foo bar"]),
("func(one)", False, ["func(", "one", ")"]),
])
def test_i_can_parse_when_unrecognized(self, text, expected_status, expected):
concepts_map = {
"prefixed": Concept("a prefixed").def_prop("a"),
"suffixed": Concept("prefixed a").def_prop("a"),
"infix": Concept("a infix b").def_prop("a").def_prop("b"),
"prefixed": Concept("a prefixed").def_var("a"),
"suffixed": Concept("prefixed a").def_var("a"),
"infix": Concept("a infix b").def_var("a").def_var("b"),
"foo bar": Concept("foo bar"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map)
@@ -116,13 +119,13 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_parse_when_surrounded_by_spaces(self, text, expected_status, expected):
concepts_map = {
"prefixed": Concept("a prefixed").def_prop("a"),
"suffixed": Concept("prefixed a").def_prop("a"),
"infix": Concept("a infix b").def_prop("a").def_prop("b"),
"prefixed": Concept("a prefixed").def_var("a"),
"suffixed": Concept("prefixed a").def_var("a"),
"infix": Concept("a infix b").def_var("a").def_var("b"),
"foo bar": Concept("foo bar"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map)
@@ -201,8 +204,8 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
])
def test_i_cannot_parse_concepts_with_property_or_bnf_or_unrecognized(self, text):
concepts_map = {
"foo": Concept("foo a").def_prop("a"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_prop("unit"),
"foo": Concept("foo a").def_var("a"),
"twenties": Concept("twenties", definition="'twenty' ('one'|'two')=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map)
@@ -221,12 +224,12 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_parse_when_unrecognized_yield_multiple_values(self, text, expected):
concepts_map = {
"hello1": Concept("hello a").def_prop("a"),
"hello2": Concept("hello b").def_prop("b"),
"hello1": Concept("hello a").def_var("a"),
"hello2": Concept("hello b").def_var("b"),
"bar": Concept("bar")
}
sheerka, context, parser = self.init_parser(concepts_map, create_new=True)
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, singleton=False)
list_of_res = parser.parse(context, text)
assert len(list_of_res) == len(expected)
@@ -239,3 +242,23 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, text, expected[1])
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
@pytest.mark.parametrize("text, expected", [
("1 + twenty one", [SCN("1 + twenty "), "one"]),
("one + twenty one", ["one", SCN(" + twenty "), ("one", 1)]),
])
def test_source_code_found_must_be_considered_as_potential_false_positive(self, text, expected):
concepts_map = {
"one": Concept("one")
}
sheerka, context, parser = self.init_parser(concepts_map)
res = parser.parse(context, text)
wrapper = res.body
lexer_nodes = res.body.body
assert not res.status
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
+257
View File
@@ -0,0 +1,257 @@
import pytest
from core.concept import Concept
from parsers.BaseNodeParser import BaseNodeParser
from parsers.BnfNodeParser import StrMatch, Sequence, OrderedChoice, Optional, ZeroOrMore, OneOrMore, ConceptExpression
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestBaseNodeParser(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("concept, expected", [
(Concept("foo"), {"foo": ["1001"]}),
(Concept("foo a").def_var("a"), {"foo": ["1001"]}),
(Concept("a b foo").def_var("a").def_var("b"), {"foo": ["1001"]}),
])
def test_i_can_get_concepts_by_first_keyword(self, concept, expected):
"""
Given a concept, i can find the first know token
example:
Concept("a foo b").def_var("a").def_var("b")
'a' and 'b' are properties
the first 'real' token is foo
:return:
"""
sheerka, context, *updated = self.init_concepts(concept)
res = BaseNodeParser.get_concepts_by_first_keyword(context, updated)
assert res.status
assert res.body == expected
@pytest.mark.parametrize("bnf, expected", [
(StrMatch("foo"), {"foo": ["1002"]}),
(StrMatch("bar"), {"bar": ["1002"]}),
(ConceptExpression("bar"), {"c:|1001:": ["1002"]}),
(Sequence(StrMatch("foo"), StrMatch("bar")), {"foo": ["1002"]}),
(Sequence(StrMatch("foo"), ConceptExpression("bar")), {"foo": ["1002"]}),
(Sequence(ConceptExpression("bar"), StrMatch("foo")), {"c:|1001:": ["1002"]}),
(OrderedChoice(StrMatch("foo"), StrMatch("bar")), {"foo": ["1002"], "bar": ["1002"]}),
(Optional(StrMatch("foo")), {"foo": ["1002"]}),
(ZeroOrMore(StrMatch("foo")), {"foo": ["1002"]}),
(OneOrMore(StrMatch("foo")), {"foo": ["1002"]}),
])
def test_i_can_get_concepts_by_first_keyword_with_bnf(self, bnf, expected):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
bar = Concept("bar").init_key()
sheerka.set_id_if_needed(bar, False)
sheerka.add_in_cache(bar)
concept = Concept("foo").init_key()
concept.bnf = bnf
sheerka.set_id_if_needed(concept, False)
res = BaseNodeParser.get_concepts_by_first_keyword(context, [concept])
assert res.status
assert res.body == expected
def test_i_can_get_concepts_by_first_keyword_when_multiple_concepts(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
bar = Concept("bar").init_key()
sheerka.set_id_if_needed(bar, False)
sheerka.add_in_cache(bar)
baz = Concept("baz").init_key()
sheerka.set_id_if_needed(baz, False)
sheerka.add_in_cache(baz)
foo = Concept("foo").init_key()
foo.bnf = OrderedChoice(ConceptExpression("bar"), ConceptExpression("baz"), StrMatch("qux"))
sheerka.set_id_if_needed(foo, False)
res = BaseNodeParser.get_concepts_by_first_keyword(context, [bar, baz, foo])
assert res.status
assert res.body == {
"bar": ["1001"],
"baz": ["1002"],
"c:|1001:": ["1003"],
"c:|1002:": ["1003"],
"qux": ["1003"],
}
def test_i_can_get_concepts_by_first_keyword_using_sheerka(self):
sheerka, context, *updated = self.init_concepts(
"one",
"two",
Concept("twenty", definition="'twenty' (one|two)"),
create_new=True
)
bar = Concept("bar").init_key()
sheerka.set_id_if_needed(bar, False)
sheerka.add_in_cache(bar)
foo = Concept("foo").init_key()
foo.bnf = OrderedChoice(ConceptExpression("one"), ConceptExpression("bar"), StrMatch("qux"))
sheerka.set_id_if_needed(foo, False)
res = BaseNodeParser.get_concepts_by_first_keyword(context, [bar, foo], use_sheerka=True)
assert res.status
assert res.body == {
"one": ["1001"],
"two": ["1002"],
"twenty": ["1003"],
"bar": ["1004"],
"c:|1001:": ["1005"],
"c:|1004:": ["1005"],
"qux": ["1005"],
}
def test_i_can_resolve_concepts_by_first_keyword(self):
sheerka, context, *updated = self.init_concepts(
"one",
Concept("two", definition="one"),
Concept("three", definition="two"),
create_new=False
)
concepts_by_first_keywords = {
"one": ["1001"],
"c:|1001:": ["1002"],
"c:|1002:": ["1003"],
}
resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(context, concepts_by_first_keywords)
assert resolved_ret_val.status
assert resolved_ret_val.body == {
"one": ["1001", "1002", "1003"],
}
def test_i_can_resolve_when_concepts_are_sets(self):
sheerka, context, one, two, three, number, foo = self.init_concepts(
"one",
"two",
"three",
"number",
Concept("foo", definition="number three"),
create_new=True # mandatory because set_isa() needs it
)
sheerka.set_isa(context, sheerka.new("one"), number)
sheerka.set_isa(context, sheerka.new("two"), number)
cbfk = BaseNodeParser.get_concepts_by_first_keyword(context, [one, two, three, number, foo]).body
resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(context, cbfk)
assert resolved_ret_val.status
assert resolved_ret_val.body == {
"one": ["1001", "1005"],
"two": ["1002", "1005"],
"three": ["1003"],
"number": ["1004"],
}
def test_concepts_are_defined_once(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
good = self.create_concept_lite(sheerka, "good")
foo = self.create_concept_lite(sheerka, "foo", bnf=ConceptExpression("good"))
bar = self.create_concept_lite(sheerka, "bar", bnf=ConceptExpression("good"))
baz = self.create_concept_lite(sheerka, "baz", bnf=OrderedChoice(
ConceptExpression("foo"),
ConceptExpression("bar")))
concepts_by_first_keywords = BaseNodeParser.get_concepts_by_first_keyword(
context, [good, foo, bar, baz]).body
resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(context, concepts_by_first_keywords)
assert resolved_ret_val.status
assert resolved_ret_val.body == {
"good": ["1001", "1002", "1003", "1004"],
}
def test_i_can_resolve_more_complex(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
a = self.create_concept_lite(sheerka, "a", bnf=Sequence("one", "two"))
b = self.create_concept_lite(sheerka, "b", bnf=Sequence(ConceptExpression("a"), "two"))
concepts_by_first_keywords = BaseNodeParser.get_concepts_by_first_keyword(
context, [a, b]).body
resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(context, concepts_by_first_keywords)
assert resolved_ret_val.status
assert resolved_ret_val.body == {
"one": ["1001", "1002"],
}
# def tests_i_can_detect_direct_recursion(self):
# sheerka = self.get_sheerka()
# good = self.get_concept(sheerka, "good")
# foo = self.get_concept(sheerka, "foo", ConceptExpression("bar"))
# bar = self.get_concept(sheerka, "bar", ConceptExpression("foo"))
#
# concepts_by_first_keywords = BaseNodeParser.get_concepts_by_first_keyword(sheerka, [good, foo, bar]).body
#
# resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(sheerka, concepts_by_first_keywords)
# assert resolved_ret_val.status
# assert resolved_ret_val.body == {
# "good": ["1001"],
# BuiltinConcepts.CHICKEN_AND_EGG: ["1002", "1003"]
# }
#
# def test_i_can_detect_indirect_infinite_recursion(self):
# sheerka = self.get_sheerka()
# good = self.get_concept(sheerka, "good")
# one = self.get_concept(sheerka, "one", ConceptExpression("two"))
# two = self.get_concept(sheerka, "two", ConceptExpression("three"))
# three = self.get_concept(sheerka, "three", ConceptExpression("two"))
#
# concepts_by_first_keywords = BaseNodeParser.get_concepts_by_first_keyword(sheerka, [good, one, two, three]).body
#
# resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(sheerka, concepts_by_first_keywords)
# assert resolved_ret_val.status
# assert resolved_ret_val.body == {
# "good": ["1001"],
# BuiltinConcepts.CHICKEN_AND_EGG: ["1002", "1004", "1003"]
# }
#
# def test_i_can_detect_infinite_recursion_from_ordered_choice(self):
# sheerka = self.get_sheerka()
# good = self.get_concept(sheerka, "good")
# one = self.get_concept(sheerka, "one", ConceptExpression("two"))
# two = self.get_concept(sheerka, "two", OrderedChoice(ConceptExpression("one"), ConceptExpression("two")))
#
# concepts_by_first_keywords = BaseNodeParser.get_concepts_by_first_keyword(sheerka, [good, one, two]).body
#
# resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(sheerka, concepts_by_first_keywords)
# assert resolved_ret_val.status
# assert resolved_ret_val.body == {
# "good": ["1001"],
# BuiltinConcepts.CHICKEN_AND_EGG: ["1002", "1003"]
# }
#
# def test_i_can_detect_infinite_recursion_with_sequence(self):
# sheerka = self.get_sheerka()
# good = self.get_concept(sheerka, "good")
# one = self.get_concept(sheerka, "one", ConceptExpression("two"))
# two = self.get_concept(sheerka, "two", Sequence(StrMatch("yes"), ConceptExpression("one")))
#
# concepts_by_first_keywords = BaseNodeParser.get_concepts_by_first_keyword(sheerka, [good, one, two]).body
#
# resolved_ret_val = BaseNodeParser.resolve_concepts_by_first_keyword(sheerka, concepts_by_first_keywords)
# assert resolved_ret_val.status
# assert resolved_ret_val.body == {
# "good": ["1001"],
# BuiltinConcepts.CHICKEN_AND_EGG: ["1002", "1003"]
# }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+32 -38
View File
@@ -1,13 +1,12 @@
import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.concept import Concept, DEFINITION_TYPE_BNF
from core.tokenizer import Tokenizer, TokenKind, LexerError, Token
from parsers.BaseNodeParser import cnode
from parsers.BaseParser import UnexpectedTokenErrorNode
from parsers.BnfParser import BnfParser, UnexpectedEndOfFileError
from parsers.BnfNodeParser import StrMatch, Optional, ZeroOrMore, OrderedChoice, Sequence, OneOrMore, \
BnfNodeParser, ConceptExpression
from parsers.BnfParser import BnfParser, UnexpectedEndOfFileError
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@@ -27,6 +26,12 @@ eof_token = Token(TokenKind.EOF, "", 0, 0, 0)
class TestBnfParser(TestUsingMemoryBasedSheerka):
def init_parser(self, *concepts):
sheerka, context, *updated = self.init_concepts(*concepts, singleton=True)
parser = BnfParser()
return sheerka, context, parser, *updated
@pytest.mark.parametrize("expression, expected", [
("'str'", StrMatch("str")),
("1", StrMatch("1")),
@@ -80,8 +85,9 @@ class TestBnfParser(TestUsingMemoryBasedSheerka):
OneOrMore(StrMatch("b"), rule_name="y"), rule_name="z")),
])
def test_i_can_parse_regex(self, expression, expected):
parser = BnfParser()
res = parser.parse(self.get_context(), Tokenizer(expression))
sheerka, context, parser = self.init_parser()
res = parser.parse(context, Tokenizer(expression))
assert not parser.has_error
assert res.status
@@ -96,16 +102,11 @@ class TestBnfParser(TestUsingMemoryBasedSheerka):
("'str' = var", Sequence(StrMatch("str"), StrMatch("="), c("var"))),
("'str''='var", Sequence(StrMatch("str"), StrMatch("="), c("var"))),
("foo=f", c("foo", "f")),
("foo=f 'constant'", Sequence(c("foo", "f"), StrMatch("constant"))),
])
def test_i_can_parse_regex_with_concept(self, expression, expected):
foo = Concept("foo")
bar = Concept("bar")
var = Concept("var")
context = self.get_context()
sheerka, context, parser, foo, bar, var = self.init_parser("foo", "bar", "var")
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
@@ -118,10 +119,9 @@ class TestBnfParser(TestUsingMemoryBasedSheerka):
("foo=f", ConceptExpression("foo", rule_name="f")),
])
def test_i_can_parse_regex_with_concept_when_the_concept_is_still_under_definition(self, expression, expected):
context = self.get_context()
sheerka, context, parser = self.init_parser()
context.obj = ClassWithName("foo")
parser = BnfParser()
res = parser.parse(context, Tokenizer(expression))
assert not parser.has_error
@@ -137,47 +137,43 @@ class TestBnfParser(TestUsingMemoryBasedSheerka):
("'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))
sheerka, context, parser = self.init_parser()
res = parser.parse(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)
sheerka, context, regex_parser, foo, bar = self.init_parser("foo", "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
for concept in [foo, bar]:
concept.metadata.definition_type = DEFINITION_TYPE_BNF
concepts = {bar: bar_definition, foo: foo_definition}
concept_parser = BnfNodeParser()
concept_parser.initialize(context, concepts)
foo.bnf = regex_parser.parse(context, "'twenty' | 'thirty'").value.value
bar.bnf = regex_parser.parse(context, "foo ('one' | 'two')").value.value
res = concept_parser.parse(context, "twenty two")
bnf_parser = BnfNodeParser()
bnf_parser.init_from_concepts(context, [foo, bar])
res = bnf_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")
res = bnf_parser.parse(context, "thirty one")
assert res.status
assert res.value.body == [cnode("bar", 0, 2, "thirty one")]
res = concept_parser.parse(context, "twenty")
res = bnf_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]
sheerka, context, regex_parser, foo1, foo2 = self.init_parser(
Concept(name="foo", body="1"),
Concept(name="foo", body="2"))
regex_parser = BnfParser()
res = regex_parser.parse(context, "foo")
assert not res.status
@@ -185,9 +181,7 @@ class TestBnfParser(TestUsingMemoryBasedSheerka):
assert res.value.body == ('key', 'foo')
def test_i_cannot_parse_when_unknown_concept(self):
context = self.get_context()
regex_parser = BnfParser()
sheerka, context, regex_parser = self.init_parser()
res = regex_parser.parse(self.get_context(), "foo")
assert not res.status
+193 -194
View File
@@ -1,194 +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.BaseNodeParser import SourceCodeNode
from parsers.BnfNodeParser import ConceptNode, UnrecognizedTokensNode
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=[UnrecognizedTokensNode(0, 0, [])]), 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(self.get_context(context.sheerka, True), 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(self.get_context(context.sheerka, True), 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(self.get_context(context.sheerka, True), 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
# 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.BaseNodeParser import SourceCodeNode, ConceptNode, UnrecognizedTokensNode
# 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=[UnrecognizedTokensNode(0, 0, [])]), 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_var("a").def_var("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(self.get_context(context.sheerka, True), 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_var("a").def_var("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(self.get_context(context.sheerka, True), 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_var("a").def_var("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(self.get_context(context.sheerka, True), 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_var("a").def_var("b")
# plus_2 = Concept("a plus b", body="body2").def_var("a").def_var("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
+43 -54
View File
@@ -1,14 +1,14 @@
import pytest
import ast
import pytest
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
from core.concept import Concept, DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
from parsers.BnfNodeParser import OrderedChoice, StrMatch, ConceptExpression
from parsers.PythonParser import PythonParser, PythonNode
from core.concept import DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
from core.tokenizer import Keywords, Tokenizer, LexerError
from parsers.BnfNodeParser import OrderedChoice, ConceptExpression, StrMatch
from parsers.BnfParser import BnfParser
from parsers.DefaultParser import DefaultParser, NameNode, SyntaxErrorNode, CannotHandleErrorNode, IsaConceptNode
from parsers.DefaultParser import UnexpectedTokenErrorNode, DefConceptNode
from parsers.BnfParser import BnfParser
from parsers.PythonParser import PythonParser, PythonNode
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@@ -63,6 +63,11 @@ def get_concept_part(part):
class TestDefaultParser(TestUsingMemoryBasedSheerka):
def init_parser(self, *concepts):
sheerka, concept, *updated = self.init_concepts(*concepts, singleton=True)
parser = DefaultParser()
return sheerka, concept, parser, *updated
@pytest.mark.parametrize("text, expected", [
("def concept hello", get_def_concept(name="hello")),
("def concept hello ", get_def_concept(name="hello")),
@@ -76,8 +81,8 @@ class TestDefaultParser(TestUsingMemoryBasedSheerka):
("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)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
node = res.value.value
assert res.status
@@ -93,8 +98,8 @@ 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)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
expected_concept = get_def_concept(
name="a plus b",
@@ -123,8 +128,8 @@ func(a)
ast.parse("def func(x):\n return x+1\nfunc(a)", mode="exec"))
)
parser = DefaultParser()
res = parser.parse(self.get_context(), text)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
assert res.status
@@ -146,8 +151,8 @@ def concept add one to a as:
ast.parse("def func(x):\n return x+1\nfunc(a)", mode="exec"))
)
parser = DefaultParser()
res = parser.parse(self.get_context(), text)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
assert res.status
@@ -162,8 +167,8 @@ def func(x):
func(a)
"""
parser = DefaultParser()
res = parser.parse(self.get_context(), text)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
assert not res.status
@@ -178,9 +183,7 @@ def concept add one to a as
return x+1
func(a)
"""
context = self.get_context()
parser = DefaultParser()
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
@@ -190,8 +193,8 @@ def concept add one to a as
def test_name_is_mandatory(self):
text = "def concept as 'hello'"
parser = DefaultParser()
res = parser.parse(self.get_context(), text)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
assert not res.status
@@ -203,8 +206,8 @@ def concept add one to a as
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)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
assert not res.status
@@ -221,10 +224,7 @@ def concept add one to a as
"def concept hello as 1+"
])
def test_i_can_detect_error_in_declaration(self, text):
context = self.get_context()
sheerka = context.sheerka
parser = DefaultParser()
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
return_value = res.value
@@ -234,21 +234,18 @@ def concept add one to a as
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)
sheerka, context, parser = self.init_parser()
res = parser.parse(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_bnf(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()
sheerka, context, parser, a_concept = self.init_parser("a_concept")
res = parser.parse(context, text)
node = res.value.value
definition = OrderedChoice(ConceptExpression(a_concept, rule_name="a_concept"), StrMatch("a_string"))
parser_result = ParserResultConcept(BnfParser(), "a_concept | 'a_string'", None, definition, definition)
@@ -261,12 +258,8 @@ def concept add one to a as
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()
sheerka, context, parser, a_concept = self.init_parser("a_concept")
parser.parse(context, text)
assert not parser.has_error
@@ -277,9 +270,8 @@ def concept add one to a as
"def concept name from as here is my body"
])
def test_i_can_detect_empty_bnf_declaration(self, text):
parser = DefaultParser()
res = parser.parse(self.get_context(), text)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
assert not res.status
assert res.value.value[0] == SyntaxErrorNode([], "Empty declaration")
@@ -288,8 +280,8 @@ def concept add one to a as
"def concept addition from a plus b as a + b",
"def concept addition from def a plus b as a + b"])
def test_i_can_def_concept_from_definition(self, text):
parser = DefaultParser()
res = parser.parse(self.get_context(), text)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
expected = get_def_concept("addition", definition="a plus b", body="a + b")
node = res.value.value
@@ -301,8 +293,7 @@ def concept add one to a as
def test_i_can_detect_not_for_me(self):
text = "hello world"
context = self.get_context()
parser = DefaultParser()
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
assert not res.status
@@ -310,9 +301,9 @@ def concept add one to a as
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)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
expected = IsaConceptNode([],
concept=NameNode(list(Tokenizer("the name of my 'concept'"))),
set=NameNode(list(Tokenizer("the name of the set"))))
@@ -331,8 +322,8 @@ def concept add one to a as
"def concept_name"
])
def test_i_cannot_parse_invalid_entries(self, text):
parser = DefaultParser()
res = parser.parse(self.get_context(), text)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
assert not res.status
assert isinstance(res.body, ParserResultConcept)
@@ -347,8 +338,8 @@ def concept add one to a as
("def concept c::", "Concept identifiers 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)
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
assert not res.status
assert isinstance(res.body, ParserResultConcept)
@@ -357,10 +348,8 @@ def concept add one to a as
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()
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
assert not res.status
+32 -29
View File
@@ -6,19 +6,19 @@ from parsers.ExactConceptParser import ExactConceptParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
def metadata_prop(concept, prop_name):
for name, value in concept.metadata.props:
def variable_def(concept, prop_name):
for name, value in concept.metadata.variables:
if name == prop_name:
return value
return None
def get_concept(name, variables):
def get_concept(name, variables=None):
c = Concept(name=name)
if variables:
for v in variables:
c.def_prop(v)
c.def_var(v)
c.init_key()
return c
@@ -50,9 +50,9 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
# 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)
sheerka = self.get_sheerka(singleton=True)
context = self.get_context(sheerka)
concept = self.create_concept_lite(sheerka, "hello world")
source = "hello world"
results = ExactConceptParser().parse(context, source)
@@ -64,9 +64,10 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert not concept_found.metadata.need_validation
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"]))
sheerka = self.get_sheerka(singleton=True)
context = self.get_context(sheerka)
self.create_concept_lite(sheerka, "hello world")
self.create_concept_lite(sheerka, "hello a", variables=["a"])
source = "hello world"
results = ExactConceptParser().parse(context, source)
@@ -76,7 +77,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert results[0].status
assert results[0].value.value.name == "hello a"
assert metadata_prop(results[0].value.value, "a") == "world"
assert variable_def(results[0].value.value, "a") == "world"
assert results[0].value.value.metadata.need_validation
assert results[1].status
@@ -84,9 +85,10 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert not results[1].value.value.metadata.need_validation
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)
sheerka = self.get_sheerka(singleton=True)
context = self.get_context(sheerka)
concept = self.create_concept_lite(sheerka, "a + b", ["a", "b"])
source = "10 + 5"
results = ExactConceptParser().parse(context, source)
@@ -95,46 +97,47 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
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"
assert variable_def(concept_found, "a") == "10"
assert variable_def(concept_found, "b") == "5"
assert concept_found.metadata.need_validation
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
sheerka = self.get_sheerka(singleton=True)
context = self.get_context(sheerka)
concept = self.create_concept_lite(sheerka, "a + b + a", ["a", "b"])
source = "10 + 5 + 10"
results = ExactConceptParser().parse(context, source)
results = ExactConceptParser(max_word_size=5).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"
assert variable_def(concept_found, "a") == "10"
assert variable_def(concept_found, "b") == "5"
assert concept_found.metadata.need_validation
def test_i_can_manage_unknown_concept(self):
context = self.get_context()
source = "def concept hello world" # this is not a concept by itself
context = self.get_context(self.get_sheerka(singleton=True))
source = "def concept hello" # 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"
assert res.value.body == "def concept hello"
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"
context = self.get_context(self.get_sheerka(singleton=True))
source = "a very very long concept"
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"
assert res.value.body == "a very very long concept"
def test_i_can_detect_concept_from_tokens(self):
context = self.get_context()
context = self.get_context(self.get_sheerka(singleton=True))
concept = get_concept("hello world", [])
context.sheerka.add_in_cache(concept)
+216 -216
View File
@@ -1,216 +1,216 @@
import pytest
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts
from core.concept import Concept
from core.tokenizer import Tokenizer, TokenKind, Token
from parsers.BaseNodeParser import cnode, scnode, utnode, SourceCodeNode
from parsers.BnfNodeParser import BnfNodeParser, ConceptNode, Sequence
from parsers.MultipleConceptsParser import MultipleConceptsParser
from parsers.PythonParser import PythonNode
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
def get_return_value(context, grammar, expression):
parser = BnfNodeParser()
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", 4),
("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
# import pytest
#
# from core.builtin_concepts import ParserResultConcept, BuiltinConcepts
# from core.concept import Concept
# from core.tokenizer import Tokenizer, TokenKind, Token
# from parsers.BaseNodeParser import cnode, scnode, utnode, SourceCodeNode, ConceptNode
# from parsers.BnfNodeParser import BnfNodeParser, Sequence
# from parsers.MultipleConceptsParser import MultipleConceptsParser
# from parsers.PythonParser import PythonNode
#
# from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
#
#
# def get_return_value(context, grammar, expression):
# parser = BnfNodeParser()
# 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", 4),
# ("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
+7 -7
View File
@@ -50,9 +50,9 @@ class TestPythonParser(TestUsingMemoryBasedSheerka):
assert res.who == parser.name
assert isinstance(res.value, NotForMeConcept)
assert res.value.body == text
assert len(res.value.get_prop("reason")) == 1
assert isinstance(res.value.get_prop("reason")[0], PythonErrorNode)
assert isinstance(res.value.get_prop("reason")[0].exception, SyntaxError)
assert len(res.value.get_value("reason")) == 1
assert isinstance(res.value.get_value("reason")[0], PythonErrorNode)
assert isinstance(res.value.get_value("reason")[0].exception, SyntaxError)
@pytest.mark.parametrize("text, error_msg, error_text", [
("c::", "Concept identifiers not found", ""),
@@ -66,10 +66,10 @@ class TestPythonParser(TestUsingMemoryBasedSheerka):
assert isinstance(res.value, NotForMeConcept)
assert res.value.body == text
assert len(res.value.get_prop("reason")) == 1
assert isinstance(res.value.get_prop("reason")[0], LexerError)
assert res.value.get_prop("reason")[0].message == error_msg
assert res.value.get_prop("reason")[0].text == error_text
assert len(res.value.get_value("reason")) == 1
assert isinstance(res.value.get_value("reason")[0], LexerError)
assert res.value.get_value("reason")[0].message == error_msg
assert res.value.get_value("reason")[0].text == error_text
def test_i_can_parse_a_concept(self):
text = "c:name|key: + 1"
@@ -4,7 +4,7 @@ import pytest
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
from core.concept import Concept
from core.tokenizer import Token, TokenKind, Tokenizer
from parsers.BnfNodeParser import ConceptNode, UnrecognizedTokensNode
from parsers.BaseNodeParser import ConceptNode, UnrecognizedTokensNode
from parsers.PythonParser import PythonNode
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
from parsers.UnrecognizedNodeParser import UnrecognizedNodeParser
@@ -3,7 +3,7 @@ from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, CC
from core.tokenizer import Tokenizer
from parsers.BaseNodeParser import utnode, ConceptNode, cnode, short_cnode, UnrecognizedTokensNode, \
SCWC, CNC, CN, UTN, scnode
SCWC, CNC, UTN
from parsers.PythonParser import PythonNode
from parsers.SyaNodeParser import SyaNodeParser, SyaConceptParserHelper, SyaAssociativity, \
NoneAssociativeSequenceErrorNode, TooManyParametersFound
@@ -16,14 +16,69 @@ def compute_expected_array(concepts_map, expression, expected):
return tests.parsers.parsers_utils.compute_expected_array(concepts_map, expression, expected, sya=True)
class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
cmap = {
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"four": Concept("four"),
"plus": Concept("a plus b").def_var("a").def_var("b"),
"minus": Concept("a minus b").def_var("a").def_var("b"),
"mult": Concept("a mult b").def_var("a").def_var("b"),
"prefixed": Concept("a prefixed").def_var("a"),
"suffixed": Concept("suffixed a").def_var("a"),
"infix": Concept("a infix b").def_var("a").def_var("b"),
"?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
"if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
"square": Concept("square(a)").def_var("a"),
"foo bar": Concept("foo bar(a)").def_var("a"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
}
def init_parser(self, concepts_map, sya_def, **kwargs):
sheerka, context, *updated_concepts = self.init_concepts(
*concepts_map.values(),
singleton=True,
class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
sheerka = None
@classmethod
def setup_class(cls):
t = TestSyaNodeParser()
TestSyaNodeParser.sheerka, context, _ = t.init_parser(
cmap,
singleton=False,
create_new=True,
**kwargs)
init_from_sheerka=True)
TestSyaNodeParser.sheerka.force_sya_def(context, [
(cmap["plus"].id, 5, SyaAssociativity.Right),
(cmap["mult"].id, 10, SyaAssociativity.Right),
(cmap["minus"].id, 10, SyaAssociativity.Right),
(cmap["square"].id, None, SyaAssociativity.No)])
def init_parser(self,
my_concepts_map=None,
sya_def=None,
post_init_concepts=None,
**kwargs):
if my_concepts_map is not None:
# a new concept map is given
# use it but
# do not instantiate a new sheerka
# do not update / init from sheerka
if 'singleton' not in kwargs:
kwargs["singleton"] = True
init_from_sheerka = kwargs.get("init_from_sheerka", False)
sheerka, context, *concepts = self.init_concepts(*my_concepts_map.values(), **kwargs)
else:
# No custom concept map is given -> Use the global cmap
# Sheerka is already initialized (the class instance)
# Use it to initialize the parser
init_from_sheerka = kwargs.get("init_from_sheerka", True)
sheerka = TestSyaNodeParser.sheerka
context = self.get_context(sheerka)
concepts = cmap.values()
if post_init_concepts:
post_init_concepts(sheerka, context)
if sya_def:
sya_def_to_use = {}
@@ -32,29 +87,15 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
else:
sya_def_to_use = None
parser = SyaNodeParser()
parser.initialize(context, updated_concepts, sya_def_to_use)
if init_from_sheerka:
parser = SyaNodeParser(sheerka=sheerka)
else:
parser = SyaNodeParser()
if my_concepts_map:
parser.init_from_concepts(context, concepts, sya=sya_def_to_use)
return sheerka, context, parser
def test_i_can_initialize(self):
sheerka, context, c1, c2, c3, c4, c5 = self.init_concepts(
"foo",
Concept("bar a").def_prop("a"),
Concept("a baz").def_prop("a"),
Concept("baz a qux b").def_prop("a").def_prop("b"),
Concept("foo a bar b").def_prop("a").def_prop("b"),
)
parser = SyaNodeParser()
parser.initialize(context, [c1, c2, c3, c4, c5])
assert parser.concepts_by_first_keyword == {
"foo": [c1.id, c5.id],
"bar": [c2.id],
"baz": [c3.id, c4.id],
}
@pytest.mark.parametrize("expression, expected_sequences", [
("one plus two", [["one", "two", "plus"]]),
("1 + 1 plus two", [["1 + 1 ", "two", "plus"]]),
@@ -143,21 +184,21 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("x$!# plus z$!#", [["x$!# ", " z$!#", "plus"]]),
])
def test_i_can_post_fix_simple_infix_concepts(self, expression, expected_sequences):
concepts_map = {
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
@pytest.mark.parametrize("expression, expected_sequences", [
@@ -169,14 +210,14 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_infix_concepts_with_long_name(self, expression, expected_sequences):
concepts_map = {
"plus plus plus": Concept("a plus plus plus b").def_prop("a").def_prop("b"),
"another long name infix": Concept("a another long name infix b").def_prop("a").def_prop("b"),
"plus plus plus": Concept("a plus plus plus b").def_var("a").def_var("b"),
"another long name infix": Concept("a another long name infix b").def_var("a").def_var("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, init_from_sheerka=True)
res = parser.infix_to_postfix(context, expression)
@@ -200,20 +241,20 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("x$!# prefixed", [["x$!# ", "prefixed"]]),
])
def test_i_can_post_fix_simple_prefixed_concepts(self, expression, expected_sequences):
concepts_map = {
"prefixed": Concept("a prefixed").def_prop("a"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "prefixed": Concept("a prefixed").def_var("a"),
# "one": Concept("one"),
# "two": Concept("two"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
@pytest.mark.parametrize("expression, expected_sequences", [
@@ -243,13 +284,13 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_prefixed_concepts_with_long_names(self, expression, expected_sequences):
concepts_map = {
"prefixed prefixed": Concept("a prefixed prefixed").def_prop("a"),
"long name prefixed": Concept("a long name prefixed").def_prop("a"),
"prefixed prefixed": Concept("a prefixed prefixed").def_var("a"),
"long name prefixed": Concept("a long name prefixed").def_var("a"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, init_from_sheerka=True)
res = parser.infix_to_postfix(context, expression)
@@ -273,20 +314,20 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("suffixed x$!#", [[" x$!#", "suffixed"]]),
])
def test_i_can_post_fix_simple_suffixed_concepts(self, expression, expected_sequences):
concepts_map = {
"suffixed": Concept("suffixed a").def_prop("a"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "suffixed": Concept("suffixed a").def_var("a"),
# "one": Concept("one"),
# "two": Concept("two"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
@pytest.mark.parametrize("expression, expected", [
@@ -295,11 +336,11 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_suffixed_concepts_with_long_names(self, expression, expected):
concepts_map = {
"suffixed suffixed": Concept("suffixed suffixed a").def_prop("a"),
"long name suffixed": Concept("long name suffixed a").def_prop("a"),
"suffixed suffixed": Concept("suffixed suffixed a").def_var("a"),
"long name suffixed": Concept("long name suffixed a").def_var("a"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
@@ -340,22 +381,22 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
:return:
"""
concepts_map = {
"?": Concept("a ? b : c").def_prop("a").def_prop("b").def_prop("c"),
"if": Concept("if a then b else c end").def_prop("a").def_prop("b").def_prop("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
# assert len(res_i.errors) == 0 # Do not validate errors
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
@pytest.mark.parametrize("expression, expected_sequences", [
@@ -373,14 +414,14 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_ternary_concept_with_long_names(self, expression, expected_sequences):
concepts_map = {
"? ?": Concept("a ? ? b : : c").def_prop("a").def_prop("b").def_prop("c"),
"if if": Concept("if if a then then b else else c end end").def_prop("a").def_prop("b").def_prop("c"),
"? ?": Concept("a ? ? b : : c").def_var("a").def_var("b").def_var("c"),
"if if": Concept("if if a then then b else else c end end").def_var("a").def_var("b").def_var("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, init_from_sheerka=True)
res = parser.infix_to_postfix(context, expression)
@@ -397,8 +438,8 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_suffixed_unary_composition(self, expression, expected):
concepts_map = {
"foo": Concept("foo a").def_prop("a"),
"bar": Concept("bar a").def_prop("a"),
"foo": Concept("foo a").def_var("a"),
"bar": Concept("bar a").def_var("a"),
"baz": Concept("baz"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
@@ -416,8 +457,8 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_prefixed_unary_composition(self, expression, expected):
concepts_map = {
"foo": Concept("a foo").def_prop("a"),
"bar": Concept("a bar").def_prop("a"),
"foo": Concept("a foo").def_var("a"),
"bar": Concept("a bar").def_var("a"),
"baz": Concept("baz"),
}
sya_def = {
@@ -439,29 +480,29 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("one mult (two plus three)", ["one", "two", "three", "plus", "mult"]),
])
def test_i_can_post_fix_binary_with_precedence(self, expression, expected):
concepts_map = {
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"mult": Concept("a mult b").def_prop("a").def_prop("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
}
sya_def = {
concepts_map["plus"]: (5, SyaAssociativity.Right),
concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
}
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
# concepts_map = {
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "mult": Concept("a mult b").def_var("a").def_var("b"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# }
# sya_def = {
# concepts_map["plus"]: (5, SyaAssociativity.Right),
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
# }
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
def test_i_can_post_fix_unary_with_precedence(self):
concepts_map = {
"suffixed": Concept("suffixed a").def_prop("a"),
"prefixed": Concept("a prefixed").def_prop("a"),
"suffixed": Concept("suffixed a").def_var("a"),
"prefixed": Concept("a prefixed").def_var("a"),
"a": Concept("a"),
}
@@ -496,7 +537,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
def test_i_can_post_fix_right_associated_binary(self):
concepts_map = {
"equals": Concept("a equals b").def_prop("a").def_prop("b"),
"equals": Concept("a equals b").def_var("a").def_var("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
@@ -518,7 +559,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
def test_i_can_post_fix_left_associated_binary(self):
concepts_map = {
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"plus": Concept("a plus b").def_var("a").def_var("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
@@ -550,7 +591,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_right_associated_ternary(self, expression, expected):
concepts_map = {
"?": Concept("a ? b : c").def_prop("a").def_prop("b").def_prop("c"),
"?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
@@ -577,7 +618,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
])
def test_i_can_post_fix_left_associated_ternary(self, expression, expected):
concepts_map = {
"?": Concept("a ? b : c").def_prop("a").def_prop("b").def_prop("c"),
"?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
@@ -594,8 +635,8 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
def test_i_can_post_fix_when_multiple_concepts_are_found(self):
concepts_map = {
"foo": Concept("foo a").def_prop("a"),
"foo bar": Concept("foo bar a").def_prop("a"),
"foo": Concept("foo a").def_var("a"),
"foo bar": Concept("foo bar a").def_var("a"),
"baz": Concept("baz"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
@@ -603,7 +644,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
expression = "foo bar baz"
res = parser.infix_to_postfix(context, expression)
expected_sequences = [
[" bar ", "foo", "baz"],
[UTN(" bar "), "foo", "baz"],
["baz", "foo bar"]
]
@@ -646,30 +687,30 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("foo bar ( one )", ["one", "foo bar"]),
])
def test_i_can_pos_fix_when_parenthesis(self, expression, expected):
concepts_map = {
"prefixed": Concept("a prefixed").def_prop("a"),
"suffixed": Concept("suffixed a").def_prop("a"),
"square": Concept("square(a)").def_prop("a"),
"foo bar": Concept("foo bar(a)").def_prop("a"),
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"minus": Concept("a minus b").def_prop("a").def_prop("b"),
"if": Concept("if a then b else c end").def_prop("a").def_prop("b").def_prop("c"),
"?": Concept("a ? b : c").def_prop("a").def_prop("b").def_prop("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
}
# concepts_map = {
# "prefixed": Concept("a prefixed").def_var("a"),
# "suffixed": Concept("suffixed a").def_var("a"),
# "square": Concept("square(a)").def_var("a"),
# "foo bar": Concept("foo bar(a)").def_var("a"),
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "minus": Concept("a minus b").def_var("a").def_var("b"),
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# }
#
# sya_def = {
# concepts_map["square"]: (None, SyaAssociativity.No),
# concepts_map["plus"]: (10, SyaAssociativity.Right),
# concepts_map["minus"]: (10, SyaAssociativity.Right),
# }
sya_def = {
concepts_map["square"]: (None, SyaAssociativity.No),
concepts_map["plus"]: (10, SyaAssociativity.Right),
concepts_map["minus"]: (10, SyaAssociativity.Right),
}
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
@@ -721,28 +762,28 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("suffixed one function(two)", [["one", "suffixed", SCWC(" function(", ")", "two")]]),
])
def test_i_can_post_fix_when_parenthesis_and_unknown(self, expression, expected_sequences):
concepts_map = {
"prefixed": Concept("a prefixed").def_prop("a"),
"suffixed": Concept("suffixed a").def_prop("a"),
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"mult": Concept("a mult b").def_prop("a").def_prop("b"),
"if": Concept("if a then b else c end").def_prop("a").def_prop("b").def_prop("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sya_def = {
concepts_map["plus"]: (5, SyaAssociativity.Right),
concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
}
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
# concepts_map = {
# "prefixed": Concept("a prefixed").def_var("a"),
# "suffixed": Concept("suffixed a").def_var("a"),
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "mult": Concept("a mult b").def_var("a").def_var("b"),
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
# sya_def = {
# concepts_map["plus"]: (5, SyaAssociativity.Right),
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
# }
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
@pytest.mark.parametrize("expression, expected", [
@@ -762,13 +803,13 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("(one plus ( 1 + )", ("(", 0)),
])
def test_i_can_detect_parenthesis_mismatch_error_when_post_fixing(self, expression, expected):
concepts_map = {
"one": Concept("one"),
"two": Concept("two"),
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"?": Concept("a ? b : c").def_prop("a").def_prop("b").def_prop("c"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "one": Concept("one"),
# "two": Concept("two"),
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
# }
sheerka, context, parser = self.init_parser()
res = parser.infix_to_postfix(context, expression)
@@ -779,13 +820,13 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("one ? one two : three", ("?", ":")),
])
def test_i_can_detected_when_too_many_parameters(self, expression, expected):
concepts_map = {
"one": Concept("one"),
"two": Concept("two"),
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"?": Concept("a ? b : c").def_prop("a").def_prop("b").def_prop("c"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "one": Concept("one"),
# "two": Concept("two"),
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
# }
sheerka, context, parser = self.init_parser(cmap, None)
res = parser.infix_to_postfix(context, expression)
@@ -793,7 +834,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
assert len(res[0].errors) == 1
error = res[0].errors[0]
assert isinstance(error, TooManyParametersFound)
assert error.concept == concepts_map[expected[0]]
assert error.concept == cmap[expected[0]]
assert error.token.value == expected[1]
@pytest.mark.parametrize("expression, expected", [
@@ -819,30 +860,30 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("(one infix two) (three prefixed)", ["one", "two", "infix", "three", "prefixed"]),
])
def test_i_can_post_fix_sequences(self, expression, expected):
concepts_map = {
"prefixed": Concept("a prefixed").def_prop("a"),
"suffixed": Concept("suffixed a").def_prop("a"),
"infix": Concept("a infix b").def_prop("a").def_prop("b"),
"?": Concept("a ? b : c").def_prop("a").def_prop("b").def_prop("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"four": Concept("four"),
}
# concepts_map = {
# "prefixed": Concept("a prefixed").def_var("a"),
# "suffixed": Concept("suffixed a").def_var("a"),
# "infix": Concept("a infix b").def_var("a").def_var("b"),
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# "four": Concept("four"),
# }
sheerka, context, parser = self.init_parser(concepts_map, None)
sheerka, context, parser = self.init_parser(cmap, None)
res = parser.infix_to_postfix(context, expression)
expected_array = compute_expected_array(concepts_map, expression, expected)
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
def test_the_more_concepts_the_more_results(self):
concepts_map = {
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"plus plus": Concept("a plus plus").def_prop("a"),
"plus equals": Concept("a plus equals b").def_prop("a").def_prop("b"),
"plus": Concept("a plus b").def_var("a").def_var("b"),
"plus plus": Concept("a plus plus").def_var("a"),
"plus equals": Concept("a plus equals b").def_var("a").def_var("b"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
@@ -864,7 +905,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
def test_i_can_use_string_instead_of_identifier(self):
concepts_map = {
"ternary": Concept("a ? ? b '::' c").def_prop("a").def_prop("b").def_prop("c"),
"ternary": Concept("a ? ? b '::' c").def_var("a").def_var("b").def_var("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
@@ -883,7 +924,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
def test_i_cannot_chain_non_associative(self):
concepts_map = {
"less than": Concept("a less than b").def_prop("a").def_prop("b"),
"less than": Concept("a less than b").def_var("a").def_var("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
@@ -904,35 +945,35 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
Not quite sure why this test is here
:return:
"""
concepts_map = {
"foo": Concept("foo a").def_prop("a"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "foo": Concept("foo a").def_var("a"),
# "one": Concept("one"),
# "two": Concept("two"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
sheerka, context, parser = self.init_parser(cmap, None)
expression = "foo twenties"
expression = "suffixed twenties"
res = parser.infix_to_postfix(context, expression)
expected = [cnode("twenties", 2, 2, "twenties"), "foo"]
expected_array = compute_expected_array(concepts_map, expression, expected)
expected = [cnode("twenties", 2, 2, "twenties"), "suffixed"]
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
def test_i_can_parse_when_concept_atom_only(self):
concepts_map = {
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"mult": Concept("a mult b").def_prop("a").def_prop("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
}
sya_def = {
concepts_map["plus"]: (5, SyaAssociativity.Right),
concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
}
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
# concepts_map = {
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "mult": Concept("a mult b").def_var("a").def_var("b"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# }
# sya_def = {
# concepts_map["plus"]: (5, SyaAssociativity.Right),
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
# }
sheerka, context, parser = self.init_parser()
text = "one plus two mult three"
res = parser.parse(context, text)
@@ -941,29 +982,29 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [ConceptNode(concepts_map["plus"], 0, 8, source=text)]
assert lexer_nodes == [ConceptNode(cmap["plus"], 0, 8, source=text)]
# check the compiled
expected_concept = lexer_nodes[0].concept
assert expected_concept.compiled["a"] == concepts_map["one"]
assert expected_concept.compiled["b"] == concepts_map["mult"]
assert expected_concept.compiled["b"].compiled["a"] == concepts_map["two"]
assert expected_concept.compiled["b"].compiled["b"] == concepts_map["three"]
assert expected_concept.compiled["a"] == cmap["one"]
assert expected_concept.compiled["b"] == cmap["mult"]
assert expected_concept.compiled["b"].compiled["a"] == cmap["two"]
assert expected_concept.compiled["b"].compiled["b"] == cmap["three"]
def test_i_can_parse_when_python_code(self):
concepts_map = {
"foo": Concept("foo a").def_prop("a")
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "foo": Concept("foo a").def_var("a")
# }
sheerka, context, parser = self.init_parser(cmap, None)
text = "foo 1 + 1"
text = "suffixed 1 + 1"
res = parser.parse(context, text)
wrapper = res.body
lexer_nodes = res.body.body
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [ConceptNode(concepts_map["foo"], 0, 6, source=text)]
assert lexer_nodes == [ConceptNode(cmap["suffixed"], 0, 6, source=text)]
# check the compiled
expected_concept = lexer_nodes[0].concept
@@ -977,15 +1018,15 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
assert isinstance(return_value_a.body.body, PythonNode)
def test_i_can_parse_when_bnf_concept(self):
concepts_map = {
"foo": Concept("foo a").def_prop("a"),
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "foo": Concept("foo a").def_var("a"),
# "one": Concept("one"),
# "two": Concept("two"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
sheerka, context, parser = self.init_parser()
text = "foo twenty one"
text = "suffixed twenty one"
res = parser.parse(context, text)
assert len(res) == 2
assert res[1].status
@@ -994,23 +1035,23 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
lexer_nodes = res[1].body.body
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [ConceptNode(concepts_map["foo"], 0, 4, source=text)]
assert lexer_nodes == [ConceptNode(cmap["suffixed"], 0, 4, source=text)]
# check the compiled
expected_concept = lexer_nodes[0].concept
assert sheerka.isinstance(expected_concept.compiled["a"], "twenties")
assert expected_concept.compiled["a"].compiled["unit"] == concepts_map["one"]
assert expected_concept.compiled["a"].compiled["unit"] == cmap["one"]
def test_i_can_parse_sequences(self):
concepts_map = {
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"foo": Concept("foo a").def_prop("a"),
"one": Concept("one"),
"two": Concept("two"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "foo": Concept("foo a").def_var("a"),
# "one": Concept("one"),
# "two": Concept("two"),
# }
sheerka, context, parser = self.init_parser(cmap, None)
text = "one plus 1 + 1 foo two"
text = "one plus 1 + 1 suffixed two"
res = parser.parse(context, text)
wrapper = res.body
lexer_nodes = res.body.body
@@ -1018,19 +1059,19 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [
ConceptNode(concepts_map["plus"], 0, 9, source="one plus 1 + 1 "),
ConceptNode(concepts_map["foo"], 10, 12, source="foo two")]
ConceptNode(cmap["plus"], 0, 9, source="one plus 1 + 1 "),
ConceptNode(cmap["suffixed"], 10, 12, source="suffixed two")]
# check the compiled
concept_plus_a = lexer_nodes[0].concept.compiled["a"]
concept_plus_b = lexer_nodes[0].concept.compiled["b"]
concept_foo_a = lexer_nodes[1].concept.compiled["a"]
concept_suffixed_a = lexer_nodes[1].concept.compiled["a"]
assert concept_plus_a == concepts_map["one"]
assert concept_plus_a == cmap["one"]
assert len(concept_plus_b) == 1
assert sheerka.isinstance(concept_plus_b[0], BuiltinConcepts.RETURN_VALUE)
assert isinstance(concept_plus_b[0].body.body, PythonNode)
assert concept_foo_a == concepts_map["two"]
assert concept_suffixed_a == cmap["two"]
@pytest.mark.parametrize("text, expected_status, expected_result", [
("function(suffixed one)", True, [
@@ -1046,28 +1087,28 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
SCWC("function(", ")", CNC("suffixed", 2, 7, a=" x$!#"))]),
])
def test_i_can_parse_when_one_result(self, text, expected_status, expected_result):
concepts_map = {
"prefixed": Concept("a prefixed").def_prop("a"),
"suffixed": Concept("suffixed a").def_prop("a"),
"mult": Concept("a mult b").def_prop("a").def_prop("b"),
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"if": Concept("if a then b else c end").def_prop("a").def_prop("b").def_prop("c"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sya_def = {
concepts_map["plus"]: (5, SyaAssociativity.Right),
concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
}
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
# concepts_map = {
# "prefixed": Concept("a prefixed").def_var("a"),
# "suffixed": Concept("suffixed a").def_var("a"),
# "mult": Concept("a mult b").def_var("a").def_var("b"),
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
# sya_def = {
# concepts_map["plus"]: (5, SyaAssociativity.Right),
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
# }
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
wrapper = res.body
lexer_nodes = res.body.body
expected_array = compute_expected_array(concepts_map, text, expected_result)
expected_array = compute_expected_array(cmap, text, expected_result)
assert res.status == expected_status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
@@ -1080,15 +1121,15 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
# ])
# def test_i_can_parse_when_multiple_results(self, text, list_of_expected):
# concepts_map = {
# "prefixed": Concept("a prefixed").def_prop("a"),
# "suffixed": Concept("suffixed a").def_prop("a"),
# "mult": Concept("a mult b").def_prop("a").def_prop("b"),
# "plus": Concept("a plus b").def_prop("a").def_prop("b"),
# "if": Concept("if a then b else c end").def_prop("a").def_prop("b").def_prop("c"),
# "prefixed": Concept("a prefixed").def_var("a"),
# "suffixed": Concept("suffixed a").def_var("a"),
# "mult": Concept("a mult b").def_var("a").def_var("b"),
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
# sya_def = {
# concepts_map["plus"]: (5, SyaAssociativity.Right),
@@ -1116,13 +1157,13 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("x$!# infix z$!#", "infix", ["a", "b"]),
])
def test_i_cannot_parse_when_unrecognized(self, text, expected_concept, expected_unrecognized):
concepts_map = {
"suffixed": Concept("suffixed a").def_prop("a"),
"prefixed": Concept("a prefixed").def_prop("a"),
"infix": Concept("a infix b").def_prop("a").def_prop("b"),
"one": Concept("one")
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "suffixed": Concept("suffixed a").def_var("a"),
# "prefixed": Concept("a prefixed").def_var("a"),
# "infix": Concept("a infix b").def_var("a").def_var("b"),
# "one": Concept("one")
# }
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
wrapper = res.body
@@ -1131,7 +1172,7 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
assert not res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [ConceptNode(concepts_map[expected_concept], 0, expected_end, source=text)]
assert lexer_nodes == [ConceptNode(cmap[expected_concept], 0, expected_end, source=text)]
concept_found = lexer_nodes[0].concept
for unrecognized in expected_unrecognized:
@@ -1142,14 +1183,14 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
("one prefixed x$!#", [cnode("__var__0 prefixed", 0, 2, "one prefixed"), utnode(3, 7, " x$!#")]),
])
def test_i_cannot_parse_when_part_of_the_sequence_is_not_recognized(self, text, expected):
concepts_map = {
"suffixed": Concept("suffixed a").def_prop("a"),
"prefixed": Concept("a prefixed").def_prop("a"),
"infix": Concept("a infix b").def_prop("a").def_prop("b"),
"one": Concept("one"),
"two": Concept("two"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "suffixed": Concept("suffixed a").def_var("a"),
# "prefixed": Concept("a prefixed").def_var("a"),
# "infix": Concept("a infix b").def_var("a").def_var("b"),
# "one": Concept("one"),
# "two": Concept("two"),
# }
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
wrapper = res.body
@@ -1173,14 +1214,14 @@ class TestSyaConceptLexerParser(TestUsingMemoryBasedSheerka):
Atoms concepts, source code or BNF concepts alone are discarded by the lexer
:return:
"""
concepts_map = {
"plus": Concept("a plus b").def_prop("a").def_prop("b"),
"one": Concept("one"),
"two": Concept("two"),
"three": Concept("three"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_prop("unit"),
}
sheerka, context, parser = self.init_parser(concepts_map, None)
# concepts_map = {
# "plus": Concept("a plus b").def_var("a").def_var("b"),
# "one": Concept("one"),
# "two": Concept("two"),
# "three": Concept("three"),
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
# }
sheerka, context, parser = self.init_parser()
res = parser.parse(context, text)
+47 -16
View File
@@ -42,17 +42,17 @@ def get_input_nodes_from(my_concepts_map, full_expr, *args):
concepts_map = {
"5params": Concept("5params").def_prop("a").def_prop("b").def_prop("c").def_prop("d").def_prop("e"),
"plus": Concept("a plus b", body="a + b").def_prop("a").def_prop("b"),
"mult": Concept("a mult b", body="a * b").def_prop("a").def_prop("b"),
"5params": Concept("5params").def_var("a").def_var("b").def_var("c").def_var("d").def_var("e"),
"plus": Concept("a plus b", body="a + b").def_var("a").def_var("b"),
"mult": Concept("a mult b", body="a * b").def_var("a").def_var("b"),
"one": Concept("one", body="1"),
"two": Concept("two", body="2"),
"three": Concept("three", body="3"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit", body="20 + unit").def_prop("unit"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit", body="20 + unit").def_var("unit"),
"hello_atom": Concept("hello one"),
"hello_sya": Concept("hello a").def_prop("a"),
"greetings_a": Concept("greetings a").def_prop("a"),
"greetings_b": Concept("greetings b").def_prop("b"),
"hello_sya": Concept("hello a").def_var("a"),
"greetings_a": Concept("greetings a").def_var("a"),
"greetings_b": Concept("greetings b").def_var("b"),
}
@@ -64,7 +64,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
def setup_class(cls):
t = TestUnrecognizedNodeParser()
TestUnrecognizedNodeParser.sheerka, context, _ = t.init_parser(concepts_map, create_new=True)
TestUnrecognizedNodeParser.sheerka.set_sya_def(context, [
TestUnrecognizedNodeParser.sheerka.force_sya_def(context, [
(concepts_map["mult"].id, 20, SyaAssociativity.Right),
(concepts_map["plus"].id, 10, SyaAssociativity.Right),
])
@@ -144,13 +144,15 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expected_nodes = compute_expected_array(
concepts_map,
" one plus two mult three ",
[CNC("plus", a="one", b=CC("mult", a="two", b="three"))])
[CNC("plus", a="one", b=CC("mult", a="two", b="three"))],
exclude_body=True)
assert concept.compiled["e"][0].body.body == expected_nodes
# # sanity check, I can evaluate the concept
# evaluated = sheerka.evaluate_concept(self.get_context(sheerka, eval_body=True), concept)
# assert evaluated.key == concept.key
# assert evaluated.get_prop("a") ==
# assert evaluated.get_value("a") ==
def test_i_can_validate_with_recursion(self):
sheerka, context, parser = self.init_parser()
@@ -246,6 +248,22 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
assert len(actual_nodes) == 1
assert actual_nodes[0] == scnode(0, 4, expression)
def test_i_cannot_parse_unrecognized_python_that_looks_like_concept(self):
sheerka, context, parser = self.init_parser()
expression = "fake_concept_name" # as it's not a concept, it will be recognized as python node
nodes = get_input_nodes_from(concepts_map, expression, UTN(expression))
parser_input = ParserResultConcept("parsers.xxx", source=expression, value=nodes)
res = parser.parse(context, parser_input)
parser_result = res.body
actual_nodes = res.body.body
assert not res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert len(actual_nodes) == 1
assert actual_nodes[0] == nodes[0]
def test_i_can_parse_unrecognized_bnf_concept_node(self):
sheerka, context, parser = self.init_parser()
@@ -285,7 +303,8 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
concepts_map,
expression, [CNC("plus",
a="one",
b=CC("mult", source="two mult three", a="two", b="three"))])
b=CC("mult", source="two mult three", a="two", b="three"))],
exclude_body=True)
assert actual_nodes == expected_array
def test_i_can_parse_sequences(self):
@@ -314,7 +333,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expression = "two hello one three"
nodes = get_input_nodes_from(concepts_map, expression,
"two", UTN("hello one"), "three")
parser_input = ParserResultConcept("parsers.xxx", source="one plus two hello one", value=nodes)
parser_input = ParserResultConcept("parsers.xxx", source=expression, value=nodes)
res = parser.parse(context, parser_input)
assert len(res) == 2
@@ -332,7 +351,8 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expected_1 = compute_expected_array(concepts_map, expression, [
CN("two", 0, 0),
CNC("hello_sya", source="hello one", start=2, end=4, a="one"),
CN("three", 6, 6)])
CN("three", 6, 6)],
exclude_body=True)
assert actual_nodes1 == expected_1
@@ -341,7 +361,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expression = "greetings two"
nodes = get_input_nodes_from(concepts_map, expression, UTN("greetings two"))
parser_input = ParserResultConcept("parsers.xxx", source="greetings two", value=nodes)
parser_input = ParserResultConcept("parsers.xxx", source=expression, value=nodes)
res = parser.parse(context, parser_input)
assert len(res) == 2
@@ -350,14 +370,25 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
actual_nodes0 = res[0].body.body
expected_0 = compute_expected_array(concepts_map, expression, [
CNC("greetings_a", source="greetings two", start=0, end=2, a="two")])
CNC("greetings_a", source="greetings two", start=0, end=2, a="two")], exclude_body=True)
assert actual_nodes0 == expected_0
actual_nodes1 = res[1].body.body
expected_1 = compute_expected_array(concepts_map, expression, [
CNC("greetings_b", source="greetings two", start=0, end=2, b="two")])
CNC("greetings_b", source="greetings two", start=0, end=2, b="two")], exclude_body=True)
assert actual_nodes1 == expected_1
def test_i_cannot_parse_when_some_unrecognized_remain(self):
sheerka, context, parser = self.init_parser()
expression = "twenty one + one"
nodes = get_input_nodes_from(concepts_map, expression, UTN("twenty "), "one", " + ", ("one", 1))
parser_input = ParserResultConcept("parsers.xxx", source=expression, value=nodes)
res = parser.parse(context, parser_input)
assert not res.status
assert res.body.body == nodes
def test_i_cannot_parse_when_i_cannot_validate(self):
sheerka, context, parser = self.init_parser(concepts_map, create_new=True)
expression = "one plus unknown tokens"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -22,14 +22,14 @@ class Obj:
def test_i_can_serialize_an_event():
event = Event("test", user="user", date=datetime.fromisoformat("2019-10-21T10:20:30.999"))
event = Event("test", user_id="user", date=datetime.fromisoformat("2019-10-21T10:20:30.999"))
serializer = Serializer()
stream = serializer.serialize(event, None)
loaded = serializer.deserialize(stream, None)
assert event.version == loaded.version
assert event.user == loaded.user
assert event.user_id == loaded.user_id
assert event.date == loaded.date
assert event.message == loaded.message
+40 -38
View File
@@ -1,5 +1,5 @@
import sheerkapickle
from core.builtin_concepts import BuiltinConcepts, UserInputConcept, ReturnValueConcept
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
from core.concept import Concept, ConceptParts
from core.sheerka.ExecutionContext import ExecutionContext
from core.tokenizer import Tokenizer
@@ -56,10 +56,11 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "meta.where": "my_where"}'
concept = set_full_serialization(Concept("foo").def_prop("a", "value_a").def_prop("b", "value_b"))
concept = set_full_serialization(Concept("foo").def_var("a", "value_a").def_var("b", "value_b"))
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "meta.variables": [["a", "value_a"], ["b", "value_b"]], "values": [["a", null], ["b", null]]}'
concept = Concept("foo").init_key()
sheerka.create_new_concept(self.get_context(sheerka), concept)
@@ -73,76 +74,76 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
sheerka = self.get_sheerka()
concept = set_full_serialization(Concept("foo"))
concept.values[ConceptParts.PRE] = 10 # an int
concept.set_value(ConceptParts.PRE, 10) # an int
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "pre": 10}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["cParts.pre", 10]]}'
concept = set_full_serialization(Concept("foo"))
concept.values[ConceptParts.POST] = 'a string' # an string
concept.set_value(ConceptParts.POST, 'a string') # an string
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "post": "a string"}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["cParts.post", "a string"]]}'
concept = set_full_serialization(Concept("foo"))
concept.values[ConceptParts.WHERE] = ['a string', 3.14] # a list
concept.set_value(ConceptParts.WHERE, ['a string', 3.14]) # a list
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "where": ["a string", 3.14]}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["cParts.where", ["a string", 3.14]]]}'
concept = set_full_serialization(Concept("foo"))
concept.values[ConceptParts.WHERE] = ('a string', 3.14) # a tuple
concept.set_value(ConceptParts.WHERE, ('a string', 3.14)) # a tuple
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "where": {"_sheerka/tuple": ["a string", 3.14]}}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["cParts.where", {"_sheerka/tuple": ["a string", 3.14]}]]}'
concept = set_full_serialization(Concept("foo"))
concept.values[ConceptParts.BODY] = set_full_serialization(Concept("foo", body="foo_body"))
concept.set_value(ConceptParts.BODY, set_full_serialization(Concept("foo", body="foo_body")))
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "body": {"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "meta.body": "foo_body"}}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["cParts.body", {"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "meta.body": "foo_body"}]]}'
def test_i_can_encode_decode_unknown_concept_properties(self):
def test_i_can_encode_decode_unknown_concept_variables(self):
sheerka = self.get_sheerka()
concept = set_full_serialization(Concept("foo"))
concept.set_prop("a", "value_a") # string
concept.set_value("a", "value_a") # string
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "props": [["a", "value_a"]]}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["a", "value_a"]]}'
concept = set_full_serialization(Concept("foo"))
concept.set_prop("a", 10) # int
concept.set_value("a", 10) # int
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "props": [["a", 10]]}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["a", 10]]}'
concept = set_full_serialization(Concept("foo"))
concept.set_prop("a", set_full_serialization(Concept("bar"))) # another concept
concept.set_value("a", set_full_serialization(Concept("bar"))) # another concept
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "props": [["a", {"_sheerka/obj": "core.concept.Concept", "meta.name": "bar"}]]}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["a", {"_sheerka/obj": "core.concept.Concept", "meta.name": "bar"}]]}'
concept = set_full_serialization(Concept("foo"))
concept.set_prop("a", "a").set_prop("b", "b") # at least two props
concept.set_value("a", "a").set_value("b", "b") # at least two variables
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "props": [["a", "a"], ["b", "b"]]}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "foo", "values": [["a", "a"], ["b", "b"]]}'
def test_i_can_encode_decode_known_concepts(self):
sheerka = self.get_sheerka()
ref_concept = Concept("my_name", True, True, "my_key", "my_body", "my_where", "my_pre", "my_post", "my_def")
ref_concept.def_prop("a", "value_a").def_prop("b", "value_b")
ref_concept.def_var("a", "value_a").def_var("b", "value_b")
sheerka.create_new_concept(self.get_context(sheerka), ref_concept)
@@ -153,29 +154,30 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
# same test, modify a value and check if this modification is correctly saved
concept = Concept().update_from(sheerka.get_by_id(ref_concept.id))
concept.set_metadata_value(ConceptParts.BODY, set_full_serialization(Concept("bar")))
concept.set_value(ConceptParts.BODY, set_full_serialization(Concept("bar")))
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "concept/id": ["my_key", "1001"], "body": {"_sheerka/obj": "core.concept.Concept", "meta.name": "bar"}}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "concept/id": ["my_key", "1001"], "values": [["cParts.body", {"_sheerka/obj": "core.concept.Concept", "meta.name": "bar"}]]}'
def test_i_can_encode_decode_when_property_is_a_concept(self):
def test_i_can_encode_decode_when_variable_is_a_concept(self):
sheerka = self.get_sheerka()
foo = Concept("foo").init_key()
foo = Concept("foo")
sheerka.create_new_concept(self.get_context(sheerka), foo)
concept = Concept("my_name").init_key()
concept = Concept("my_name")
sheerka.create_new_concept(self.get_context(sheerka), concept)
concept.def_prop(foo, "a value")
concept.def_var(foo, "a value")
concept.set_value(foo, "another value")
concept.metadata.full_serialization = True
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "my_name", "meta.key": "my_name", ' + \
'"meta.props": [{"_sheerka/tuple": [{"_sheerka/obj": "core.concept.Concept", "concept/id": ["foo", "1001"]}, "a value"]}], ' + \
'"meta.id": "1002", "props": [[{"_sheerka/id": 1}, null]]}'
'"meta.variables": [[{"_sheerka/obj": "core.concept.Concept", "concept/id": ["foo", "1001"]}, "a value"]], ' + \
'"meta.id": "1002", "values": [[{"_sheerka/id": 1}, "another value"]]}'
def test_i_can_manage_reference_of_the_same_object(self):
sheerka = self.get_sheerka()
@@ -183,13 +185,13 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
concept_ref = set_full_serialization(Concept("foo"))
concept = set_full_serialization(Concept("bar"))
concept.set_metadata_value(ConceptParts.PRE, concept_ref)
concept.set_metadata_value(ConceptParts.BODY, concept_ref)
concept.set_value(ConceptParts.PRE, concept_ref)
concept.set_value(ConceptParts.BODY, concept_ref)
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "bar", "pre": {"_sheerka/obj": "core.concept.Concept", "meta.name": "foo"}, "body": {"_sheerka/id": 1}}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "bar", "values": [["cParts.pre", {"_sheerka/obj": "core.concept.Concept", "meta.name": "foo"}], ["cParts.body", {"_sheerka/id": 1}]]}'
def test_i_can_encode_decode_user_input(self):
sheerka = self.get_sheerka()
@@ -199,7 +201,7 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
to_string = sheerkapickle.encode(sheerka, user_input)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == user_input
assert to_string == '{"_sheerka/obj": "core.builtin_concepts.UserInputConcept", "concept/id": ["__USER_INPUT", null], "user_name": "my_user_name", "text": "my_text"}'
assert to_string == '{"_sheerka/obj": "core.builtin_concepts.UserInputConcept", "concept/id": ["__USER_INPUT", "11"], "user_name": "my_user_name", "text": "my_text"}'
def test_i_can_encode_decode_user_input_when_tokens(self):
sheerka = self.get_sheerka()
@@ -210,8 +212,8 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
to_string = sheerkapickle.encode(sheerka, user_input)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == UserInputConcept(text, "my_user_name")
assert to_string == '{' + f'"_sheerka/obj": "core.builtin_concepts.UserInputConcept", "concept/id": ["__USER_INPUT", null], "user_name": "my_user_name", "text": "{text}"' + '}'
assert decoded == sheerka.new(BuiltinConcepts.USER_INPUT, body=text, user_name="my_user_name")
assert to_string == '{' + f'"_sheerka/obj": "core.builtin_concepts.UserInputConcept", "concept/id": ["__USER_INPUT", "11"], "user_name": "my_user_name", "text": "{text}"' + '}'
def test_i_can_encode_decode_return_value(self):
sheerka = self.get_sheerka()
@@ -221,7 +223,7 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
to_string = sheerkapickle.encode(sheerka, ret_val)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == ret_val
assert to_string == '{"_sheerka/obj": "core.builtin_concepts.ReturnValueConcept", "concept/id": ["__RETURN_VALUE", null], "who": "who", "status": true, "value": 10}'
assert to_string == '{"_sheerka/obj": "core.builtin_concepts.ReturnValueConcept", "concept/id": ["__RETURN_VALUE", "16"], "who": "who", "status": true, "value": 10}'
def test_i_can_encode_decode_return_value_with_parent(self):
sheerka = self.get_sheerka()
@@ -234,7 +236,7 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == ret_val
assert decoded.parents == ret_val.parents
id_str = ', "concept/id": ["__RETURN_VALUE", null]'
id_str = ', "concept/id": ["__RETURN_VALUE", "16"]'
parents_str = '[{"_sheerka/obj": "core.builtin_concepts.ReturnValueConcept"' + id_str + ', "who": "parent_who", "status": true, "value": "10"}, {"_sheerka/id": 1}]'
assert to_string == '{"_sheerka/obj": "core.builtin_concepts.ReturnValueConcept"' + id_str + ', "who": "who", "status": true, "value": 10, "parents": ' + parents_str + '}'