Fixed #101 : Implement PLURIAL

Fixed #103 : Implement PlurialNodeParser
Fixed #104 : Implement dynamic concept
Fixed #107 : PrepareEvalxxxEvaluator: context hints are lost on a second evaluation
This commit is contained in:
2021-08-05 19:07:21 +02:00
parent c798c2c570
commit 71d1b1d1ca
31 changed files with 600 additions and 105 deletions
+8
View File
@@ -1537,6 +1537,14 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
weights = sheerka.get_weights(BuiltinConcepts.PRECEDENCE, comparison_context=CONCEPT_COMPARISON_CONTEXT)
assert weights == {'c:one|1001:': 2, 'c:two|1002:': 1}
def test_i_can_get_a_dynamic_concept_by_id_when_allow_dynamic(self):
sheerka, context, foo = self.init_concepts("foo")
dynamic_foo = sheerka.new_dynamic(foo, "SUFFIX")
assert sheerka.isinstance(sheerka.get_by_id(dynamic_foo.id), BuiltinConcepts.UNKNOWN_CONCEPT)
assert sheerka.isinstance(sheerka.get_by_id(dynamic_foo.id, allow_dynamic=True), foo)
class TestSheerkaConceptManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
def test_i_can_add_several_concepts(self):
+28 -1
View File
@@ -518,6 +518,29 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, False, False), concept)
assert evaluated.key == concept.key
def test_i_can_evaluate_context_hint_multiple_times(self):
"""
Previous behaviour (that we want to change)
When def concept foo as global_truth(xxx) pre yyy
the context hint for the global truth is set during the initialisation of the ast
if the body is computed straight away it's ok,
But if the concept is evaluated a second time, the asts is not computed again, so the context hint is not set
:return:
"""
sheerka, context, foo = self.init_concepts(
Concept("foo", body="global_truth(in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED))")
)
foo_instance = sheerka.new("foo")
evaluated = sheerka.evaluate_concept(context, foo_instance, eval_body=False)
assert ConceptParts.BODY in evaluated.get_compiled()
assert evaluated.body == NotInit
assert not evaluated.get_hints().is_evaluated
evaluated = sheerka.evaluate_concept(context, foo_instance, eval_body=True) # evaluate the body this time
assert isinstance(evaluated.body, bool) and evaluated.body
def test_i_can_apply_intermediate_where_condition_using_python(self):
sheerka, context, one_1, one_str, plus = self.init_concepts(
Concept("one", body="1"),
@@ -818,10 +841,14 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
(Concept("foo"), False, []),
(Concept("foo", pre="pre", post="post", ret="ret", where="where"), False, ["#pre#", "#post#"]),
(Concept("foo", pre="pr", post="p", ret="r", where="w"), True,
["#pre#", "#ret#", "#post#", "variables", "#body#"]),
["#pre#", "variables", "#body#", "#ret#", "#post#"]),
(Concept("foo", pre="pre", body="body"), False, ["#pre#"]),
(Concept("foo", pre="pre", body="body"), True, ["#pre#", "variables", "#body#"]),
(Concept("foo", pre="a").def_var("a"), False, ["variables", "#pre#"]),
(Concept("foo", pre="self"), False, ["#body#", "#pre#"]),
(Concept("foo", pre="self + a").def_var("a"), False, ["variables", "#body#", "#pre#"]),
(Concept("foo", pre="self + a", ret="ret").def_var("a"), False, ["variables", "#body#", "#pre#"]),
(Concept("foo", pre="self + a", ret="ret").def_var("a"), True, ["variables", "#body#", "#pre#", "#ret#"]),
(Concept("foo", body="body"), False, [])
+17
View File
@@ -9,7 +9,10 @@ class TestSheerkaHasAManager(TestUsingMemoryBasedSheerka):
king_instance = sheerka.new("king")
res = sheerka.set_hasa(context, king_instance, kingdom)
assert res.status
assert king_instance.get_prop(BuiltinConcepts.HASA) == {kingdom}
assert sheerka.hasa(king_instance, kingdom)
# when global truth is not activated, only the current instance is modified
another_king = sheerka.get_by_key("king")
@@ -56,3 +59,17 @@ class TestSheerkaHasAManager(TestUsingMemoryBasedSheerka):
assert res.body.property_name == BuiltinConcepts.HASA
assert res.body.property_value == kingdom
assert res.body.concept == sheerka.new("king")
def test_i_can_set_hase_twice_when_global_truth_is_true_the_second_time(self):
sheerka, context, king, kingdom = self.init_concepts("king", "kingdom")
global_truth_context = self.get_context(sheerka, global_truth=True)
king_instance = sheerka.new("king")
sheerka.set_hasa(context, king_instance, kingdom)
# set it again with global_truth = True
res = sheerka.set_hasa(global_truth_context, king_instance, kingdom)
assert res.status
assert sheerka.hasa(king_instance, kingdom)
assert sheerka.hasa(sheerka.new("king"), kingdom) # try another instance
+16 -1
View File
@@ -116,7 +116,8 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
context.add_to_private_hints(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
sheerka.set_isa(context, blue_instance, color)
res = sheerka.set_isa(context, blue_instance, color)
assert res.status
assert sheerka.isa(blue_instance, color)
assert sheerka.isaset(context, color)
assert sheerka.isinset(blue_instance, color)
@@ -423,6 +424,20 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
foo = sheerka.get_by_id(foo.id)
assert not sheerka.isa(foo, group2)
def test_i_can_set_isa_twice_when_global_truth_is_true_the_second_time(self):
sheerka, context, blue, color = self.init_concepts(Concept("blue"), Concept("color"))
global_truth_context = self.get_context(sheerka, global_truth=True)
blue_instance = sheerka.new("blue")
sheerka.set_isa(context, blue_instance, color)
# set it again with global_truth = True
res = sheerka.set_isa(global_truth_context, blue_instance, color)
assert res.status
assert sheerka.isa(blue_instance, color)
assert sheerka.isa(sheerka.new("blue"), color) # try another instance
class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
def test_i_can_add_concept_to_set_and_retrieve_it_in_another_session(self):
+76
View File
@@ -0,0 +1,76 @@
from core.builtin_concepts_ids import BuiltinConcepts
from core.global_symbols import NotFound
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaPluralManager(TestUsingMemoryBasedSheerka):
def test_i_can_set_plural(self):
sheerka, context, man, men = self.init_concepts("man", "men")
men_instance = sheerka.new("men")
res = sheerka.set_plural(context, men_instance, man)
assert res.status
assert men_instance.get_prop(BuiltinConcepts.PLURAL) == man
assert sheerka.is_plural(men_instance)
assert sheerka.is_plural(men_instance, man)
# global truth is not set
another_instance = sheerka.new("men")
assert another_instance.get_prop(BuiltinConcepts.PLURAL) is None
def test_i_can_set_plural_when_global_truth_is_set(self):
sheerka, context, man, men = self.init_concepts("man", "men", global_truth=True)
assert sheerka.known_plural(man) == NotFound
res = sheerka.set_plural(context, men, man)
assert res.status
assert sheerka.is_plural(men)
another_instance = sheerka.new("men")
assert sheerka.is_plural(another_instance)
assert sheerka.known_plural(man) == men.id
def test_i_cannot_set_plural_twice(self):
sheerka, context, man, men = self.init_concepts("man", "men")
men_instance = sheerka.new("men")
sheerka.set_plural(context, men_instance, man)
res = sheerka.set_plural(context, men_instance, man)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.PROPERTY_ALREADY_DEFINED)
assert res.body.concept == men_instance
assert res.body.property_name == BuiltinConcepts.PLURAL
assert res.body.property_value == man
def test_i_cannot_set_plural_twice_when_global_truth(self):
sheerka, context, man, men = self.init_concepts("man", "men", global_truth=True)
sheerka.set_plural(context, men, man)
another_instance = sheerka.new("men")
res = sheerka.set_plural(context, another_instance, man)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.PROPERTY_ALREADY_DEFINED)
assert res.body.concept == another_instance
assert res.body.property_name == BuiltinConcepts.PLURAL
assert res.body.property_value == man
def test_i_can_set_plural_twice_when_global_truth_is_true_the_second_time(self):
sheerka, context, man, men = self.init_concepts("man", "men")
global_truth_context = self.get_context(sheerka, global_truth=True)
men_instance = sheerka.new("men")
sheerka.set_plural(context, men_instance, man)
# set it again with global_truth = True
res = sheerka.set_plural(global_truth_context, men_instance, man)
assert res.status
assert men_instance.get_prop(BuiltinConcepts.PLURAL) == man
# and it's now true for all newly created context
assert sheerka.is_plural(sheerka.new("men"), man)
@@ -0,0 +1,59 @@
from core.builtin_concepts_ids import BuiltinConcepts
from core.concept import Concept, ConceptParts
from evaluators.PrepareEvalCommon import PrepareEvalCommon
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestPrepareEvalCommon(TestUsingMemoryBasedSheerka):
def test_i_can_update_the_current_root(self):
sheerka, context = self.init_concepts()
PrepareEvalCommon.update_context_hints(context, "prop_name", ["to_put_in_context"])
assert context.in_context("to_put_in_context")
def test_i_can_update_process_input(self):
sheerka, context = self.init_concepts()
process_input_context = context.push(BuiltinConcepts.PROCESS_INPUT, "some input", desc=f"some desc")
level1 = process_input_context.push(BuiltinConcepts.TESTING, "some stuff")
level2 = level1.push(BuiltinConcepts.TESTING, "some stuff") # another level for the fun
PrepareEvalCommon.update_context_hints(level2, "prop_name", ["to_put_in_context"])
assert not context.in_context("to_put_in_context")
assert process_input_context.in_context("to_put_in_context")
assert not level1.in_context("to_put_in_context")
assert not level2.in_context("to_put_in_context")
def test_i_can_update_process_when_evaluating_a_concept(self):
sheerka, context, foo = self.init_concepts("foo")
eval_context = context.push(BuiltinConcepts.EVALUATING_CONCEPT, foo, desc=f"some desc")
parsing_prop_context = eval_context.push(BuiltinConcepts.PARSING, {"prop": ConceptParts.BODY})
level1 = parsing_prop_context.push(BuiltinConcepts.TESTING, "some stuff")
level2 = level1.push(BuiltinConcepts.TESTING, "some stuff") # another level for the fun
PrepareEvalCommon.update_context_hints(level2, "prop_name", ["to_put_in_context"])
assert not context.in_context("to_put_in_context")
assert not eval_context.in_context("to_put_in_context")
assert not parsing_prop_context.in_context("to_put_in_context")
assert not level1.in_context("to_put_in_context")
assert not level2.in_context("to_put_in_context")
assert foo.get_compiled_context_hints() == {ConceptParts.BODY: ["to_put_in_context"]}
def test_i_can_update_for_the_correct_variable(self):
# when source is the name of the variable,
# use this name, rather than the attribute being parsed
sheerka, context, foo = self.init_concepts(Concept("foo").def_var("var_name"))
eval_context = context.push(BuiltinConcepts.EVALUATING_CONCEPT, foo, desc=f"some desc")
parsing_prop_context = eval_context.push(BuiltinConcepts.PARSING, {"prop": ConceptParts.BODY})
level1 = parsing_prop_context.push(BuiltinConcepts.TESTING, "some stuff")
level2 = level1.push(BuiltinConcepts.TESTING, "some stuff") # another level for the fun
PrepareEvalCommon.update_context_hints(level2, "var_name", ["to_put_in_context"])
assert not context.in_context("to_put_in_context")
assert not eval_context.in_context("to_put_in_context")
assert not parsing_prop_context.in_context("to_put_in_context")
assert not level1.in_context("to_put_in_context")
assert not level2.in_context("to_put_in_context")
assert foo.get_compiled_context_hints() == {"var_name": ["to_put_in_context"]}
+11
View File
@@ -44,3 +44,14 @@ class TestSheerkaNonRegMemory2(TestUsingMemoryBasedSheerka):
assert res[0].status
assert sheerka.isa(sheerka.new("one"), sheerka.new("number"))
# def test_i_can_define_plural(self):
# init = [
# "def concept man",
# "def concept men as set_plural(man) ret man auto_eval True",
# ]
# sheerka = self.init_scenario(init)
#
# res = sheerka.evaluate_user_input("men")
# assert res[0].status
+2 -2
View File
@@ -151,8 +151,8 @@ __default__
init = [
"def concept one as 1",
"def concept two as 2",
"one",
"two"
"eval one",
"eval two"
]
sheerka = self.init_scenario(init)
capsys.readouterr()
+12
View File
@@ -3,6 +3,7 @@ import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.BaseNodeParser import SourceCodeWithConceptNode
from parsers.BaseParser import ErrorSink
from parsers.FunctionParser import FunctionParser
from parsers.PythonParser import PythonErrorNode
@@ -192,6 +193,17 @@ class TestFunctionParser(TestUsingMemoryBasedSheerka):
assert expression.python_node is not None
assert expression.return_value is not None
def test_i_can_parse_when_the_parameter_is_a_dynamic_concept(self):
sheerka, context, parser = self.init_parser()
text = "func(ones)"
res = parser.parse(context, ParserInput(text))
assert res.status
assert isinstance(res.body.body, SourceCodeWithConceptNode)
assert res.body.body.python_node.source == 'func(__C__ones__1001___PLURAL__C__)'
assert "__C__ones__1001___PLURAL__C__" in res.body.body.python_node.objects
@pytest.mark.parametrize("text, expected_error_type", [
("one", BuiltinConcepts.NOT_FOR_ME), # no function found
("$*!", BuiltinConcepts.NOT_FOR_ME), # no function found
+21
View File
@@ -229,11 +229,13 @@ class TestSequenceNodeParser(TestUsingMemoryBasedSheerka):
sheerka, context, parser = self.init_parser(concepts_map)
res = parser.parse(context, ParserInput("a special concept"))
assert res.status
lexer_nodes = res.body.body
expected_array = compute_expected_array(concepts_map, "a special concept", ["a special concept"])
compare_with_test_object(lexer_nodes, expected_array)
res = parser.parse(context, ParserInput("isa"))
assert res.status
lexer_nodes = res.body.body
expected_array = compute_expected_array(concepts_map, "isa", ["isa"])
compare_with_test_object(lexer_nodes, expected_array)
@@ -442,3 +444,22 @@ class TestSequenceNodeParser(TestUsingMemoryBasedSheerka):
for node in res.body.body:
if hasattr(node, "concept"):
assert node.concept.get_hints().use_copy
def test_i_can_parse_plural(self):
concepts_map = {
"boy": Concept("boy"),
}
sheerka, context, parser = self.init_parser(concepts_map)
boy = concepts_map['boy']
res = parser.parse(context, ParserInput("boys"))
assert res.status
lexer_nodes = res.body.body
assert len(lexer_nodes) == 1
concept_found = lexer_nodes[0].concept
assert concept_found.id == f"{boy.id}-{BuiltinConcepts.PLURAL}"
assert concept_found.name == "boys"
assert concept_found.key == "boys"
assert concept_found.get_prop(BuiltinConcepts.PLURAL) == boy
+21 -22
View File
@@ -159,7 +159,7 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
to_string = sheerkapickle.encode(sheerka, ref_concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == ref_concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "concept/id": ["my_key", "1001"]}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "concept/id": "1001"}'
# same test, modify a value and check if this modification is correctly saved
concept = Concept().update_from(sheerka.get_by_id(ref_concept.id))
@@ -167,26 +167,7 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
to_string = sheerkapickle.encode(sheerka, concept)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == concept
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "concept/id": ["my_key", "1001"], "values": [["#body#", {"_sheerka/obj": "core.concept.Concept", "meta.name": "bar"}]]}'
# def test_i_can_encode_decode_when_variable_is_a_concept(self):
# sheerka = self.get_sheerka()
#
# foo = Concept("foo")
# sheerka.create_new_concept(self.get_context(sheerka), foo)
#
# concept = Concept("my_name")
# sheerka.create_new_concept(self.get_context(sheerka), concept)
# concept.def_var(foo, "a value")
# concept.set_value(foo, "another value")
# concept.get_metadata().full_serialization = True
#
# to_string = sheerkapickle.encode(sheerka, concept)
# decoded = sheerkapickle.decode(sheerka, to_string)
# assert decoded == concept
# assert to_string == '{"_sheerka/obj": "core.concept.Concept", "meta.name": "my_name", "meta.key": "my_name", ' + \
# '"meta.variables": [[{"_sheerka/obj": "core.concept.Concept", "concept/id": ["foo", "1001"]}, "a value"]], ' + \
# '"meta.id": "1002", "values": [[{"_sheerka/id": 1}, "another value"]]}'
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "concept/id": "1001", "values": [["#body#", {"_sheerka/obj": "core.concept.Concept", "meta.name": "bar"}]]}'
def test_i_can_manage_reference_of_the_same_object(self):
sheerka = self.get_sheerka()
@@ -331,7 +312,7 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
def test_i_can_encode_decode_rule(self):
sheerka = self.get_sheerka()
rule = Rule("print", "my rule", "True","Hello world")
rule = Rule("print", "my rule", "True", "Hello world")
rule.metadata.id = "1"
to_string = sheerkapickle.encode(sheerka, rule)
@@ -339,3 +320,21 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
assert to_string == '{"_sheerka/obj": "core.rule.Rule", "rule/id": "1", "name": "my rule", "predicate": "True", "action_type": "print", "action": "Hello world"}'
assert decoded == rule
def test_i_can_encode_decode_dynamic_concept(self):
sheerka, context, foo = self.init_concepts("foo", global_truth=True, create_new=True)
sheerka.set_attr(context, foo, "attr", "attr_value")
sheerka.set_property(context, foo, "prop", "prop_value", all_concepts=True)
foo_instance = sheerka.new(foo)
dynamic_foo = sheerka.new_dynamic(foo_instance,
"SUFFIX",
"new_name",
props={"new_prop": "value"},
attrs={"new_attr": "value"})
to_string = sheerkapickle.encode(sheerka, dynamic_foo)
decoded = sheerkapickle.decode(sheerka, to_string)
assert decoded == dynamic_foo
assert to_string == '{"_sheerka/obj": "core.concept.Concept", "concept/id": "1001-SUFFIX", "meta.name": "new_name", "meta.key": "new_name", "meta.props": {"prop": "prop_value", "new_prop": "value"}, "meta.id": "1001-SUFFIX", "values": [["new_attr", "value"]]}'