Refactored Concept class for better separation of metadata, compiled and values

This commit is contained in:
2020-01-17 17:27:54 +01:00
parent 3789ef25d1
commit a7b239c167
27 changed files with 614 additions and 349 deletions
+13 -11
View File
@@ -21,7 +21,7 @@ def get_context():
return ExecutionContext("test", Event(), sheerka)
def get_concept(name, where=None, pre=None, post=None, body=None, definition=None):
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None):
concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
if body:
@@ -87,7 +87,7 @@ def test_i_can_match(ret_val, expected):
def test_that_the_source_is_correctly_set():
context = get_context()
def_concept_return_value = get_concept(
def_concept_return_value = get_def_concept(
name="hello a",
definition=get_concept_definition("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
where="isinstance(a, str )",
@@ -132,21 +132,22 @@ def test_that_the_source_is_correctly_set():
#
# created_concept = evaluated.body.body
#
# assert ConceptParts.WHERE in created_concept.cached_asts
# assert ConceptParts.PRE in created_concept.cached_asts
# assert ConceptParts.BODY in created_concept.cached_asts
# assert ConceptParts.POST not in created_concept.cached_asts
# assert ConceptParts.WHERE in created_concept.compiled
# assert ConceptParts.PRE in created_concept.compiled
# assert ConceptParts.BODY in created_concept.compiled
# assert ConceptParts.POST not in created_concept.compiled
def test_that_the_new_concept_is_correctly_saved():
def test_that_the_new_concept_is_correctly_saved_in_db():
context = get_context()
def_concept_return_value = get_concept(
def_concept_return_value = get_def_concept(
name="hello a",
definition=get_concept_definition("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
where="isinstance(a, str )",
pre="a is not None",
body="print('hello' + a)")
# sanity. Make sure that the concept does not already exist
from_db = context.sheerka.get("hello " + VARIABLE_PREFIX + "0")
assert context.sheerka.isinstance(from_db, BuiltinConcepts.UNKNOWN_CONCEPT)
@@ -161,10 +162,11 @@ def test_that_the_new_concept_is_correctly_saved():
assert from_db.metadata.post is None
assert from_db.metadata.body == "print('hello' + a)"
assert from_db.metadata.definition == "hello a"
assert len(from_db.props) == 1
assert len(from_db.metadata.props) == 1
assert from_db.metadata.props[0] == ("a", None)
assert "a" in from_db.props
assert from_db.cached_asts == {} # ast is not saved in db
assert from_db.compiled == {} # ast is not saved in db
def test_i_can_get_props_from_python_node():
@@ -175,7 +177,7 @@ def test_i_can_get_props_from_python_node():
def test_i_can_get_props_from_another_concept():
concept = Concept("hello").set_prop("a").set_prop("b")
concept = Concept("hello").def_prop("a").def_prop("b")
ret_val = ReturnValueConcept(who="some_parser",
status=True,
value=ParserResultConcept(value=concept))
+11 -9
View File
@@ -1,10 +1,9 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import Concept
from core.concept import Concept, ConceptParts
from core.sheerka import Sheerka, ExecutionContext
from evaluators.ConceptEvaluator import ConceptEvaluator
from parsers.BaseParser import BaseParser
from parsers.ExactConceptParser import ExactConceptParser
from sdp.sheerkaDataProvider import Event
@@ -41,7 +40,7 @@ def test_i_can_evaluate_concept():
concept = Concept(name="foo",
where="1",
pre="2",
post="3").set_prop("a", "4").set_prop("b", "5")
post="3").def_prop("a", "4").def_prop("b", "5")
evaluator = ConceptEvaluator()
item = get_return_value(concept)
@@ -49,10 +48,13 @@ def test_i_can_evaluate_concept():
assert result.who == evaluator.name
assert result.status
assert result.value == Concept(name="foo",
where=1,
pre=2,
post=3).set_prop("a", 4).set_prop("b", 5).init_key()
assert result.value.name == "foo"
assert result.value.get_metadata_value(ConceptParts.WHERE) == 1
assert result.value.get_metadata_value(ConceptParts.PRE) == 2
assert result.value.get_metadata_value(ConceptParts.POST) == 3
assert result.value.get_prop("a") == 4
assert result.value.get_prop("b") == 5
assert result.value.key == "foo"
assert result.parents == [item]
@@ -111,8 +113,8 @@ def test_i_cannot_recognize_a_concept_if_one_of_the_prop_is_unknown():
context = get_context()
context.sheerka.add_in_cache(Concept(name="one").init_key())
concept_plus = context.sheerka.add_in_cache(Concept(name="a plus b")
.set_prop("a", "one")
.set_prop("b", "two").init_key())
.def_prop("a", "one")
.def_prop("b", "two").init_key())
evaluator = ConceptEvaluator()
item = get_return_value(concept_plus)
+10 -7
View File
@@ -59,19 +59,21 @@ def get_context():
def get_expected(concept, text=None):
c = Concept(name=concept.name)
c.cached_asts[ConceptParts.BODY] = DoNotResolve(text or concept.name)
c.compiled[ConceptParts.BODY] = DoNotResolve(text or concept.name)
c.init_key()
return c
def cbody(concept):
"""cbody stands for compiled body"""
return concept.cached_asts[ConceptParts.BODY]
if not ConceptParts.BODY in concept.compiled:
return None
return concept.compiled[ConceptParts.BODY]
def cprop(concept, prop_name):
"""cbody stands for compiled property"""
return concept.cached_asts[prop_name]
return concept.compiled[prop_name]
def init(concepts, grammar):
@@ -402,14 +404,15 @@ def test_i_can_use_a_reference_with_a_body():
assert context.sheerka.isinstance(res[0].value, BuiltinConcepts.PARSER_RESULT)
assert res[0].value.body == [cnode("foo", 0, 2, "one two")]
concept_found_1 = res[0].value.body[0].concept
assert concept_found_1.body == "'foo'"
assert concept_found_1.metadata.body == "'foo'"
assert cbody(concept_found_1) is None
assert res[1].status
assert context.sheerka.isinstance(res[1].value, BuiltinConcepts.PARSER_RESULT)
assert res[1].value.body == [cnode("bar", 0, 2, "one two")]
concept_found_2 = res[1].value.body[0].concept
# the body and the prop['foo'] are the same concept 'foo'
assert cbody(concept_found_2) == foo
# the body and the prop['foo'] are the same concept 'foo'
assert id(cprop(concept_found_2, "foo")) == id(cbody(concept_found_2))
@@ -513,7 +516,7 @@ def test_i_can_parse_when_reference_has_a_body():
assert res.status
assert res.value.body == [cnode("foo", 0, 0, "twenty")]
concept_found = res.value.body[0].concept
assert concept_found.body == "'one'"
assert concept_found.metadata.body == "'one'"
def test_i_can_parse_multiple_results():
@@ -1089,7 +1092,7 @@ def test_i_get_multiple_props_when_zero_or_more():
assert return_value == [cnode("foo", 0, 4, "one one one")]
concept_found = return_value[0].concept
assert cbody(concept_found) == DoNotResolve("one one one")
assert len(concept_found.cached_asts["one"]) == 3
assert len(concept_found.compiled["one"]) == 3
assert cprop(concept_found, "one")[0] == get_expected(one)
assert cprop(concept_found, "one")[1] == get_expected(one)
assert cprop(concept_found, "one")[2] == get_expected(one)
+15 -15
View File
@@ -86,7 +86,7 @@ def test_not_interested(text, interested):
def test_i_can_parse_composition_of_concepts():
foo = Concept("foo")
bar = Concept("bar")
plus = Concept("a plus b").set_prop("a").set_prop("b")
plus = Concept("a plus b").def_prop("a").def_prop("b")
context, parser, result, wrapper, return_value = execute([foo, bar, plus], [foo, " plus ", bar])
@@ -96,8 +96,8 @@ def test_i_can_parse_composition_of_concepts():
assert wrapper.source == "foo plus bar"
assert context.sheerka.isinstance(return_value, plus)
assert return_value.cached_asts["a"] == foo
assert return_value.cached_asts["b"] == bar
assert return_value.compiled["a"] == foo
assert return_value.compiled["b"] == bar
# sanity check, I can evaluate the result
evaluated = context.sheerka.evaluate_concept(context, return_value)
@@ -107,7 +107,7 @@ def test_i_can_parse_composition_of_concepts():
def test_i_can_parse_when_composition_of_source_code():
plus = Concept("a plus b", body="a + b").set_prop("a").set_prop("b")
plus = Concept("a plus b", body="a + b").def_prop("a").def_prop("b")
left = PythonNode("1+1", ast.parse("1+1", mode="eval"))
right = PythonNode("2+2", ast.parse("2+2", mode="eval"))
context, parser, result, wrapper, return_value = execute([plus], [left, " plus ", right])
@@ -120,8 +120,8 @@ def test_i_can_parse_when_composition_of_source_code():
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.cached_asts["a"] == [ReturnValueConcept(parser.name, True, left_parser_result)]
assert return_value.cached_asts["b"] == [ReturnValueConcept(parser.name, True, right_parser_result)]
assert return_value.compiled["a"] == [ReturnValueConcept(parser.name, True, left_parser_result)]
assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, right_parser_result)]
# sanity check, I can evaluate the result
evaluated = context.sheerka.evaluate_concept(context, return_value)
@@ -132,7 +132,7 @@ def test_i_can_parse_when_composition_of_source_code():
def test_i_can_parse_when_mix_of_concept_and_code():
plus = Concept("a plus b").set_prop("a").set_prop("b")
plus = Concept("a plus b").def_prop("a").def_prop("b")
code = PythonNode("1+1", ast.parse("1+1", mode="eval"))
foo = Concept("foo")
context, parser, result, wrapper, return_value = execute([plus, foo], [foo, " plus ", code])
@@ -144,8 +144,8 @@ def test_i_can_parse_when_mix_of_concept_and_code():
assert context.sheerka.isinstance(return_value, plus)
code_parser_result = ParserResultConcept(parser=parser, source="1+1", value=code)
assert return_value.cached_asts["a"] == foo
assert return_value.cached_asts["b"] == [ReturnValueConcept(parser.name, True, code_parser_result)]
assert return_value.compiled["a"] == foo
assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, code_parser_result)]
# sanity check, I can evaluate the result
evaluated = context.sheerka.evaluate_concept(context, return_value)
@@ -157,8 +157,8 @@ def test_i_can_parse_when_mix_of_concept_and_code():
def test_i_can_parse_when_multiple_concepts_are_recognized():
foo = Concept("foo")
bar = Concept("bar")
plus_1 = Concept("a plus b", body="body1").set_prop("a").set_prop("b")
plus_2 = Concept("a plus b", body="body2").set_prop("a").set_prop("b")
plus_1 = Concept("a plus b", body="body1").def_prop("a").def_prop("b")
plus_2 = Concept("a plus b", body="body2").def_prop("a").def_prop("b")
context, input_return_values = init([foo, bar, plus_1, plus_2], [foo, " plus ", bar])
parser = ConceptsWithConceptsParser()
@@ -174,8 +174,8 @@ def test_i_can_parse_when_multiple_concepts_are_recognized():
assert res.who == wrapper.parser.name
assert wrapper.source == "foo plus bar"
assert context.sheerka.isinstance(return_value, plus_1)
assert return_value.cached_asts["a"] == foo
assert return_value.cached_asts["b"] == bar
assert return_value.compiled["a"] == foo
assert return_value.compiled["b"] == bar
res = result[1]
wrapper = res.value
@@ -184,8 +184,8 @@ def test_i_can_parse_when_multiple_concepts_are_recognized():
assert res.who == wrapper.parser.name
assert wrapper.source == "foo plus bar"
assert context.sheerka.isinstance(return_value, plus_2)
assert return_value.cached_asts["a"] == foo
assert return_value.cached_asts["b"] == bar
assert return_value.compiled["a"] == foo
assert return_value.compiled["b"] == bar
def test_i_cannot_parse_when_unknown_concept():
+3 -3
View File
@@ -23,13 +23,13 @@ eval_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcep
def test_i_can_match_and_eval():
context = get_context()
to_eval1 = ReturnValueConcept("some_name", True, Concept(name="2", body="to eval"))
to_eval2 = ReturnValueConcept("some_name", True, Concept(name="3", body="also to eval"))
to_eval1 = ReturnValueConcept("some_name", True, Concept(name="2", body="to eval").auto_init())
to_eval2 = ReturnValueConcept("some_name", True, Concept(name="3", body="also to eval").auto_init())
return_values = [
ReturnValueConcept("some_name", True, "not to eval"),
ReturnValueConcept("some_name", True, Concept(name="not to eval")),
ReturnValueConcept("some_name", False, Concept(name="1", body="not to eval")),
ReturnValueConcept("some_name", False, Concept(name="1", body="'not to eval'")),
to_eval1,
to_eval2,
eval_requested
+14 -6
View File
@@ -6,6 +6,14 @@ from parsers.ExactConceptParser import ExactConceptParser
from sdp.sheerkaDataProvider import Event
def metadata_prop(concept, prop_name):
for name, value in concept.metadata.props:
if name == prop_name:
return value
return None
def test_i_can_compute_combinations():
parser = ExactConceptParser()
res = parser.combinations(["foo", "bar", "baz"])
@@ -58,7 +66,7 @@ def test_i_can_recognize_concepts_defined_several_times():
assert results[0].status
assert results[0].value.value.name == "hello a"
assert results[0].value.value.props["a"].value == "world"
assert metadata_prop(results[0].value.value, "a") == "world"
assert results[1].status
assert results[1].value.value.name == "hello world"
@@ -75,8 +83,8 @@ def test_i_can_recognize_a_concept_with_variables():
assert results[0].status
concept_found = results[0].value.value
assert concept_found.key == concept.key
assert concept_found.props["a"].value == "10"
assert concept_found.props["b"].value == "5"
assert metadata_prop(concept_found, "a") == "10"
assert metadata_prop(concept_found, "b") == "5"
def test_i_can_recognize_a_concept_with_duplicate_variables():
@@ -90,8 +98,8 @@ def test_i_can_recognize_a_concept_with_duplicate_variables():
assert results[0].status
concept_found = results[0].value.value
assert concept_found.key == concept.key
assert concept_found.props["a"].value == "10"
assert concept_found.props["b"].value == "5"
assert metadata_prop(concept_found, "a") == "10"
assert metadata_prop(concept_found, "b") == "5"
def test_i_can_manage_unknown_concept():
@@ -138,6 +146,6 @@ def get_concept(name, variables):
c = Concept(name=name)
if variables:
for v in variables:
c.props[v] = Property(v, None)
c.def_prop(v)
c.init_key()
return c
+1 -1
View File
@@ -90,7 +90,7 @@ def test_concept_is_returned_when_only_one_in_the_list():
assert wrapper.parser == evaluator
assert wrapper.source == "foo"
assert return_value == Concept("foo").init_key()
assert return_value.cached_asts[ConceptParts.BODY] == DoNotResolve("foo")
assert return_value.compiled[ConceptParts.BODY] == DoNotResolve("foo")
assert result.parents == [ret_val]
+2 -2
View File
@@ -136,12 +136,12 @@ def test_i_can_parse_when_multiple_concepts_are_matching():
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.body == "bar1"
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.body == "bar2"
assert ret_val[1].value.value[1].concept.metadata.body == "bar2"
def test_i_can_parse_when_source_code():
+25 -25
View File
@@ -20,8 +20,8 @@ def test_i_can_match_and_eval():
return_values = [
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -30,7 +30,7 @@ def test_i_can_match_and_eval():
evaluated = evaluator.eval(context, return_values)
assert evaluated.status
assert evaluated.value == Concept(name="1", body="value") # the first concept is returned
assert evaluated.value == Concept(name="1", body="value").auto_init() # the first concept is returned
def test_i_can_match_and_eval_when_no_body():
@@ -40,8 +40,8 @@ def test_i_can_match_and_eval_when_no_body():
return_values = [
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -50,7 +50,7 @@ def test_i_can_match_and_eval_when_no_body():
evaluated = evaluator.eval(context, return_values)
assert evaluated.status
assert evaluated.value == Concept(name="1")
assert evaluated.value == Concept(name="1").auto_init()
def test_i_can_match_and_eval_when_value_is_not_a_concept():
@@ -82,9 +82,9 @@ def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_concept_evalu
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, "value"),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="2", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "Concept", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="3", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="2", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "Concept", True, Concept(name="1", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="3", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -94,7 +94,7 @@ def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_concept_evalu
evaluated = evaluator.eval(context, return_values)
assert evaluated.status
assert evaluated.value == Concept(name="1", body="value") # the concept is returned, not the value
assert evaluated.value == Concept(name="1", body="value").auto_init() # the concept is returned, not the value
def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_python_evaluator_first():
@@ -106,9 +106,9 @@ def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_python_evalua
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, "value"),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="2", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="3", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="2", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "Python", True, Concept(name="1", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, Concept(name="3", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "other", True, "value"),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -118,7 +118,7 @@ def test_i_can_match_and_eval_when_at_least_one_value_is_a_concept_python_evalua
evaluated = evaluator.eval(context, return_values)
assert evaluated.status
assert evaluated.value == Concept(name="1", body="value") # the concept is returned, not the value
assert evaluated.value == Concept(name="1", body="value").auto_init() # the concept is returned, not the value
def test_i_can_match_even_if_the_value_are_not_the_same_but_eval_will_fail():
@@ -128,8 +128,8 @@ def test_i_can_match_even_if_the_value_are_not_the_same_but_eval_will_fail():
return_values = [
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value2")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value2").auto_init()),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -145,8 +145,8 @@ def test_i_can_match_even_if_the_value_are_not_the_same_but_eval_will_fail_when_
return_values = [
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2").auto_init()),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -160,8 +160,8 @@ def test_i_can_match_if_no_parser():
sheerka = context.sheerka
return_values = [
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -175,8 +175,8 @@ def test_i_cannot_match_if_not_reduced_requested():
return_values = [
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
ReturnValueConcept("some_name", True, Concept(name="2", body="value")),
# ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -192,7 +192,7 @@ def test_i_cannot_match_if_only_one_successful_evaluator():
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
ReturnValueConcept(BaseParser.PREFIX + "some_name2", False, "Not relevant"),
# ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
ReturnValueConcept("some_name", True, Concept(name="2", body="value")),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
@@ -207,8 +207,8 @@ def test_i_cannot_match_if_at_least_one_parser_is_successful():
return_values = [
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "Not relevant"),
ReturnValueConcept(BaseParser.PREFIX + "some_name2", True, "Not relevant"),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value")),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="1", body="value").auto_init()),
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, Concept(name="2", body="value").auto_init()),
ReturnValueConcept("some_name", True, sheerka.new(BuiltinConcepts.REDUCE_REQUESTED))
]
+17 -14
View File
@@ -1,6 +1,6 @@
import pytest
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
from core.concept import Concept
from core.sheerka import Sheerka, ExecutionContext
from evaluators.PrepareEvalEvaluator import PrepareEvalEvaluator
@@ -13,18 +13,21 @@ def get_context():
return ExecutionContext("test", Event(), sheerka)
r = ReturnValueConcept
@pytest.mark.parametrize("ret_val, expected", [
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body="eval 1 + 1")), True),
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body=" eval 1 + 1")), True),
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body="eval")), False),
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body="1+1")), False),
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body="")), False),
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body="eval ")), False),
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body=[])), False),
(ReturnValueConcept("some_name", True, Concept("foo")), False),
(ReturnValueConcept("some_name", True, "not a concept"), False),
(ReturnValueConcept("some_name", False, Concept(key=BuiltinConcepts.USER_INPUT, body="eval 1 + 1")), False),
(ReturnValueConcept("some_name", False, Concept(key=BuiltinConcepts.USER_INPUT, body=" eval 1 + 1")), False),
(r("name", True, UserInputConcept("eval 1 + 1")), True),
(r("name", True, UserInputConcept(" eval 1 + 1")), True),
(r("name", True, UserInputConcept("eval")), False),
(r("name", True, UserInputConcept("1+1")), False),
(r("name", True, UserInputConcept("")), False),
(r("name", True, UserInputConcept("eval ")), False),
(r("name", True, UserInputConcept([])), False),
(r("name", True, Concept("foo")), False),
(r("name", True, "not a concept"), False),
(r("name", False, UserInputConcept("eval 1 + 1")), False),
(r("name", False, UserInputConcept(" eval 1 + 1")), False),
])
def test_i_can_match(ret_val, expected):
context = get_context()
@@ -32,8 +35,8 @@ def test_i_can_match(ret_val, expected):
@pytest.mark.parametrize("ret_val, expected", [
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body="eval 1 + 1")), "1 + 1"),
(ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.USER_INPUT, body=" eval 1 + 1")), "1 + 1"),
(r("name", True, UserInputConcept("eval 1 + 1")), "1 + 1"),
(r("name", True, UserInputConcept(" eval 1 + 1")), "1 + 1"),
])
def test_i_can_eval(ret_val, expected):
context = get_context()
+4 -4
View File
@@ -73,8 +73,8 @@ def test_i_can_eval_when_same_success():
context = get_context()
return_values = [
r("evaluators.a", value=Concept("c1", body="1")),
r("evaluators.a", value=Concept("c2", body="1")),
r("evaluators.a", value=Concept("c1", body="1").auto_init()),
r("evaluators.a", value=Concept("c2", body="1").auto_init()),
r("other", False),
reduce_requested
]
@@ -90,8 +90,8 @@ def test_i_can_eval_when_same_success():
def test_other_success_are_not_reduced():
context = get_context()
value1 = r("evaluators.a", value=Concept("c1", body="1"))
value2 = r("evaluators.a", value=Concept("c2", body="2"))
value1 = r("evaluators.a", value=Concept("c1", body="1").auto_init())
value2 = r("evaluators.a", value=Concept("c2", body="2").auto_init())
other_success = r("other")
return_values = [
value1,
+92 -12
View File
@@ -1,9 +1,18 @@
import pytest
from core.concept import Concept
from core.concept import Concept, ConceptParts
@pytest.mark.parametrize("name, variables, expected", [
@pytest.mark.parametrize("name, properties, expected", [
("foo", [], "foo"),
("foo(bar)", [], "foo ( bar )"),
("foo a", ["a"], "foo __var__0"),
("a foo b", ["a", "b"], "__var__0 foo __var__1"),
("a foo b", ["b", "a"], "__var__1 foo __var__0"),
("foo", ["foo"], "foo"),
("foo a", ["foo"], "__var__0 a"),
("foo a b", ["a"], "foo __var__0 b"),
("'foo'", [], "foo"),
("my name is a", ["a"], "my name is __var__0"),
("a b c d", ["b", "c"], "a __var__0 __var__1 d"),
("a 'b c' d", ["b", "c"], "a b c d"),
@@ -11,17 +20,17 @@ from core.concept import Concept
("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_get_concept_key(name, variables, expected):
def test_i_can_compute_the_key(name, properties, expected):
concept = Concept(name)
for v in variables:
concept.set_prop(v, None)
for prop in properties:
concept.metadata.props.append((prop, None))
concept.init_key()
assert concept.metadata.key == expected
assert concept.key == expected
def test_key_does_not_use_variable_when_definition_is_set():
concept = Concept("plus").set_prop('plus')
concept = Concept("plus").def_prop('plus')
concept.init_key()
assert concept.metadata.key == "plus"
@@ -45,7 +54,7 @@ def test_i_can_serialize():
definition_type="def type",
desc="this this the desc",
id="123456"
).set_prop("a", 10).set_prop("b", None)
).def_prop("a", "10").def_prop("b", None)
to_dict = concept.to_dict()
assert to_dict == {
@@ -60,7 +69,7 @@ def test_i_can_serialize():
'name': 'concept_name',
'post': 'definition of the post',
'pre': 'definition of the pre',
'props': [('a', 10), ('b', None)],
'props': [('a', "10"), ('b', None)],
'where': 'definition of the where'
}
@@ -83,7 +92,7 @@ def test_i_can_deserialize():
'name': 'concept_name',
'post': 'definition of the post',
'pre': 'definition of the pre',
'props': [('a', 10), ('b', None)],
'props': [('a', "10"), ('b', None)],
'where': 'definition of the where'
}
@@ -102,7 +111,50 @@ def test_i_can_deserialize():
definition_type="def type",
desc="this this the desc",
id="123456"
).set_prop("a", 10).set_prop("b", None)
).def_prop("a", "10").def_prop("b", None)
def test_i_can_deserialize_props_coming_from_sdp():
from_dict = {
'props': [['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)
def test_i_can_compare_concepts():
concept_a = Concept(
name="concept_name",
is_builtin=True,
is_unique=True,
key="concept_key",
body="definition of the body",
where="definition of the where",
pre="definition of the pre",
post="definition of the post",
definition="bnf definition",
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
concept_b = Concept(
name="concept_name",
is_builtin=True,
is_unique=True,
key="concept_key",
body="definition of the body",
where="definition of the where",
pre="definition of the pre",
post="definition of the post",
definition="bnf definition",
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
assert concept_a == concept_b
def test_i_can_compare_concept_with_circular_reference():
@@ -128,3 +180,31 @@ def test_i_can_compare_concept_with_sophisticated_circular_reference_in_other_me
foo.metadata.pre = baz
assert foo != bar
def test_i_can_update_from():
template = Concept(
name="concept_name",
is_builtin=True,
is_unique=True,
key="concept_key",
body="definition of the body",
where="definition of the where",
pre="definition of the pre",
post="definition of the post",
definition="bnf definition",
definition_type="def type",
desc="this this the desc",
id="123456"
).def_prop("a", "10").def_prop("b", None)
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)
concept = Concept().update_from(template)
assert concept == template
+63 -62
View File
@@ -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)
+33 -32
View File
@@ -5,7 +5,7 @@ from os import path
import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property, simplec
from core.sheerka import Sheerka, ExecutionContext
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
from parsers.ConceptLexerParser import Sequence, StrMatch, OrderedChoice, Optional, ConceptExpression
@@ -50,8 +50,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
@@ -79,7 +79,7 @@ def test_i_can_eval_concept_with_python_body():
res = sheerka.evaluate_user_input(text)
assert len(res) == 1
assert res[0].status
assert res[0].value == Concept(name="one", body=1).init_key() # by default, the concept is returned
assert res[0].value == simplec("one", 1) # by default, the concept is returned
def test_i_can_eval_concept_with_concept_body():
@@ -93,7 +93,7 @@ def test_i_can_eval_concept_with_concept_body():
return_value = res[0].value
assert len(res) == 1
assert res[0].status
assert return_value == Concept(name="un", body=Concept(name="one").init_key()).init_key()
assert return_value == simplec("un", simplec("one", None))
def test_i_can_eval_concept_with_no_body():
@@ -137,6 +137,7 @@ as:
expected = get_default_concept()
expected.metadata.id = "1001"
expected.metadata.desc = None
expected.metadata.props = [("a", None), ("b", None)]
expected.init_key()
sheerka = get_sheerka()
@@ -165,11 +166,11 @@ def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept()
sheerka = get_sheerka()
# concept 'a plus b' is known
concept_a_plus_b = Concept(name="a plus b").set_prop("a").set_prop("b")
concept_a_plus_b = Concept(name="a plus b").def_prop("a").def_prop("b")
sheerka.add_in_cache(concept_a_plus_b)
res = sheerka.evaluate_user_input("def concept a xx b as a plus b")
expected = Concept(name="a xx b", body="a plus b").set_prop("a").set_prop("b").init_key()
expected = Concept(name="a xx b", body="a plus b").def_prop("a").def_prop("b").init_key()
expected.metadata.id = "1001"
assert len(res) == 1
@@ -224,7 +225,7 @@ def test_i_can_eval_a_empty_input(text):
def test_i_can_eval_concept_with_variable():
sheerka = get_sheerka()
concept_hello = Concept(name="hello a").set_prop("a")
concept_hello = Concept(name="hello a").def_prop("a")
concept_foo = Concept(name="foo")
sheerka.add_in_cache(concept_hello)
sheerka.add_in_cache(concept_foo)
@@ -239,7 +240,7 @@ def test_i_can_eval_concept_with_variable():
def test_i_can_eval_concept_with_variable_and_python_as_body():
sheerka = get_sheerka()
hello_a = sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").set_prop("a"))
hello_a = sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a"))
sheerka.add_in_cache(Concept(name="foo", body="'foo'"))
res = sheerka.evaluate_user_input("hello foo")
@@ -248,14 +249,14 @@ def test_i_can_eval_concept_with_variable_and_python_as_body():
assert sheerka.isinstance(res[0].value, hello_a)
assert res[0].value.body == "hello foo"
assert res[0].value.metadata.is_evaluated
assert res[0].value.props["a"].value == Concept(name="foo", body="foo").init_key()
assert res[0].value.props["a"].value == simplec("foo", "foo")
assert res[0].value.props["a"].value.metadata.is_evaluated
def test_i_can_eval_duplicate_concepts_with_same_value():
sheerka = get_sheerka()
sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").set_prop("a"))
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'"))
@@ -269,7 +270,7 @@ def test_i_can_eval_duplicate_concepts_with_same_value():
def test_i_cannot_manage_duplicate_concepts_when_the_values_are_different():
sheerka = get_sheerka()
sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").set_prop("a"))
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'"))
@@ -289,8 +290,8 @@ def test_i_can_manage_concepts_with_the_same_key_when_values_are_the_same():
sheerka = get_sheerka()
context = get_context(sheerka)
sheerka.create_new_concept(context, Concept(name="hello a", body="'hello ' + a").set_prop("a"))
sheerka.create_new_concept(context, Concept(name="hello b", body="'hello ' + b").set_prop("b"))
sheerka.create_new_concept(context, Concept(name="hello a", body="'hello ' + a").def_prop("a"))
sheerka.create_new_concept(context, Concept(name="hello b", body="'hello ' + b").def_prop("b"))
res = sheerka.evaluate_user_input("hello 'foo'")
assert len(res) == 1
@@ -453,10 +454,10 @@ def test_i_can_mix_concept_with_python_to_define_numbers(desc, definitions):
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
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():
@@ -472,20 +473,20 @@ def test_i_can_mix_concept_of_concept():
for definition in definitions:
sheerka.evaluate_user_input(definition)
# res = sheerka.evaluate_user_input("1 plus 2")
# assert len(res) == 1
# assert res[0].status
# assert res[0].body.body == 3
#
# res = sheerka.evaluate_user_input("1 plus one")
# assert len(res) == 1
# assert res[0].status
# assert res[0].body.body == 2
# res = sheerka.evaluate_user_input("1 + 1 plus 1")
# assert len(res) == 1
# assert res[0].status
# assert res[0].body.body == 3
res = sheerka.evaluate_user_input("1 plus 2")
assert len(res) == 1
assert res[0].status
assert res[0].body.body == 3
res = sheerka.evaluate_user_input("1 plus one")
assert len(res) == 1
assert res[0].status
assert res[0].body.body == 2
res = sheerka.evaluate_user_input("1 + 1 plus 1")
assert len(res) == 1
assert res[0].status
assert res[0].body.body == 3
res = sheerka.evaluate_user_input("1 plus twenty one")
assert len(res) == 1
+75 -43
View File
@@ -1,5 +1,5 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.concept import Concept, ConceptParts
from core.sheerka import Sheerka, ExecutionContext, ExecutionContextIdManager
from core.sheerka_transform import SheerkaTransform, OBJ_TYPE_KEY, SheerkaTransformType, OBJ_ID_KEY
from sdp.sheerkaDataProvider import Event
@@ -33,7 +33,14 @@ def test_i_can_transform_an_unknown_concept():
definition="it is a definition",
definition_type="def type",
desc="this this the desc"
).set_prop("a", 10).set_prop("b", foo).set_prop("c", concept_with_sub)
).def_prop("a", "10").def_prop("b", "foo").def_prop("c", "concept_with_sub")
# add values and props
concept.values[ConceptParts.BODY] = Concept().update_from(concept_with_sub).auto_init()
concept.values[ConceptParts.WHERE] = [foo, 1, "1", True, 1.0]
concept.values[ConceptParts.PRE] = Concept().update_from(foo).auto_init()
concept.values[ConceptParts.POST] = "a value for POST"
concept.set_prop("a", 10).set_prop("b", foo).set_prop("c", concept_with_sub)
st = SheerkaTransform(sheerka)
to_dict = st.to_dict(concept)
@@ -41,28 +48,41 @@ def test_i_can_transform_an_unknown_concept():
assert to_dict == {
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 0,
'name': 'concept_name',
'key': 'concept_key',
'is_builtin': True,
'is_unique': True,
'definition': 'it is a definition',
'definition_type': 'def type',
'desc': 'this this the desc',
'where': [{OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 1,
'body': 'body',
'name': 'foo'}, 1, '1', True, 1.0],
'pre': {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1},
'body': {
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 2,
'name': 'concept_with_sub',
'body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}},
'props': [
('a', 10),
('b', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}),
('c', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 2})
]
'meta.name': 'concept_name',
'meta.key': 'concept_key',
'meta.is_builtin': True,
'meta.is_unique': True,
'meta.definition': 'it is a definition',
'meta.definition_type': 'def type',
'meta.desc': 'this this the desc',
'meta.where': [{OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 1,
'meta.body': 'body',
'meta.name': 'foo'}, 1, '1', True, 1.0],
'meta.pre': {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1},
'meta.body': {
'__type__': SheerkaTransformType.Concept,
'__id__': 2,
'meta.name': 'concept_with_sub',
'meta.body': {
'__type__': SheerkaTransformType.Reference,
'__id__': 1}},
'meta.props': [['a', '10'], ['b', 'foo'], ['c', 'concept_with_sub']],
'pre': {'__type__': SheerkaTransformType.Concept,
'__id__': 4,
'meta.body': 'body',
'meta.name': 'foo',
'body': 'body'},
'post': "a value for POST",
'body': {'__type__': SheerkaTransformType.Concept,
'__id__': 3,
'meta.body': {'__id__': 1, '__type__': SheerkaTransformType.Reference},
'meta.name': 'concept_with_sub',
'body': {'__id__': 1, '__type__': SheerkaTransformType.Reference}},
'where': [{OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}, 1, '1', True, 1.0],
'props': [('a', 10),
('b', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 1}),
('c', {OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: 2})],
}
@@ -73,10 +93,16 @@ def test_i_can_transform_unknown_concept_with_almost_same_value():
st = SheerkaTransform(sheerka)
to_dict = st.to_dict(concept)
assert to_dict == {OBJ_TYPE_KEY: SheerkaTransformType.Concept, OBJ_ID_KEY: 0, 'name': 'foo'}
assert to_dict == {OBJ_TYPE_KEY: SheerkaTransformType.Concept, OBJ_ID_KEY: 0, 'meta.name': 'foo'}
def test_i_can_transform_known_concept_when_the_values_are_the_same():
"""
Values are the same means that we are serializing a concept which has kept all its default values
There is not diff between the concept to serialize and the one which was registered with create_new_concept()
We serialize only the id of the concept
:return:
"""
sheerka = get_sheerka()
concept = Concept(
@@ -91,7 +117,7 @@ def test_i_can_transform_known_concept_when_the_values_are_the_same():
definition="it is a definition",
definition_type="def type",
desc="this this the desc"
).set_prop("a").set_prop("b")
).def_prop("a").def_prop("b")
sheerka.create_new_concept(get_context(sheerka), concept)
new_concept = sheerka.new(concept.key)
@@ -102,6 +128,12 @@ def test_i_can_transform_known_concept_when_the_values_are_the_same():
def test_i_can_transform_known_concept_when_the_values_are_different():
"""
Values are the different means the concept was modified.
It's different from the one which was registered with create_new_concept()
We serialize only the differences
:return:
"""
sheerka = get_sheerka()
concept = Concept(
@@ -116,7 +148,7 @@ def test_i_can_transform_known_concept_when_the_values_are_different():
definition="it is a definition",
definition_type="def type",
desc="this this the desc"
).set_prop("a").set_prop("b")
).def_prop("a").def_prop("b")
sheerka.create_new_concept(get_context(sheerka), concept)
new_concept = sheerka.new(concept.key, body="another", a=10, pre="another pre")
@@ -135,7 +167,7 @@ def test_i_can_transform_known_concept_when_the_values_are_different():
def test_i_can_transform_concept_with_circular_reference():
sheerka = get_sheerka()
foo = Concept("foo", )
foo = Concept("foo")
bar = Concept("bar", body=foo)
foo.metadata.body = bar
@@ -145,19 +177,19 @@ def test_i_can_transform_concept_with_circular_reference():
assert to_dict == {
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 0,
'name': 'foo',
'body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 1,
'name': 'bar',
'body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
OBJ_ID_KEY: 0},
},
'meta.name': 'foo',
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 1,
'meta.name': 'bar',
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
OBJ_ID_KEY: 0},
},
}
def test_i_can_transform_concept_with_circular_reference_2():
sheerka = get_sheerka()
foo = Concept("foo", )
foo = Concept("foo")
bar = Concept("foo", body=foo)
foo.metadata.body = bar
@@ -167,13 +199,13 @@ def test_i_can_transform_concept_with_circular_reference_2():
assert to_dict == {
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 0,
'name': 'foo',
'body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 1,
'name': 'foo',
'body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
OBJ_ID_KEY: 0},
},
'meta.name': 'foo',
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Concept,
OBJ_ID_KEY: 1,
'meta.name': 'foo',
'meta.body': {OBJ_TYPE_KEY: SheerkaTransformType.Reference,
OBJ_ID_KEY: 0},
},
}