We can now use concept sets in BNF definitions
This commit is contained in:
+72
-6
@@ -1,5 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from core.tokenizer import Tokenizer, TokenKind, LexerError
|
||||
@@ -17,6 +18,11 @@ def get_context():
|
||||
return ExecutionContext("sheerka", Event(), sheerka)
|
||||
|
||||
|
||||
class ClassWithName():
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("'str'", StrMatch("str")),
|
||||
("1", StrMatch("1")),
|
||||
@@ -41,12 +47,6 @@ def get_context():
|
||||
("(1|*) +", Sequence(OrderedChoice(StrMatch("1"), StrMatch("*")), StrMatch("+"))),
|
||||
("1, :&", Sequence(StrMatch("1"), StrMatch(","), StrMatch(":"), StrMatch("&"))),
|
||||
("(1 )", StrMatch("1")),
|
||||
("foo", ConceptExpression("foo")),
|
||||
("foo*", ZeroOrMore(ConceptExpression("foo"))),
|
||||
("foo 'and' bar+", Sequence(ConceptExpression("foo"), StrMatch("and"), OneOrMore(ConceptExpression("bar")))),
|
||||
("foo | bar?", OrderedChoice(ConceptExpression("foo"), Optional(ConceptExpression("bar")))),
|
||||
("'str' = var", Sequence(StrMatch("str"), StrMatch("="), ConceptExpression("var"))),
|
||||
("'str''='var", Sequence(StrMatch("str"), StrMatch("="), ConceptExpression("var"))),
|
||||
("'str'=var", StrMatch("str", rule_name="var")),
|
||||
("'foo'?=var", Optional(StrMatch("foo"), rule_name="var")),
|
||||
("('foo'?)=var", Optional(StrMatch("foo"), rule_name="var")),
|
||||
@@ -75,6 +75,47 @@ def test_i_can_parse_regex(expression, expected):
|
||||
assert res.value.source == expression
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("foo", Concept("foo").init_key()),
|
||||
("foo*", ZeroOrMore(Concept("foo").init_key())),
|
||||
("foo 'and' bar+", Sequence(Concept("foo").init_key(), StrMatch("and"), OneOrMore(Concept("bar").init_key()))),
|
||||
("foo | bar?", OrderedChoice(Concept("foo").init_key(), Optional(Concept("bar").init_key()))),
|
||||
("'str' = var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
|
||||
("'str''='var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
|
||||
])
|
||||
def test_i_can_parse_regex_with_concept(expression, expected):
|
||||
foo = Concept("foo")
|
||||
bar = Concept("bar")
|
||||
var = Concept("var")
|
||||
context = get_context()
|
||||
|
||||
for c in (foo, bar, var):
|
||||
context.sheerka.add_in_cache(c)
|
||||
parser = BnfParser()
|
||||
res = parser.parse(context, Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
|
||||
def test_i_can_parse_regex_with_concept_when_the_concept_is_still_under_definition():
|
||||
expression = "foo"
|
||||
expected = ConceptExpression("foo")
|
||||
|
||||
context = get_context()
|
||||
context.obj = ClassWithName("foo")
|
||||
|
||||
parser = BnfParser()
|
||||
res = parser.parse(context, Tokenizer(expression))
|
||||
|
||||
assert not parser.has_error
|
||||
assert res.status
|
||||
assert res.value.value == expected
|
||||
assert res.value.source == expression
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, error", [
|
||||
("1 ", UnexpectedEndOfFileError()),
|
||||
("1|", UnexpectedEndOfFileError()),
|
||||
@@ -117,3 +158,28 @@ def test_i_can_use_the_result_of_regex_parsing_to_parse_a_text():
|
||||
res = concept_parser.parse(context, "twenty")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("foo", 0, 0, "twenty")]
|
||||
|
||||
|
||||
def test_i_cannot_parse_when_too_many_concepts():
|
||||
foo1 = Concept(name="foo", body="1")
|
||||
foo2 = Concept(name="foo", body="2")
|
||||
context = get_context()
|
||||
context.sheerka.cache_by_key["foo"] = [foo1, foo2]
|
||||
|
||||
regex_parser = BnfParser()
|
||||
res = regex_parser.parse(context, "foo")
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CANNOT_RESOLVE_CONCEPT)
|
||||
assert res.value.body == ('key', 'foo')
|
||||
|
||||
|
||||
def test_i_cannot_parse_when_unknown_concept():
|
||||
context = get_context()
|
||||
|
||||
regex_parser = BnfParser()
|
||||
res = regex_parser.parse(get_context(), "foo")
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == ('key', 'foo')
|
||||
|
||||
@@ -61,6 +61,7 @@ def get_expected(concept, text=None):
|
||||
c = Concept(name=concept.name)
|
||||
c.compiled[ConceptParts.BODY] = DoNotResolve(text or concept.name)
|
||||
c.init_key()
|
||||
c.metadata.id = concept.id
|
||||
return c
|
||||
|
||||
|
||||
@@ -606,9 +607,6 @@ def test_i_can_parse_concept_reference_that_is_not_in_grammar():
|
||||
grammar = {foo: Sequence("twenty", OrderedChoice(one, two))}
|
||||
context, parser = init([one, two, foo], grammar)
|
||||
|
||||
parser = ConceptLexerParser()
|
||||
parser.initialize(context, grammar)
|
||||
|
||||
res = parser.parse(context, "twenty two")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("foo", 0, 2, "twenty two")]
|
||||
@@ -621,6 +619,46 @@ def test_i_can_parse_concept_reference_that_is_not_in_grammar():
|
||||
assert res.value.body == [cnode("foo", 0, 2, "twenty one")]
|
||||
|
||||
|
||||
def test_i_can_parse_concept_reference_that_is_group():
|
||||
"""
|
||||
if one is number, then number is a 'group'
|
||||
a group can be found under the sdp entry 'all_<group_name>'
|
||||
"""
|
||||
|
||||
context = get_context()
|
||||
one = Concept(name="one")
|
||||
two = Concept(name="two")
|
||||
number = Concept(name="number")
|
||||
foo = Concept(name="foo")
|
||||
for c in [one, two, number, foo]:
|
||||
context.sheerka.set_id_if_needed(c, False)
|
||||
context.sheerka.add_in_cache(c)
|
||||
|
||||
context.sheerka.add_concept_to_set(context, one, number)
|
||||
context.sheerka.add_concept_to_set(context, two, number)
|
||||
|
||||
grammar = {foo: Sequence("twenty", number)}
|
||||
|
||||
parser = ConceptLexerParser()
|
||||
parser.initialize(context, grammar)
|
||||
|
||||
res = parser.parse(context, "twenty two")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("foo", 0, 2, "twenty two")]
|
||||
concept_found = res.value.body[0].concept
|
||||
assert cbody(concept_found) == DoNotResolve("twenty two")
|
||||
assert cprop(concept_found, "two") == get_expected(two, "two")
|
||||
assert cprop(concept_found, "number") == get_expected(number, get_expected(two, "two"))
|
||||
|
||||
res = parser.parse(context, "twenty one")
|
||||
assert res.status
|
||||
assert res.value.body == [cnode("foo", 0, 2, "twenty one")]
|
||||
concept_found = res.value.body[0].concept
|
||||
assert cbody(concept_found) == DoNotResolve("twenty one")
|
||||
assert cprop(concept_found, "one") == get_expected(one, "one")
|
||||
assert cprop(concept_found, "number") == get_expected(number, get_expected(one, "one"))
|
||||
|
||||
|
||||
def test_i_can_parse_zero_or_more():
|
||||
foo = Concept(name="foo")
|
||||
grammar = {foo: ZeroOrMore("one")}
|
||||
|
||||
@@ -2,6 +2,7 @@ import pytest
|
||||
import ast
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from parsers.ConceptLexerParser import OrderedChoice, StrMatch, ConceptExpression
|
||||
from parsers.PythonParser import PythonParser, PythonNode
|
||||
@@ -191,8 +192,7 @@ def concept add one to a as
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert sheerka.isinstance(return_value.value[0], BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
assert context.sheerka.isinstance(return_value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
|
||||
|
||||
def test_name_is_mandatory():
|
||||
@@ -239,8 +239,7 @@ def test_i_can_detect_error_in_declaration(text):
|
||||
return_value = res.value
|
||||
|
||||
assert not res.status
|
||||
assert isinstance(return_value, ParserResultConcept)
|
||||
assert sheerka.isinstance(return_value.value[0], BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
assert sheerka.isinstance(return_value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
|
||||
|
||||
def test_new_line_is_not_allowed_in_the_name():
|
||||
@@ -255,11 +254,15 @@ def test_new_line_is_not_allowed_in_the_name():
|
||||
|
||||
|
||||
def test_i_can_parse_def_concept_from_regex():
|
||||
context = get_context()
|
||||
a_concept = Concept("a_concept")
|
||||
context.sheerka.add_in_cache(a_concept)
|
||||
|
||||
text = "def concept name from bnf a_concept | 'a_string' as __definition[0]"
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
res = parser.parse(context, text)
|
||||
node = res.value.value
|
||||
definition = OrderedChoice(ConceptExpression("a_concept"), StrMatch("a_string"))
|
||||
definition = OrderedChoice(a_concept, StrMatch("a_string"))
|
||||
parser_result = ParserResultConcept(BnfParser(), "a_concept | 'a_string'", definition, definition)
|
||||
expected = get_def_concept(name="name", body="__definition[0]", definition=parser_result)
|
||||
|
||||
@@ -270,6 +273,18 @@ def test_i_can_parse_def_concept_from_regex():
|
||||
assert node == expected
|
||||
|
||||
|
||||
def test_i_can_parse_def_concept_where_bnf_references_itself():
|
||||
context = get_context()
|
||||
a_concept = Concept("a_concept")
|
||||
context.sheerka.add_in_cache(a_concept)
|
||||
|
||||
text = "def concept name from bnf 'a' + name?"
|
||||
parser = DefaultParser()
|
||||
parser.parse(context, text)
|
||||
|
||||
assert not parser.has_error
|
||||
|
||||
|
||||
def test_i_can_detect_empty_bnf_declaration():
|
||||
text = "def concept name from bnf as __definition[0]"
|
||||
|
||||
@@ -339,3 +354,15 @@ def test_i_cannot_parse_when_tokenizer_fails(text, error_msg, error_text):
|
||||
assert isinstance(res.body.body[0], LexerError)
|
||||
assert res.body.body[0].message == error_msg
|
||||
assert res.body.body[0].text == error_text
|
||||
|
||||
|
||||
def test_i_cannot_parse_bnf_definition_referencing_unknown_concept():
|
||||
context = get_context()
|
||||
text = "def concept name from bnf unknown"
|
||||
|
||||
parser = DefaultParser()
|
||||
res = parser.parse(context, text)
|
||||
|
||||
assert not res.status
|
||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert res.value.body == ("key", "unknown")
|
||||
|
||||
@@ -90,7 +90,7 @@ def test_i_can_recognize_a_concept_with_variables():
|
||||
def test_i_can_recognize_a_concept_with_duplicate_variables():
|
||||
context = get_context()
|
||||
concept = get_concept("a + b + a", ["a", "b"])
|
||||
context.sheerka.concepts_cache[concept.key] = concept
|
||||
context.sheerka.cache_by_key[concept.key] = concept
|
||||
source = "10 + 5 + 10"
|
||||
results = ExactConceptParser().parse(context, source)
|
||||
|
||||
|
||||
@@ -50,8 +50,6 @@ def test_i_can_parse_from_tokens(text, expected):
|
||||
"foo = 'name"
|
||||
])
|
||||
def test_i_can_detect_error(text):
|
||||
text = "1+"
|
||||
|
||||
parser = PythonParser()
|
||||
res = parser.parse(get_context(), text)
|
||||
|
||||
|
||||
+99
-17
@@ -76,13 +76,13 @@ def test_i_can_list_builtin_concepts():
|
||||
|
||||
def test_builtin_concepts_are_initialized():
|
||||
sheerka = get_sheerka(skip_builtins_in_db=False)
|
||||
assert len(sheerka.concepts_cache) == len(BuiltinConcepts)
|
||||
assert len(sheerka.cache_by_key) == len(BuiltinConcepts)
|
||||
for concept_name in BuiltinConcepts:
|
||||
assert str(concept_name) in sheerka.concepts_cache
|
||||
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.concepts_cache[key], concept_class)
|
||||
assert isinstance(sheerka.cache_by_key[key], concept_class)
|
||||
|
||||
|
||||
def test_builtin_concepts_can_be_updated():
|
||||
@@ -113,7 +113,8 @@ def test_i_can_add_a_concept():
|
||||
assert concept_found.key == "__var__0 + __var__1"
|
||||
assert concept_found.id == "1001"
|
||||
|
||||
assert concept.key in sheerka.concepts_cache
|
||||
assert concept.key in sheerka.cache_by_key
|
||||
assert concept.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_found.get_digest()))
|
||||
|
||||
@@ -154,7 +155,10 @@ def test_i_can_get_a_newly_created_concept():
|
||||
|
||||
from_cache = sheerka.get(concept.key)
|
||||
assert from_cache is not None
|
||||
assert from_cache.key == concept.key
|
||||
assert from_cache == concept
|
||||
|
||||
from_cache = sheerka.get_by_id(concept.id)
|
||||
assert from_cache is not None
|
||||
assert from_cache == concept
|
||||
|
||||
|
||||
@@ -163,7 +167,7 @@ def test_i_first_look_in_local_cache():
|
||||
concept = get_default_concept()
|
||||
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
sheerka.concepts_cache[concept.key].pre = "I have modified the concept in cache"
|
||||
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
|
||||
@@ -180,12 +184,29 @@ def test_i_can_get_a_known_concept_when_not_in_cache():
|
||||
concept = get_default_concept()
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
sheerka.concepts_cache = {} # reset the cache
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
loaded = sheerka.get(concept.key)
|
||||
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
# I can also get it by its id
|
||||
loaded = sheerka.sdp.get(sheerka.CONCEPTS_BY_ID_ENTRY, concept.id)
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
|
||||
def test_i_can_get_a_concept_by_its_id():
|
||||
sheerka = get_sheerka()
|
||||
concept = get_default_concept()
|
||||
sheerka.create_new_concept(get_context(sheerka), concept)
|
||||
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
loaded = sheerka.get_by_id(concept.id)
|
||||
|
||||
assert loaded is not None
|
||||
assert loaded == concept
|
||||
|
||||
|
||||
def test_i_can_get_list_of_concept_when_same_key_when_no_cache():
|
||||
sheerka = get_sheerka()
|
||||
@@ -198,7 +219,7 @@ def test_i_can_get_list_of_concept_when_same_key_when_no_cache():
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
sheerka.concepts_cache = {} # reset the cache
|
||||
sheerka.cache_by_key = {} # reset the cache
|
||||
|
||||
result = sheerka.get(concept1.key)
|
||||
assert len(result) == 2
|
||||
@@ -217,7 +238,7 @@ def test_i_can_get_list_of_concept_when_same_key_when_cache():
|
||||
|
||||
assert res1.value.body.key == res2.value.body.key # same key
|
||||
|
||||
# sheerka.concepts_cache = {} # Do not reset the cache
|
||||
# sheerka.cache_by_key = {} # Do not reset the cache
|
||||
|
||||
result = sheerka.get(concept1.key)
|
||||
assert len(result) == 2
|
||||
@@ -280,14 +301,25 @@ def test_i_cannot_get_when_key_is_none():
|
||||
assert res.body == "Concept key is undefined."
|
||||
|
||||
|
||||
def test_unknown_concept_is_return_when_the_concept_is_not_found():
|
||||
def test_unknown_concept_is_return_when_the_concept_key_is_not_found():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
loaded = sheerka.get("concept_that_does_not_exist")
|
||||
loaded = sheerka.get("key_that_does_not_exist")
|
||||
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == "concept_that_does_not_exist"
|
||||
assert loaded.body == ("key", "key_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_unknown_concept_is_return_when_the_concept_id_is_not_found():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
loaded = sheerka.get_by_id("id_that_does_not_exist")
|
||||
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == ("id", "id_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
|
||||
|
||||
@@ -372,7 +404,7 @@ def test_i_cannot_instantiate_an_unknown_concept():
|
||||
new = sheerka.new("fake_concept")
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == "fake_concept"
|
||||
assert new.body == ('key', 'fake_concept')
|
||||
|
||||
|
||||
def test_i_cannot_instantiate_with_invalid_id():
|
||||
@@ -383,7 +415,7 @@ def test_i_cannot_instantiate_with_invalid_id():
|
||||
new = sheerka.new(("foo", "invalid_id"))
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == "foo"
|
||||
assert new.body == [('key', 'foo'), ('id', 'invalid_id')]
|
||||
|
||||
|
||||
def test_i_cannot_instantiate_with_invalid_key():
|
||||
@@ -394,7 +426,7 @@ def test_i_cannot_instantiate_with_invalid_key():
|
||||
new = sheerka.new(("invalid_key", "1001"))
|
||||
|
||||
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert new.body == "invalid_key"
|
||||
assert new.body == [('key', 'invalid_key'), ('id', '1001')]
|
||||
|
||||
|
||||
def test_concept_id_is_irrelevant_when_only_one_concept():
|
||||
@@ -457,8 +489,8 @@ def test_list_of_concept_is_sorted_by_id():
|
||||
|
||||
|
||||
@pytest.mark.parametrize("body, expected", [
|
||||
(None, None),
|
||||
("", ""),
|
||||
# (None, None),
|
||||
# ("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
("'one'", "one"),
|
||||
@@ -871,3 +903,53 @@ def test_i_cannot_add_the_same_concept_twice_in_a_set():
|
||||
all_entries = sheerka.sdp.get("All_" + all_foos.id, None, False)
|
||||
assert len(all_entries) == 1
|
||||
assert foo.id in all_entries
|
||||
|
||||
|
||||
def test_i_get_elements_from_a_set():
|
||||
sheerka = get_sheerka(False, False)
|
||||
|
||||
one = Concept("one")
|
||||
two = Concept("two")
|
||||
three = Concept("three")
|
||||
number = Concept("number")
|
||||
|
||||
for c in [one, two, three, number]:
|
||||
sheerka.set_id_if_needed(c, False)
|
||||
sheerka.add_in_cache(c)
|
||||
|
||||
context = get_context(sheerka)
|
||||
for c in [one, two, three]:
|
||||
sheerka.add_concept_to_set(context, c, number)
|
||||
|
||||
elements = sheerka.get_set_elements(number)
|
||||
|
||||
assert set(elements) == set([one, two, three])
|
||||
|
||||
|
||||
def test_i_cannot_get_elements_if_not_a_set():
|
||||
sheerka = get_sheerka(False, False)
|
||||
one = Concept("one")
|
||||
sheerka.set_id_if_needed(one, False)
|
||||
sheerka.add_in_cache(one)
|
||||
|
||||
error = sheerka.get_set_elements(one)
|
||||
|
||||
assert sheerka.isinstance(error, BuiltinConcepts.NOT_A_SET)
|
||||
assert error.body == one
|
||||
|
||||
|
||||
def test_isa_and_isa_group():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
group = Concept("group").init_key()
|
||||
group.metadata.id = "1001"
|
||||
assert not sheerka.isagroup(group)
|
||||
|
||||
foo = Concept("foo").init_key()
|
||||
foo.metadata.id = "1002"
|
||||
assert not sheerka.isa(foo, group)
|
||||
|
||||
context = get_context(sheerka)
|
||||
sheerka.add_concept_to_set(context, foo, group)
|
||||
assert sheerka.isagroup(group)
|
||||
assert sheerka.isa(foo, group)
|
||||
|
||||
@@ -164,7 +164,7 @@ class ObjWithDigestWithKey:
|
||||
return hash((self.a, self.b))
|
||||
|
||||
def __eq__(self, obj):
|
||||
return isinstance(obj, ObjNoKey) and \
|
||||
return isinstance(obj, ObjWithDigestWithKey) and \
|
||||
self.a == obj.a and \
|
||||
self.b == obj.b
|
||||
|
||||
@@ -529,6 +529,44 @@ def test_i_can_add_obj_with_key_to_a_list(root):
|
||||
assert loaded == ["foo", "bar", ObjWithKey("a", "b")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
])
|
||||
def test_i_can_add_a_reference(root):
|
||||
sdp = SheerkaDataProvider(root)
|
||||
sdp.serializer.register(PickleSerializer(lambda o: isinstance(o, ObjWithDigestWithKey)))
|
||||
obj1 = ObjWithDigestWithKey(1, "foo")
|
||||
sdp.add(evt_digest, "entry", obj1, use_ref=True)
|
||||
sdp.add(evt_digest, "entry_by_value", {obj1.b: obj1.get_digest()}, is_ref=True)
|
||||
|
||||
# another object
|
||||
obj2 = ObjWithDigestWithKey(2, "bar")
|
||||
sdp.add(evt_digest, "entry", obj2, use_ref=True)
|
||||
sdp.add(evt_digest, "entry_by_value", {obj2.b: obj2.get_digest()}, is_ref=True)
|
||||
|
||||
state = sdp.load_state(sdp.get_snapshot())
|
||||
assert state.data == {
|
||||
"entry": {
|
||||
"1": '##REF##:' + obj1.get_digest(),
|
||||
"2": '##REF##:' + obj2.get_digest(),
|
||||
},
|
||||
"entry_by_value": {
|
||||
"foo": '##REF##:' + obj1.get_digest(),
|
||||
"bar": '##REF##:' + obj2.get_digest()
|
||||
},
|
||||
}
|
||||
|
||||
# sanity check, make sure that I can load back
|
||||
loaded1 = sdp.get("entry_by_value", "foo")
|
||||
assert loaded1 == ObjWithDigestWithKey(1, "foo")
|
||||
assert getattr(loaded1, Serializer.ORIGIN) == obj1.get_digest()
|
||||
|
||||
loaded2 = sdp.get("entry_by_value", "bar")
|
||||
assert loaded2 == ObjWithDigestWithKey(2, "bar")
|
||||
assert getattr(loaded2, Serializer.ORIGIN) == obj2.get_digest()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
@@ -650,6 +688,20 @@ def test_i_cannot_add_the_same_digest_twice_in_the_same_entry4(root):
|
||||
assert error.value.args[0] == "Duplicate object."
|
||||
|
||||
|
||||
def test_i_cannot_add_using_use_ref_and_is_ref():
|
||||
sdp = SheerkaDataProvider("mem://")
|
||||
|
||||
with pytest.raises(SheerkaDataProviderError) as error:
|
||||
sdp.add(evt_digest, "entry", ObjWithDigestWithKey("a", "b"), use_ref=True, is_ref=True)
|
||||
|
||||
|
||||
def test_i_cannot_add_using_is_ref_if_obj_is_not_a_dictionary():
|
||||
sdp = SheerkaDataProvider("mem://")
|
||||
|
||||
with pytest.raises(SheerkaDataProviderError) as error:
|
||||
sdp.add(evt_digest, "entry", ObjWithDigestWithKey("a", "b"), is_ref=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
@@ -782,6 +834,43 @@ def test_i_can_set_using_reference(root):
|
||||
assert getattr(loaded, Serializer.ORIGIN) == "95b5cbab545dded0b90b57a3d15a157b9a559fb586ee2f8d6ccbc6d2491f1268"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
])
|
||||
def test_i_can_set_a_reference(root):
|
||||
sdp = SheerkaDataProvider(root)
|
||||
sdp.serializer.register(PickleSerializer(lambda o: isinstance(o, ObjWithDigestWithKey)))
|
||||
obj = ObjWithDigestWithKey(1, "foo")
|
||||
sdp.add(evt_digest, "entry", obj, use_ref=True)
|
||||
sdp.set(evt_digest, "entry_by_value", {obj.b: obj.get_digest()}, is_ref=True)
|
||||
|
||||
state = sdp.load_state(sdp.get_snapshot())
|
||||
assert state.data == {
|
||||
"entry": {"1": '##REF##:' + obj.get_digest()},
|
||||
"entry_by_value": {"foo": '##REF##:' + obj.get_digest()},
|
||||
}
|
||||
|
||||
# sanity check, make sure that I can load back
|
||||
loaded = sdp.get("entry_by_value", "foo")
|
||||
assert loaded == ObjWithDigestWithKey(1, "foo")
|
||||
assert getattr(loaded, Serializer.ORIGIN) == obj.get_digest()
|
||||
|
||||
|
||||
def test_i_cannot_set_using_use_ref_and_is_ref():
|
||||
sdp = SheerkaDataProvider("mem://")
|
||||
|
||||
with pytest.raises(SheerkaDataProviderError) as error:
|
||||
sdp.set(evt_digest, "entry", ObjWithDigestWithKey("a", "b"), use_ref=True, is_ref=True)
|
||||
|
||||
|
||||
def test_i_cannot_set_using_is_ref_if_obj_is_not_a_dictionary():
|
||||
sdp = SheerkaDataProvider("mem://")
|
||||
|
||||
with pytest.raises(SheerkaDataProviderError) as error:
|
||||
sdp.set(evt_digest, "entry", ObjWithDigestWithKey("a", "b"), is_ref=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root", [
|
||||
".sheerka",
|
||||
"mem://"
|
||||
|
||||
@@ -18,8 +18,8 @@ def get_context(sheerka):
|
||||
|
||||
def get_ret_val(sheerka, concept, who="who"):
|
||||
concept.init_key()
|
||||
if concept.key not in sheerka.concepts_cache:
|
||||
sheerka.concepts_cache[concept.key] = concept
|
||||
if concept.key not in sheerka.cache_by_key:
|
||||
sheerka.cache_by_key[concept.key] = concept
|
||||
return sheerka.ret(who, True, sheerka.new(concept.key))
|
||||
|
||||
|
||||
|
||||
@@ -152,7 +152,8 @@ as:
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||
|
||||
assert concept_saved.key in sheerka.concepts_cache
|
||||
assert concept_saved.key in sheerka.cache_by_key
|
||||
assert concept_saved.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_digest()))
|
||||
|
||||
@@ -182,7 +183,8 @@ def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept()
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||
|
||||
assert concept_saved.key in sheerka.concepts_cache
|
||||
assert concept_saved.key in sheerka.cache_by_key
|
||||
assert concept_saved.id in sheerka.cache_by_id
|
||||
assert sheerka.sdp.io.exists(
|
||||
sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_digest()))
|
||||
|
||||
@@ -331,8 +333,7 @@ def test_i_can_create_concept_with_bnf_definition():
|
||||
|
||||
saved_definitions = sheerka.sdp.get_safe(sheerka.CONCEPTS_DEFINITIONS_ENTRY)
|
||||
expected_bnf = Sequence(
|
||||
ConceptExpression("a", rule_name="a"),
|
||||
Optional(Sequence(StrMatch("plus"), ConceptExpression("plus", rule_name="plus"))))
|
||||
a, Optional(Sequence(StrMatch("plus"), ConceptExpression("plus", rule_name="plus"))))
|
||||
assert saved_definitions[saved_concept] == expected_bnf
|
||||
|
||||
new_concept = res[0].value.body
|
||||
@@ -421,6 +422,23 @@ def test_i_can_eval_bnf_definitions_from_separate_instances():
|
||||
"def concept digit from bnf one|two",
|
||||
"def concept twenties from bnf twenty digit as twenty + digit"
|
||||
]),
|
||||
("When using isa and concept twenty", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"two isa number",
|
||||
"def concept twenties from bnf 'twenty' number as 20 + number"
|
||||
]),
|
||||
("When using isa and concept twenty", [
|
||||
"def concept one as 1",
|
||||
"def concept two as 2",
|
||||
"def concept twenty as 20",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"two isa number",
|
||||
"def concept twenties from bnf twenty number as 20 + number"
|
||||
]),
|
||||
])
|
||||
def test_i_can_mix_concept_with_python_to_define_numbers(desc, definitions):
|
||||
sheerka = get_sheerka()
|
||||
@@ -460,6 +478,50 @@ def test_i_can_mix_concept_with_python_to_define_numbers(desc, definitions):
|
||||
assert res[0].body == 23
|
||||
|
||||
|
||||
def test_i_can_mix_bnf_and_isa():
|
||||
"""
|
||||
if 'one' isa 'number, twenty number should be recognized
|
||||
:return:
|
||||
"""
|
||||
sheerka = get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("def concept two as 2")
|
||||
sheerka.evaluate_user_input("def concept number")
|
||||
sheerka.evaluate_user_input("one isa number")
|
||||
sheerka.evaluate_user_input("two isa number")
|
||||
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' number as 20 + number")
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == simplec("twenties", 21)
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + 1")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("twenty one + twenty two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 43
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 22
|
||||
|
||||
res = sheerka.evaluate_user_input("1 + 1 + twenty one")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 23
|
||||
|
||||
|
||||
def test_i_can_mix_concept_of_concept():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user