import pytest from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, ParserResultConcept from core.concept import Concept, simplec, DoNotResolve, ConceptParts, Property from parsers.PythonParser import PythonNode from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): @pytest.mark.parametrize("body, expected", [ # (None, None), # ("", ""), ("1", 1), ("1+1", 2), ("'one'", "one"), ("'one' + 'two'", "onetwo"), ("True", True), ("1 > 2", False), ]) def test_i_can_evaluate_a_concept_with_simple_body(self, body, expected): sheerka = self.get_sheerka() concept = Concept("foo", body=body) evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == expected assert evaluated.metadata.body == body assert evaluated.metadata.pre is None assert evaluated.metadata.post is None assert evaluated.metadata.where is None assert evaluated.props == {} assert evaluated.metadata.is_evaluated assert len(evaluated.values) == 0 if body is None else 1 @pytest.mark.parametrize("expr, expected", [ ("", ""), ("1", 1), ("1+1", 2), ("'one'", "one"), ("'one' + 'two'", "onetwo"), ("True", True), ("1 > 2", False), ]) def test_i_can_evaluate_the_other_metadata(self, expr, expected): """ I only test PRE, it's the same for the others :param expr: :param expected: :return: """ sheerka = self.get_sheerka() concept = Concept("foo", pre=expr) evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.metadata.body is None assert evaluated.metadata.pre == expr assert evaluated.metadata.post is None assert evaluated.metadata.where is None assert evaluated.get_metadata_value(ConceptParts.PRE) == expected assert evaluated.props == {} assert evaluated.metadata.is_evaluated assert len(evaluated.values) == 0 if expr is None else 1 @pytest.mark.parametrize("expr, expected", [ (None, None), ("", ""), ("1", 1), ("1+1", 2), ("'one'", "one"), ("'one' + 'two'", "onetwo"), ("True", True), ("1 > 2", False), ]) def test_i_can_evaluate_a_concept_with_prop(self, expr, expected): sheerka = self.get_sheerka() concept = Concept("foo").def_prop("a", expr) evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.metadata.pre is None assert evaluated.metadata.pre is None assert evaluated.metadata.post is None assert evaluated.metadata.where is None assert evaluated.props == {"a": Property("a", expected)} assert evaluated.metadata.is_evaluated def test_i_can_evaluate_metadata_using_do_not_resolve(self): sheerka = self.get_sheerka() concept = Concept("foo") concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.body == "do not resolve" assert evaluated.metadata.is_evaluated def test_i_can_evaluate_property_using_do_not_resolve(self): sheerka = self.get_sheerka() concept = Concept("foo").def_prop("a") concept.compiled["a"] = DoNotResolve("do not resolve") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.get_prop("a") == "do not resolve" assert evaluated.metadata.is_evaluated def test_original_value_is_overridden_when_using_do_no_resolve(self): sheerka = self.get_sheerka() concept = Concept("foo", body="original value").set_prop("a", "original value") concept.compiled["a"] = DoNotResolve("do not resolve") concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.body == "do not resolve" assert evaluated.get_prop("a") == "do not resolve" assert evaluated.metadata.is_evaluated def test_props_are_evaluated_before_body(self): sheerka = self.get_sheerka() concept = Concept("foo", body="a+1").def_prop("a", "10").init_key() evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == 11 def test_i_can_evaluate_when_another_concept_is_referenced(self): sheerka = self.get_sheerka() concept_a = Concept("a") sheerka.add_in_cache(concept_a) concept = Concept("foo", body="a").init_key() evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated == simplec("foo", simplec("a", None)) assert id(evaluated.body) != id(concept_a) assert evaluated.metadata.is_evaluated assert evaluated.body.metadata.is_evaluated def test_i_can_evaluate_when_the_referenced_concept_has_a_body(self): sheerka = self.get_sheerka() concept_a = Concept("a", body="1") sheerka.add_in_cache(concept_a) concept = Concept("foo", body="a") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == simplec("a", 1) assert not concept_a.metadata.is_evaluated assert evaluated.metadata.is_evaluated def test_i_can_evaluate_concept_of_concept_when_the_leaf_has_a_body(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept(name="a", body="'a'")) sheerka.add_in_cache(Concept(name="b", body="a")) sheerka.add_in_cache(Concept(name="c", body="b")) concept_d = sheerka.add_in_cache(Concept(name="d", body="c")) evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d) assert evaluated.key == concept_d.key expected = simplec("c", simplec("b", simplec("a", "a"))) assert evaluated.body == expected assert sheerka.value(evaluated) == 'a' assert evaluated.metadata.is_evaluated def test_i_can_evaluate_concept_of_concept_does_not_have_a_body(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept(name="a")) sheerka.add_in_cache(Concept(name="b", body="a")) sheerka.add_in_cache(Concept(name="c", body="b")) concept_d = sheerka.add_in_cache(Concept(name="d", body="c")) evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d) assert evaluated.key == concept_d.key expected = simplec("c", simplec("b", simplec("a", None))) assert evaluated.body == expected assert sheerka.value(evaluated) == Concept(name="a").init_key() assert evaluated.metadata.is_evaluated def test_i_can_evaluate_concept_when_properties_reference_others_concepts(self): sheerka = self.get_sheerka() concept_a = sheerka.add_in_cache(Concept(name="a").init_key()) concept = Concept("foo", body="a").def_prop("a", "a").init_key() evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) # first prop a is evaluated to concept_a # then body is evaluated to prop a -> concept_a assert evaluated.key == concept.key assert evaluated.body == concept_a def test_i_can_evaluate_concept_when_properties_reference_others_concepts_2(self): """ Same test, but the name of the property and the name of the concept are different :return: """ sheerka = self.get_sheerka() concept_a = sheerka.add_in_cache(Concept(name="a")) concept = Concept("foo", body="concept_a").def_prop("concept_a", "a") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == concept_a def test_i_can_evaluate_concept_when_properties_reference_others_concepts_with_body(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept(name="a", body="1")) sheerka.add_in_cache(Concept(name="b", body="2")) concept = Concept("foo", body="propA + propB").def_prop("propA", "a").def_prop("propB", "b") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == 3 def test_i_can_evaluate_concept_when_properties_is_a_concept(self): sheerka = self.get_sheerka() concept_a = sheerka.add_in_cache(Concept(name="a", body="'a'").init_key()) concept = Concept("foo").def_prop("a") concept.compiled["a"] = concept_a evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.get_prop("a") == simplec("a", "a") def test_i_can_evaluate_when_property_asts_is_a_list(self): sheerka = self.get_sheerka() foo = Concept("foo", body="1") concept = Concept("to_eval").def_prop("prop") concept.compiled["prop"] = [foo, DoNotResolve("1")] evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) props = evaluated.get_prop("prop") assert len(props) == 2 assert props[0] == simplec("foo", 1) assert props[1] == "1" def test_i_can_evaluate_when_compiled_is_set_up_with_return_value(self): sheerka = self.get_sheerka() python_node = PythonNode("1 +1 ") parser_result = ParserResultConcept(parser="who", value=python_node) concept = Concept("to_eval").def_prop("prop") concept.compiled["prop"] = [ReturnValueConcept("who", True, parser_result)] evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.get_prop("prop") == 2 # also works when only one return value concept = Concept("to_eval").def_prop("prop") concept.compiled["prop"] = ReturnValueConcept("who", True, parser_result) evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.get_prop("prop") == 2 def test_i_can_reference_sheerka(self): sheerka = self.get_sheerka() concept = Concept("foo", body="sheerka.test()").init_key() evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == sheerka.test() def test_properties_values_takes_precedence_over_the_outside_world(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept(name="a", body="'concept_a'")) sheerka.add_in_cache(Concept(name="b", body="'concept_b'")) concept = Concept("foo", body="a") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == simplec("a", "concept_a") # this test was already done # so check this one. concept = Concept("foo", body="a").def_prop("a", "'property_a'") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == 'property_a' # or this one. concept = Concept("foo", body="a").def_prop("a", "b") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == simplec(name="b", body="concept_b") def test_properties_values_takes_precedence(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept(name="a", body="'concept_a'")) sheerka.add_in_cache(Concept(name="b", body="'concept_b'")) concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == 'prop_aconcept_b' def test_i_can_reference_sub_property_of_a_property(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept(name="concept_a").def_prop("subProp", "'sub_a'")) concept = Concept("foo", body="a.props['subProp'].value").def_prop("a", "concept_a") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated == simplec(concept.key, "sub_a") def test_i_cannot_evaluate_concept_if_property_is_in_error(self): sheerka = self.get_sheerka() concept = Concept(name="concept_a").def_prop("subProp", "undef_concept") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR) def test_key_is_initialized_by_evaluation(self): sheerka = self.get_sheerka() concept = Concept("foo") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.init_key().key @pytest.mark.parametrize("where_clause, expected", [ ("True", True), ("False", False), ("self < 10", False), ("self < 11", True), ("a < 20", False), ("a > 19", True), ("a + self > 20", True), ]) def test_i_can_evaluate_simple_where(self, where_clause, expected): sheerka = self.get_sheerka() concept = Concept("foo", body="10", where=where_clause).def_prop("a", "20") sheerka.add_in_cache(concept) evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) if expected: assert evaluated.key == concept.key else: assert sheerka.isinstance(evaluated, BuiltinConcepts.WHERE_CLAUSE_FAILED) assert evaluated.body == concept def test_i_can_evaluate_where_when_using_other_concept(self): sheerka = self.get_sheerka() foo_true = Concept("foo_true", body="True").init_key() foo_false = Concept("foo_false", body="False").init_key() sheerka.add_in_cache(foo_false) sheerka.add_in_cache(foo_true) concept = Concept("foo", where="foo_true").init_key() evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key concept = Concept("foo", where="foo_false") evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert sheerka.isinstance(evaluated, BuiltinConcepts.WHERE_CLAUSE_FAILED) assert evaluated.body == concept