Refactored Concept class for better separation of metadata, compiled and values
This commit is contained in:
+63
-62
@@ -5,7 +5,7 @@ import shutil
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept, ConceptAlreadyInSet, \
|
||||
ParserResultConcept
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property, ConceptParts, DoNotResolve
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property, ConceptParts, DoNotResolve, simplec
|
||||
from core.sheerka import Sheerka, ExecutionContext
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event
|
||||
@@ -49,8 +49,8 @@ def get_default_concept():
|
||||
post="isinstance(res, int)",
|
||||
body="def func(x,y):\n return x+y\nfunc(a,b)",
|
||||
desc="specific description")
|
||||
concept.set_prop("a", "value1")
|
||||
concept.set_prop("b", "value2")
|
||||
concept.def_prop("a", "value1")
|
||||
concept.def_prop("b", "value2")
|
||||
|
||||
return concept
|
||||
|
||||
@@ -238,7 +238,7 @@ def test_i_can_get_the_correct_concept_using_the_id_when_same_key_when_no_cache(
|
||||
|
||||
result = sheerka.get(concept1.key, res2.body.body.id)
|
||||
assert result.name == "a + b"
|
||||
assert result.body == "a+b"
|
||||
assert result.metadata.body == "a+b"
|
||||
|
||||
|
||||
def test_i_can_get_the_correct_concept_using_the_id__when_same_key_when_cache():
|
||||
@@ -254,7 +254,7 @@ def test_i_can_get_the_correct_concept_using_the_id__when_same_key_when_cache():
|
||||
|
||||
result = sheerka.get(concept1.key, res2.body.body.id)
|
||||
assert result.name == "a + b"
|
||||
assert result.body == "a+b"
|
||||
assert result.metadata.body == "a+b"
|
||||
|
||||
|
||||
def test_i_cannot_get_the_correct_concept_id_the_id_is_wrong():
|
||||
@@ -283,11 +283,12 @@ def test_i_cannot_get_when_key_is_none():
|
||||
def test_unknown_concept_is_return_when_the_concept_is_not_found():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
loaded = sheerka.get("fake_key")
|
||||
loaded = sheerka.get("concept_that_does_not_exist")
|
||||
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == "fake_key"
|
||||
assert loaded.body == "concept_that_does_not_exist"
|
||||
assert loaded.metadata.is_evaluated
|
||||
|
||||
|
||||
def test_i_can_instantiate_a_builtin_concept_when_it_has_its_own_class():
|
||||
@@ -335,10 +336,10 @@ def test_i_can_instantiate_with_the_name_and_the_id():
|
||||
assert len(concepts) == 2
|
||||
|
||||
foo1 = sheerka.new(("foo", "1001"))
|
||||
assert foo1.body == "foo1"
|
||||
assert foo1.metadata.body == "foo1"
|
||||
|
||||
foo2 = sheerka.new(("foo", "1002"))
|
||||
assert foo2.body == "foo2"
|
||||
assert foo2.metadata.body == "foo2"
|
||||
|
||||
|
||||
def test_instances_are_different_when_asking_for_new():
|
||||
@@ -403,7 +404,7 @@ def test_concept_id_is_irrelevant_when_only_one_concept():
|
||||
new = sheerka.new(("foo", "invalid_id"))
|
||||
|
||||
assert sheerka.isinstance(new, "foo")
|
||||
assert new.body == "foo1"
|
||||
assert new.metadata.body == "foo1"
|
||||
|
||||
|
||||
def test_i_cannot_instantiate_when_properties_are_not_recognized():
|
||||
@@ -439,6 +440,12 @@ def test_i_cannot_instantiate_when_properties_are_not_recognized():
|
||||
def test_i_can_get_value(concept, reduce_simple_list, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
# I use auto_init() instead of evaluate_concept() to be quicker
|
||||
c = concept
|
||||
while isinstance(c, Concept):
|
||||
c.auto_init()
|
||||
c = c.body
|
||||
|
||||
assert sheerka.value(concept, reduce_simple_list) == expected
|
||||
|
||||
|
||||
@@ -462,16 +469,18 @@ def test_list_of_concept_is_sorted_by_id():
|
||||
def test_i_can_evaluate_a_concept_with_simple_body(body, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo", body=body).init_key()
|
||||
concept = Concept("foo", body=body)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == expected
|
||||
assert evaluated.metadata.body == body
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.props == {}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert len(evaluated.values) == 0 if body is None else 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
@@ -493,20 +502,22 @@ def test_i_can_evaluate_the_other_metadata(expr, expected):
|
||||
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo", where=expr).init_key()
|
||||
concept = Concept("foo", where=expr)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body is None
|
||||
assert evaluated.metadata.body is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where == expected
|
||||
assert evaluated.metadata.where == expr
|
||||
assert evaluated.get_metadata_value(ConceptParts.WHERE) == expected
|
||||
assert evaluated.props == {}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert len(evaluated.values) == 0 if expr is None else 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
# (None, None),
|
||||
(None, None),
|
||||
("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
@@ -518,11 +529,11 @@ def test_i_can_evaluate_the_other_metadata(expr, expected):
|
||||
def test_i_can_evaluate_a_concept_with_prop(expr, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo").set_prop("a", expr).init_key()
|
||||
concept = Concept("foo").def_prop("a", expr)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
@@ -533,7 +544,7 @@ def test_i_can_evaluate_a_concept_with_prop(expr, expected):
|
||||
def test_i_can_evaluate_metadata_using_do_not_resolve():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept("foo")
|
||||
concept.cached_asts[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
@@ -543,8 +554,8 @@ def test_i_can_evaluate_metadata_using_do_not_resolve():
|
||||
|
||||
def test_i_can_evaluate_property_using_do_not_resolve():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept("foo").set_prop("a")
|
||||
concept.cached_asts["a"] = DoNotResolve("do not resolve")
|
||||
concept = Concept("foo").def_prop("a")
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
@@ -555,8 +566,8 @@ def test_i_can_evaluate_property_using_do_not_resolve():
|
||||
def test_original_value_is_overridden_when_using_do_no_resolve():
|
||||
sheerka = get_sheerka()
|
||||
concept = Concept("foo", body="original value").set_prop("a", "original value")
|
||||
concept.cached_asts["a"] = DoNotResolve("do not resolve")
|
||||
concept.cached_asts[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
@@ -568,7 +579,7 @@ def test_original_value_is_overridden_when_using_do_no_resolve():
|
||||
def test_props_are_evaluated_before_body():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept("foo", body="a+1").set_prop("a", "10").init_key()
|
||||
concept = Concept("foo", body="a+1").def_prop("a", "10").init_key()
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
@@ -583,8 +594,7 @@ def test_i_can_evaluate_when_another_concept_is_referenced():
|
||||
concept = Concept("foo", body="a").init_key()
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert sheerka.isinstance(evaluated.body, concept_a)
|
||||
assert evaluated == simplec("foo", simplec("a", None))
|
||||
assert id(evaluated.body) != id(concept_a)
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.body.metadata.is_evaluated
|
||||
@@ -595,11 +605,11 @@ def test_i_can_evaluate_when_the_referenced_concept_has_a_body():
|
||||
concept_a = Concept("a", body="1")
|
||||
sheerka.add_in_cache(concept_a)
|
||||
|
||||
concept = Concept("foo", body="a").init_key()
|
||||
concept = Concept("foo", body="a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == Concept("a", body=1).init_key()
|
||||
assert evaluated.body == simplec("a", 1)
|
||||
assert not concept_a.metadata.is_evaluated
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
@@ -614,13 +624,8 @@ def test_i_can_evaluate_concept_of_concept_when_the_leaf_has_a_body():
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept_d)
|
||||
|
||||
assert evaluated.key == concept_d.key
|
||||
assert evaluated.body == Concept(
|
||||
name="c",
|
||||
body=Concept(
|
||||
name="b",
|
||||
body=Concept(
|
||||
name="a",
|
||||
body="a").init_key()).init_key()).init_key()
|
||||
expected = simplec("c", simplec("b", simplec("a", "a")))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.value(evaluated) == 'a'
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
@@ -635,12 +640,8 @@ def test_i_can_evaluate_concept_of_concept_does_not_have_a_body():
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept_d)
|
||||
|
||||
assert evaluated.key == concept_d.key
|
||||
assert evaluated.body == Concept(
|
||||
name="c",
|
||||
body=Concept(
|
||||
name="b",
|
||||
body=Concept(
|
||||
name="a").init_key()).init_key()).init_key()
|
||||
expected = simplec("c", simplec("b", simplec("a", None)))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.value(evaluated) == Concept(name="a").init_key()
|
||||
assert evaluated.metadata.is_evaluated
|
||||
|
||||
@@ -649,7 +650,7 @@ def test_i_can_evaluate_concept_when_properties_reference_others_concepts():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a").init_key())
|
||||
|
||||
concept = Concept("foo", body="a").set_prop("a", "a").init_key()
|
||||
concept = Concept("foo", body="a").def_prop("a", "a").init_key()
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
# first prop a is evaluated to concept_a
|
||||
@@ -667,7 +668,7 @@ def test_i_can_evaluate_concept_when_properties_reference_others_concepts_2():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a"))
|
||||
|
||||
concept = Concept("foo", body="concept_a").set_prop("concept_a", "a")
|
||||
concept = Concept("foo", body="concept_a").def_prop("concept_a", "a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
@@ -679,7 +680,7 @@ def test_i_can_evaluate_concept_when_properties_reference_others_concepts_with_b
|
||||
sheerka.add_in_cache(Concept(name="a", body="1"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="2"))
|
||||
|
||||
concept = Concept("foo", body="propA + propB").set_prop("propA", "a").set_prop("propB", "b")
|
||||
concept = Concept("foo", body="propA + propB").def_prop("propA", "a").def_prop("propB", "b")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
@@ -690,24 +691,25 @@ def test_i_can_evaluate_concept_when_properties_is_a_concept():
|
||||
sheerka = get_sheerka()
|
||||
concept_a = sheerka.add_in_cache(Concept(name="a", body="'a'").init_key())
|
||||
|
||||
concept = Concept("foo").set_prop("a", concept_a)
|
||||
concept = Concept("foo").def_prop("a")
|
||||
concept.compiled["a"] = concept_a
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.get_prop("a") == Concept(name="a", body="a").init_key()
|
||||
assert evaluated.get_prop("a") == simplec("a", "a")
|
||||
|
||||
|
||||
def test_i_can_evaluate_when_property_asts_is_a_list():
|
||||
sheerka = get_sheerka()
|
||||
foo = Concept("foo", body="1")
|
||||
|
||||
concept = Concept("to_eval").set_prop("prop")
|
||||
concept.cached_asts["prop"] = [foo, DoNotResolve("1")]
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = [foo, DoNotResolve("1")]
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
|
||||
props = evaluated.get_prop("prop")
|
||||
assert len(props) == 2
|
||||
assert props[0] == Concept("foo", body=1).init_key()
|
||||
assert props[0] == simplec("foo", 1)
|
||||
assert props[1] == "1"
|
||||
|
||||
|
||||
@@ -717,14 +719,14 @@ def test_i_can_evaluate_when_compiled_is_set_up_with_return_value():
|
||||
python_node = PythonNode("1 +1 ")
|
||||
parser_result = ParserResultConcept(parser="who", value=python_node)
|
||||
|
||||
concept = Concept("to_eval").set_prop("prop")
|
||||
concept.cached_asts["prop"] = [ReturnValueConcept("who", True, parser_result)]
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = [ReturnValueConcept("who", True, parser_result)]
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.get_prop("prop") == 2
|
||||
|
||||
# also works when only one return value
|
||||
concept = Concept("to_eval").set_prop("prop")
|
||||
concept.cached_asts["prop"] = ReturnValueConcept("who", True, parser_result)
|
||||
concept = Concept("to_eval").def_prop("prop")
|
||||
concept.compiled["prop"] = ReturnValueConcept("who", True, parser_result)
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.get_prop("prop") == 2
|
||||
|
||||
@@ -747,19 +749,19 @@ def test_properties_values_takes_precedence_over_the_outside_world():
|
||||
concept = Concept("foo", body="a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == Concept(name="a", body="concept_a").init_key() # this test was already done
|
||||
assert evaluated.body == simplec("a", "concept_a") # this test was already done
|
||||
|
||||
# so check this one.
|
||||
concept = Concept("foo", body="a").set_prop("a", "'property_a'")
|
||||
concept = Concept("foo", body="a").def_prop("a", "'property_a'")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 'property_a'
|
||||
|
||||
# or this one.
|
||||
concept = Concept("foo", body="a").set_prop("a", "b")
|
||||
concept = Concept("foo", body="a").def_prop("a", "b")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == Concept(name="b", body="concept_b").init_key()
|
||||
assert evaluated.body == simplec(name="b", body="concept_b")
|
||||
|
||||
|
||||
def test_properties_values_takes_precedence():
|
||||
@@ -767,7 +769,7 @@ def test_properties_values_takes_precedence():
|
||||
sheerka.add_in_cache(Concept(name="a", body="'concept_a'"))
|
||||
sheerka.add_in_cache(Concept(name="b", body="'concept_b'"))
|
||||
|
||||
concept = Concept("foo", body="a + b").set_prop("a", "'prop_a'")
|
||||
concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 'prop_aconcept_b'
|
||||
@@ -775,18 +777,17 @@ def test_properties_values_takes_precedence():
|
||||
|
||||
def test_i_can_reference_sub_property_of_a_property():
|
||||
sheerka = get_sheerka()
|
||||
sheerka.add_in_cache(Concept(name="concept_a").set_prop("subProp", "'sub_a'"))
|
||||
sheerka.add_in_cache(Concept(name="concept_a").def_prop("subProp", "'sub_a'"))
|
||||
|
||||
concept = Concept("foo", body="a.props['subProp'].value").set_prop("a", "concept_a")
|
||||
concept = Concept("foo", body="a.props['subProp'].value").def_prop("a", "concept_a")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == 'sub_a'
|
||||
assert evaluated == simplec(concept.key, "sub_a")
|
||||
|
||||
|
||||
def test_i_cannot_evaluate_concept_if_property_is_in_error():
|
||||
sheerka = get_sheerka()
|
||||
|
||||
concept = Concept(name="concept_a").set_prop("subProp", "undef_concept")
|
||||
concept = Concept(name="concept_a").def_prop("subProp", "undef_concept")
|
||||
evaluated = sheerka.evaluate_concept(get_context(sheerka), concept)
|
||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user