Added concept 'isa' other_concept functionality

This commit is contained in:
2019-12-21 22:02:07 +01:00
parent 2474b08150
commit a683d4cd42
13 changed files with 489 additions and 61 deletions
+94
View File
@@ -0,0 +1,94 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import Concept
from core.sheerka import Sheerka, ExecutionContext
from core.tokenizer import Tokenizer
from evaluators.AddConceptInSetEvaluator import AddConceptInSetEvaluator
from parsers.DefaultParser import IsaConceptNode, NameNode
def get_context():
sheerka = Sheerka(skip_builtins_in_db=True)
sheerka.initialize("mem://")
return ExecutionContext("test", "xxx", sheerka)
def get_ret_val(concept_name, concept_set_name):
n1 = NameNode(list(Tokenizer(concept_name)))
n2 = NameNode(list(Tokenizer(concept_set_name)))
return ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([], n1, n2)))
@pytest.mark.parametrize("ret_val, expected", [
(ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([]))), True),
(ReturnValueConcept("some_name", False, ParserResultConcept(value=IsaConceptNode([]))), False),
(ReturnValueConcept("some_name", True, "not a ParserResultConcept"), False),
(ReturnValueConcept("some_name", True, ParserResultConcept()), False),
])
def test_i_can_match(ret_val, expected):
context = get_context()
assert AddConceptInSetEvaluator().matches(context, ret_val) == expected
def test_i_cannot_add_if_the_concept_does_not_exists():
context = get_context()
ret_val = get_ret_val("foo", "bar")
res = AddConceptInSetEvaluator().eval(context, ret_val)
assert not res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
assert res.value.body == "foo"
def test_i_cannot_add_if_the_set_does_not_exists():
context = get_context()
foo = Concept("foo")
context.sheerka.set_id_if_needed(foo, False)
context.sheerka.add_in_cache(foo)
ret_val = get_ret_val("foo", "bar")
res = AddConceptInSetEvaluator().eval(context, ret_val)
assert not res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
assert res.value.body == "bar"
def test_i_can_add_concept_to_a_set_of_concept():
context = get_context()
foo = Concept("foo")
context.sheerka.set_id_if_needed(foo, False)
context.sheerka.add_in_cache(foo)
bar = Concept("bar")
context.sheerka.set_id_if_needed(bar, False)
context.sheerka.add_in_cache(bar)
ret_val = get_ret_val("foo", "bar")
res = AddConceptInSetEvaluator().eval(context, ret_val)
assert res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
def test_i_cannot_add_the_same_concept_twice():
context = get_context()
foo = Concept("foo")
context.sheerka.set_id_if_needed(foo, False)
context.sheerka.add_in_cache(foo)
bar = Concept("bar")
context.sheerka.set_id_if_needed(bar, False)
context.sheerka.add_in_cache(bar)
ret_val = get_ret_val("foo", "bar")
AddConceptInSetEvaluator().eval(context, ret_val)
res = AddConceptInSetEvaluator().eval(context, ret_val)
assert not res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_IN_SET)
assert res.value.concept == foo
assert res.value.concept_set == bar
+53 -24
View File
@@ -6,7 +6,7 @@ from core.sheerka import Sheerka, ExecutionContext
from parsers.ConceptLexerParser import OrderedChoice, StrMatch, ConceptMatch
from parsers.PythonParser import PythonParser, PythonNode
from core.tokenizer import Keywords, Tokenizer
from parsers.DefaultParser import DefaultParser, NameNode, SyntaxErrorNode, CannotHandleErrorNode
from parsers.DefaultParser import DefaultParser, NameNode, SyntaxErrorNode, CannotHandleErrorNode, IsaConceptNode
from parsers.DefaultParser import UnexpectedTokenErrorNode, DefConceptNode
from parsers.BnfParser import BnfParser
@@ -55,24 +55,24 @@ from parsers.BnfParser import BnfParser
# return left_as_string == right_as_string
#
def get_concept(name, where=None, pre=None, post=None, body=None, definition=None):
concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None):
def_concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
if body:
concept.body = get_concept_part(body)
def_concept.body = get_concept_part(body)
if where:
concept.where = get_concept_part(where)
def_concept.where = get_concept_part(where)
if pre:
concept.pre = get_concept_part(pre)
def_concept.pre = get_concept_part(pre)
if post:
concept.post = get_concept_part(post)
def_concept.post = get_concept_part(post)
if definition:
concept.definition = ReturnValueConcept(
def_concept.definition = ReturnValueConcept(
"parsers.Bnf",
True,
definition)
return concept
return def_concept
def get_context():
@@ -145,16 +145,16 @@ def get_concept_part(part):
@pytest.mark.parametrize("text, expected", [
("def concept hello", get_concept(name="hello")),
("def concept hello ", get_concept(name="hello")),
("def concept a + b", get_concept(name="a + b")),
("def concept a+b", get_concept(name="a + b")),
("def concept 'a+b'+c", get_concept(name="'a+b' + c")),
("def concept 'as if'", get_concept(name="'as if'")),
("def concept 'as' if", get_concept(name="'as if'")),
("def concept hello as 'hello'", get_concept(name="hello", body="'hello'")),
("def concept hello as 1", get_concept(name="hello", body="1")),
("def concept hello as 1 + 1", get_concept(name="hello", body="1 + 1")),
("def concept hello", get_def_concept(name="hello")),
("def concept hello ", get_def_concept(name="hello")),
("def concept a + b", get_def_concept(name="a + b")),
("def concept a+b", get_def_concept(name="a + b")),
("def concept 'a+b'+c", get_def_concept(name="'a+b' + c")),
("def concept 'as if'", get_def_concept(name="'as if'")),
("def concept 'as' if", get_def_concept(name="'as if'")),
("def concept hello as 'hello'", get_def_concept(name="hello", body="'hello'")),
("def concept hello as 1", get_def_concept(name="hello", body="1")),
("def concept hello as 1 + 1", get_def_concept(name="hello", body="1 + 1")),
])
def test_i_can_parse_def_concept(text, expected):
parser = DefaultParser()
@@ -178,7 +178,7 @@ as res = a + b
parser = DefaultParser()
res = parser.parse(get_context(), text)
return_value = res.value
expected_concept = get_concept(
expected_concept = get_def_concept(
name="a plus b",
where="a,b",
pre="isinstance(a, int) and isinstance(b, float)",
@@ -199,7 +199,7 @@ def func(x):
func(a)
"""
expected_concept = get_concept(
expected_concept = get_def_concept(
name="add one to a ",
body=PythonNode(
"def func(x):\n return x+1\nfunc(a)",
@@ -223,7 +223,7 @@ def concept add one to a as:
func(a)
"""
expected_concept = get_concept(
expected_concept = get_def_concept(
name="add one to a ",
body=PythonNode(
"def func(x):\n return x+1\nfunc(a)",
@@ -292,7 +292,7 @@ def test_name_is_mandatory():
def test_concept_keyword_is_mandatory_but_the_concept_is_recognized():
text = "def hello as a where b pre c post d"
expected_concept = get_concept(name="hello", body="a", where="b", pre="c", post="d")
expected_concept = get_def_concept(name="hello", body="a", where="b", pre="c", post="d")
parser = DefaultParser()
res = parser.parse(get_context(), text)
return_value = res.value
@@ -342,7 +342,7 @@ def test_i_can_parse_def_concept_from_regex():
node = res.value.value
definition = OrderedChoice(ConceptMatch("a_concept"), StrMatch("a_string"))
parser_result = ParserResultConcept(BnfParser(), "a_concept | 'a_string'", definition, definition)
expected = get_concept(name="name", body="__definition[0]", definition=parser_result)
expected = get_def_concept(name="name", body="__definition[0]", definition=parser_result)
assert res.status
assert res.who == parser.name
@@ -370,3 +370,32 @@ def test_i_can_detect_not_for_me():
assert not res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.NOT_FOR_ME)
assert isinstance(res.value.body[0], CannotHandleErrorNode)
def test_i_can_parse_is_a():
parser = DefaultParser()
text = "the name of my 'concept' isa the name of the set"
res = parser.parse(get_context(), text)
expected = IsaConceptNode([],
concept=NameNode(list(Tokenizer("the name of my 'concept'"))),
set=NameNode(list(Tokenizer("the name of the set"))))
assert res.status
assert res.who == parser.name
assert res.value.source == text
assert isinstance(res.value, ParserResultConcept)
assert res.value.value == expected
@pytest.mark.parametrize("text", [
"concept",
"isa number",
"name isa",
])
def test_i_cannot_parse_invalid_entries(text):
parser = DefaultParser()
res = parser.parse(get_context(), text)
assert not res.status
assert isinstance(res.body, ParserResultConcept)
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
+69 -1
View File
@@ -3,7 +3,7 @@ import os
from os import path
import shutil
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept, ConceptAlreadyInSet
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, Property
from core.sheerka import Sheerka, ExecutionContext
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
@@ -600,3 +600,71 @@ def test_builtin_error_concept_are_errors():
# only test a random one, it will be the same for the others
sheerka = get_sheerka()
assert not sheerka.is_success(sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS))
def test_i_can_add_concept_to_set():
sheerka = get_sheerka(False, False)
foo = Concept("foo")
sheerka.set_id_if_needed(foo, False)
all_foos = Concept("all_foos")
sheerka.set_id_if_needed(all_foos, False)
context = get_context(sheerka)
res = sheerka.add_concept_to_set(context, foo, all_foos)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
all_entries = get_sheerka(False, False).sdp.get("All_" + all_foos.id, None, False)
assert len(all_entries) == 1
assert foo.id in all_entries
def test_i_can_add_several_concepts_to_set():
sheerka = get_sheerka(False, False)
foo1 = Concept("foo1")
sheerka.set_id_if_needed(foo1, False)
foo2 = Concept("foo1")
sheerka.set_id_if_needed(foo2, False)
all_foos = Concept("all_foos")
sheerka.set_id_if_needed(all_foos, False)
context = get_context(sheerka)
sheerka.add_concept_to_set(context, foo1, all_foos)
res = sheerka.add_concept_to_set(context, foo2, all_foos)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
all_entries = get_sheerka(False, False).sdp.get("All_" + all_foos.id, None, False)
assert len(all_entries) == 2
assert foo1.id in all_entries
assert foo2.id in all_entries
def test_i_cannot_add_the_same_concept_twice_in_a_set():
sheerka = get_sheerka()
foo = Concept("foo")
sheerka.set_id_if_needed(foo, False)
all_foos = Concept("all_foos")
sheerka.set_id_if_needed(all_foos, False)
context = get_context(sheerka)
sheerka.add_concept_to_set(context, foo, all_foos)
res = sheerka.add_concept_to_set(context, foo, all_foos)
assert not res.status
assert res.body == ConceptAlreadyInSet(foo, all_foos)
all_entries = sheerka.sdp.get("All_" + all_foos.id, None, False)
assert len(all_entries) == 1
assert foo.id in all_entries
+10 -5
View File
@@ -836,15 +836,20 @@ def test_i_can_add_a_dictionary_as_a_reference(root):
])
def test_i_can_add_unique(root):
sdp = SheerkaDataProvider(root)
sdp.add_unique(evt_digest, "entry", ObjNoKey(1, "foo"))
sdp.add_unique(evt_digest, "entry", ObjNoKey(1, "foo"))
sdp.add_unique(evt_digest, "entry", ObjNoKey(2, "bar"))
entry, key = sdp.add_unique(evt_digest, "entry", ObjNoKey(1, "foo"))
assert (entry, key) == ("entry", None)
entry, key = sdp.add_unique(evt_digest, "entry", ObjNoKey(1, "foo"))
assert (entry, key) == (None, None)
entry, key = sdp.add_unique(evt_digest, "entry", ObjNoKey(2, "bar"))
assert (entry, key) == ("entry", None)
entry, key = sdp.add_unique(evt_digest, "entry", ObjNoKey(2, "bar"))
assert (entry, key) == (None, None)
state = sdp.load_state(sdp.get_snapshot())
assert state.data == {"entry": {ObjNoKey(1, "foo"), ObjNoKey(2, "bar")}}
assert entry == "entry"
assert key is None
@pytest.mark.parametrize("root", [
+33 -23
View File
@@ -30,6 +30,32 @@ def init_test():
os.chdir(current_pwd)
def get_sheerka(use_dict=True, skip_builtins_in_db=True):
root = "mem://" if use_dict else root_folder
sheerka = Sheerka(skip_builtins_in_db=skip_builtins_in_db)
sheerka.initialize(root)
return sheerka
def get_context(sheerka):
return ExecutionContext("test", "xxx", sheerka)
def get_default_concept():
concept = Concept(
name="a + b",
where="isinstance(a, int) and isinstance(b, int)",
pre="isinstance(a, int) and isinstance(b, int)",
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")
return concept
@pytest.mark.parametrize("text, expected", [
("1 + 1", 2),
("sheerka.test()", 'I have access to Sheerka !')
@@ -382,27 +408,11 @@ def test_i_can_eval_bnf_definitions_from_separate_instances():
assert sheerka.isinstance(res[0].value, concept_b)
def get_sheerka(use_dict=True, skip_builtins_in_db=True):
root = "mem://" if use_dict else root_folder
sheerka = Sheerka(skip_builtins_in_db=skip_builtins_in_db)
sheerka.initialize(root)
def test_i_can_say_that_a_concept_isa_another_concept():
sheerka = get_sheerka()
sheerka.evaluate_user_input("def concept foo")
sheerka.evaluate_user_input("def concept bar")
return sheerka
def get_context(sheerka):
return ExecutionContext("test", "xxx", sheerka)
def get_default_concept():
concept = Concept(
name="a + b",
where="isinstance(a, int) and isinstance(b, int)",
pre="isinstance(a, int) and isinstance(b, int)",
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")
return concept
res = sheerka.evaluate_user_input("foo isa bar")
assert res[0].status
assert sheerka.isinstance(res[0].body, BuiltinConcepts.SUCCESS)