Fixed #68: Implement SheerkaQL

Fixed #70: SheerkaFilterManager : Pipe functions
Fixed #71: SheerkaFilterManager : filter_objects
Fixed #75: SheerkaMemory: Enhance memory() to use the filtering capabilities
Fixed #76: SheerkaEvaluateConcept: Concepts that modify the state of the system must not be evaluated during question
This commit is contained in:
2021-04-26 19:13:47 +02:00
parent bef5f3208c
commit 1059ce25c5
57 changed files with 5759 additions and 1302 deletions
+47 -3
View File
@@ -12,9 +12,12 @@ class TestExecutionContext(TestUsingMemoryBasedSheerka):
def test_id_is_incremented_by_event_digest(self):
sheerka = self.get_sheerka()
a = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
b = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
c = ExecutionContext("foo", Event("event_2"), sheerka, BuiltinConcepts.NOP, None)
event1 = Event("event_1")
event2 = Event("event_2")
a = ExecutionContext("foo", event1, sheerka, BuiltinConcepts.NOP, None)
b = ExecutionContext("foo", event1, sheerka, BuiltinConcepts.NOP, None)
c = ExecutionContext("foo", event2, sheerka, BuiltinConcepts.NOP, None)
d = b.push(BuiltinConcepts.NOP, None)
e = c.push(BuiltinConcepts.NOP, None)
@@ -177,6 +180,47 @@ class TestExecutionContext(TestUsingMemoryBasedSheerka):
assert sub2.has_parent(root.id)
assert not sub1.has_parent(sub2.id)
assert not sub2.has_parent(sub1.id)
def test_i_can_reset_global_hints(self):
sheerka = self.get_sheerka()
context = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
context.add_to_global_hints(BuiltinConcepts.TESTING)
context.add_to_global_hints(BuiltinConcepts.DEBUG)
sub_context1 = context.push(BuiltinConcepts.NOP, None)
assert BuiltinConcepts.TESTING in sub_context1.global_hints
assert BuiltinConcepts.DEBUG in sub_context1.global_hints
sub_context2 = context.push(BuiltinConcepts.NOP, None, reset_hints={BuiltinConcepts.TESTING})
assert BuiltinConcepts.TESTING not in sub_context2.global_hints
assert BuiltinConcepts.DEBUG in sub_context2.global_hints
sub_context3 = context.push(BuiltinConcepts.NOP,
None,
reset_hints={BuiltinConcepts.DEBUG, BuiltinConcepts.TESTING})
assert sub_context3.global_hints == set()
def test_i_can_reset_protected_hints(self):
sheerka = self.get_sheerka()
context = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
context.add_to_protected_hints(BuiltinConcepts.TESTING)
context.add_to_protected_hints(BuiltinConcepts.DEBUG)
sub_context1 = context.push(BuiltinConcepts.NOP, None)
assert BuiltinConcepts.TESTING in sub_context1.protected_hints
assert BuiltinConcepts.DEBUG in sub_context1.protected_hints
sub_context2 = context.push(BuiltinConcepts.NOP, None, reset_hints={BuiltinConcepts.TESTING})
assert BuiltinConcepts.TESTING not in sub_context2.protected_hints
assert BuiltinConcepts.DEBUG in sub_context2.protected_hints
sub_context3 = context.push(BuiltinConcepts.NOP,
None,
reset_hints={BuiltinConcepts.DEBUG, BuiltinConcepts.TESTING})
assert sub_context3.protected_hints == set()
# def test_variables_are_passed_to_children_but_not_to_parents(self):
# sheerka = self.get_sheerka()
#
+2 -23
View File
@@ -2,7 +2,7 @@ import pytest
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, ParserResultConcept
from core.concept import Concept, DoNotResolve, ConceptParts, InfiniteRecursionResolved, \
concept_part_value, DEFINITION_TYPE_DEF
DEFINITION_TYPE_DEF
from core.global_symbols import NotInit, NotFound
from core.sheerka.services.SheerkaEvaluateConcept import SheerkaEvaluateConcept
from core.sheerka.services.SheerkaMemory import SheerkaMemory
@@ -420,7 +420,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
concept = Concept("foo", body="a")
evaluated = sheerka.evaluate_concept(context, concept)
assert evaluated.key == concept.key
compare_with_test_object(evaluated.body, CB("a", "concept_a")) # this test was already done
compare_with_test_object(evaluated.body, CB("a", "concept_a")) # this test was already done
# so check this one.
concept = Concept("foo", body="a").def_var("a", "'property_a'")
@@ -784,27 +784,6 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
assert evaluated.key == command.key
assert sheerka.get_from_memory(context, "a").obj == 10
@pytest.mark.parametrize("metadata", [
ConceptParts.WHERE,
ConceptParts.PRE,
ConceptParts.POST,
ConceptParts.RET
])
def test_i_cannot_evaluate_python_statement_in_where_pre_post_ret(self, metadata, capsys):
sheerka, context, foo = self.init_concepts("foo")
setattr(foo.get_metadata(), concept_part_value(metadata), "a=10; print('10')")
foo.get_metadata().need_validation = True
evaluated = sheerka.evaluate_concept(context, foo, eval_body=True)
captured = capsys.readouterr()
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
error = evaluated.body
assert sheerka.isinstance(error, BuiltinConcepts.PYTHON_SECURITY_ERROR)
assert error.prop == metadata
assert error.body == "a=10; print('10')"
assert captured.out == ""
def test_python_builtin_function_are_forbidden_in_where_pre_post_ret(self, capsys):
# I do the test only for PRE, as it will be the same for the other ConceptPart
sheerka, context, foo, bar = self.init_concepts(
+11 -10
View File
@@ -9,8 +9,9 @@ from core.sheerka.Sheerka import RECOGNIZED_BY_ID, RECOGNIZED_BY_NAME
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules, LOW_PRIORITY_RULES, DISABLED_RULES
from core.sheerka.services.SheerkaExecute import ParserInput
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, CompiledCondition
from evaluators.PythonEvaluator import PythonEvaluator, Expando
from evaluators.PythonEvaluator import PythonEvaluator
from parsers.PythonParser import PythonParser
from sheerkapython.python_wrapper import Expando
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@@ -84,7 +85,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
# create fake compiled predicates
parser = PythonParser()
my_rule.compiled_conditions = [
CompiledCondition(PythonEvaluator.NAME, parser.parse(context, ParserInput(exp)), set(), set(), None)
CompiledCondition(PythonEvaluator.NAME, parser.parse(context, ParserInput(exp)), set(), set(), None, set())
for exp in predicates]
my_rule.metadata.is_compiled = True
my_rule.metadata.is_enabled = True
@@ -114,9 +115,9 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
assert res == {True: [r1, r3], False: [r2]}
@pytest.mark.parametrize("predicate", [
"greetings",
"c:|1001:",
"hello 'kodjo'"
"recognize(__ret.body, greetings)",
"recognize(__ret.body, c:|1001:)",
"recognize(__ret.body, hello 'kodjo')"
])
def test_i_can_evaluate_rules_when_concepts_are_not_questions(self, predicate):
"""
@@ -146,7 +147,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("there"),
create_new=True).with_format_rules(
Rule(predicate="hello there", action="")).unpack()
Rule(predicate="recognize(__ret.body, hello there)", action="")).unpack()
service = sheerka.services[SheerkaEvaluateRules.NAME]
there_instance = sheerka.new_from_template(there, there.key)
@@ -169,7 +170,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("my friend"),
create_new=True).with_format_rules(
Rule(predicate="hello my friend", action="")).unpack()
Rule(predicate="recognize(__ret.body, hello my friend)", action="")).unpack()
service = sheerka.services[SheerkaEvaluateRules.NAME]
my_friend_instance = sheerka.new_from_template(my_friend, my_friend.key)
@@ -183,7 +184,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
sheerka, context, greetings, rule = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
create_new=True).with_format_rules(
Rule(predicate="hello sheerka", action="")).unpack()
Rule(predicate="recognize(__ret.body, hello sheerka)", action="")).unpack()
service = sheerka.services[SheerkaEvaluateRules.NAME]
ret = sheerka.ret("evaluator", True, sheerka.new(greetings, a=Expando("sheerka", {})))
@@ -196,7 +197,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("greetings", definition="hi a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
create_new=True).with_format_rules(
Rule(predicate="greetings", action="")).unpack()
Rule(predicate="recognize(__ret.body, greetings)", action="")).unpack()
service = sheerka.services[SheerkaEvaluateRules.NAME]
ret1 = sheerka.ret("evaluator", True, sheerka.new(g1, a="kodjo"))
@@ -210,7 +211,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
def test_i_can_evaluate_concept_rule_with_the_same_name_when_the_second_concept_is_declared_after(self):
sheerka, context, g1, rule, g2 = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
create_new=True).with_format_rules(Rule(predicate="greetings", action="")).with_concepts(
create_new=True).with_format_rules(Rule(predicate="recognize(__ret.body, greetings)", action="")).with_concepts(
Concept("greetings", definition="hi a", definition_type=DEFINITION_TYPE_DEF).def_var("a")).unpack()
service = sheerka.services[SheerkaEvaluateRules.NAME]
+41 -1
View File
@@ -87,7 +87,9 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
foo = Concept("foo")
sheerka.add_to_memory(context, "a", foo)
assert sheerka.om.copy(SheerkaMemory.OBJECTS_ENTRY) == {"a": MemoryObject(context.event.get_digest(), foo)}
assert sheerka.om.copy(SheerkaMemory.OBJECTS_ENTRY) == {"a": MemoryObject(context.event.get_digest(),
context.event.date.timestamp(),
foo)}
assert id(sheerka.get_from_memory(context, "a").obj) == id(foo)
def test_i_can_use_memory_with_a_string(self):
@@ -106,6 +108,44 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
assert sheerka.memory(context, Concept("foo")) == foo
def test_i_can_use_memory_with_a_query(self):
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
sheerka.add_to_memory(context, "x", foo)
sheerka.add_to_memory(context, "y", bar)
assert sheerka.memory(context, "self.name == 'foo'") == foo
def test_i_retrieve_the_last_entry_when_requesting_memory_with_a_query(self):
sheerka, context, foo, bar, foo2 = self.init_concepts("foo", "bar", Concept("foo", body="2"))
sheerka.add_to_memory(context, "x", foo)
sheerka.add_to_memory(context, "y", bar)
context2 = self.get_context(sheerka) # timestamp is newer
sheerka.add_to_memory(context2, "z", foo2)
assert sheerka.memory(context, "self.name == 'foo'") == foo2
def test_i_can_look_in_the_previous_objects_when_using_query_to_request_the_memory(self):
sheerka, context, foo, bar, baz = self.init_concepts("foo", "bar", "baz")
sheerka.add_to_memory(context, "x", foo)
sheerka.add_to_memory(context, "y", bar)
sheerka.add_to_memory(context, "z", baz)
# another layer
sheerka.add_to_memory(context, "x", bar)
sheerka.add_to_memory(context, "y", baz)
# another layer
sheerka.add_to_memory(context, "x", baz)
# so under x there is [foo] -> [bar] -> [baz]
# so under y there is [bar] -> [baz]
# so under z there is [baz]
assert sheerka.memory(context, "self.name == 'foo'") == foo
def test_concept_not_found_is_return_when_not_found(self):
sheerka, context = self.init_test().unpack()
+205
View File
@@ -0,0 +1,205 @@
from dataclasses import dataclass
import pytest
from core.builtin_concepts_ids import BuiltinConcepts
from core.concept import Concept
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@dataclass
class A:
prop1: object
prop2: object
def __eq__(self, other):
if not isinstance(other, A):
return False
return self.prop1 == other.prop1 and self.prop2 == other.prop2
def __hash__(self):
hash_res = []
for p in [self.prop1, self.prop2]:
hash_res.append(0 if isinstance(p, (list, dict, set)) else p)
return hash(tuple(hash_res))
@dataclass
class B(A):
def as_bag(self):
return {
"fake_prop1": self.prop1,
"fake_prop2": self.prop2
}
def __hash__(self):
return hash((self.prop1, self.prop2))
class TestSheerkaQueryManager(TestUsingMemoryBasedSheerka):
def test_i_can_filter_objects_using_kwargs(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
assert sheerka.filter_objects(context, lst, prop1="a21") == [lst[1]]
assert sheerka.filter_objects(context, lst, prop2=10) == [lst[0]]
assert sheerka.filter_objects(context, lst, prop2=3.14) == [lst[1]]
assert sheerka.filter_objects(context, lst, prop2=0xab) == [lst[2]]
assert sheerka.filter_objects(context, lst, prop1=[0, 1]) == [lst[3]]
assert sheerka.filter_objects(context, lst, prop2={"key": "value"}) == [lst[3]]
# assert sheerka.filter_objects(context, lst, prop1={1, "v"}) == [lst[2]] set are not supported
def test_i_can_filter_by_object_type(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", "a12"), Concept("foo", body="a").auto_init(), Concept("foo", body="b").auto_init()]
assert sheerka.filter_objects(context, lst, __type="foo") == [lst[1], lst[2]]
def test_i_can_filter_on_atomic_def(self):
sheerka, context, isa, plus, isa2 = self.init_concepts(
Concept('x is a y').def_var("x").def_var("y"),
Concept('a plus b').def_var("a").def_var("b"),
Concept('u is a v').def_var("u").def_var("v"),
)
lst = [isa, plus, isa2]
assert sheerka.filter_objects(context, lst, atomic_def="is a") == [lst[0], lst[2]]
def test_i_can_filter_on_as_bag_property(self):
sheerka, context = self.init_test().unpack()
lst = [B("a11", "a12"), B("a21", "a22"), B("a31", "a32")]
assert sheerka.filter_objects(context, lst, fake_prop1="a21") == [lst[1]]
def test_i_can_filter_container(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
container = sheerka.new(BuiltinConcepts.EXPLANATION, body=lst, digest="xxx", command="text")
res = sheerka.filter_objects(context, container, prop1="a21")
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
assert res.digest == "xxx"
assert res.command == "text"
assert res.body == [lst[1]]
def test_i_can_filter_when_property_does_not_exist(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", "a12"), B("a21", "a22"), B("a31", "a32")]
assert sheerka.filter_objects(context, lst, prop1="a11") == [lst[0]]
def test_i_can_filter_objets_using_predicate(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10),
A("a21", 3.14),
A({1, "v"}, 0xab),
A([0, 1], {"key": "value"}),
Concept("foo", body="a").auto_init(),
B("a21", "a22"),
Concept("foo", body="b").auto_init(),
B("a31", "a32")]
assert sheerka.filter_objects(context, lst, "self.prop1 == 'a21'") == [lst[1]]
assert sheerka.filter_objects(context, lst, "self.prop2 >= 1") == [lst[0], lst[1], lst[2]]
assert sheerka.filter_objects(context, lst, "get_type(self) == 'foo' ") == [lst[4], lst[6]]
assert sheerka.filter_objects(context, lst, "self.fake_prop1 == 'a21' ") == [lst[5]]
assert sheerka.filter_objects(context, lst, "hasattr(self, 'fake_prop1')") == [lst[5], lst[7]]
def test_i_can_filter_object_using_predicate_and_sheerka_objects(self):
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
lst = [foo, bar, A("a21", 3.14)]
assert sheerka.filter_objects(context, lst, "self == bar") == [lst[1]]
def test_i_can_filter_objects_using_concept(self):
sheerka, context, foo, bar, isa = self.init_concepts(
"foo",
"bar",
Concept("x is a concept", body="isinstance(x, Concept)", pre="is_question()").def_var("x"),
create_new=True)
lst = [foo, A("a21", 3.14), bar, B("a21", 3.14)]
assert sheerka.filter_objects(context, lst, "self is a concept") == [foo, bar]
def test_i_can_filter_objects_when_no_kwargs_and_no_predicate(self):
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
lst = [foo, bar, A("a21", 3.14)]
assert sheerka.filter_objects(context, lst) == lst
def test_i_must_select_object_property_using_string(self):
sheerka, context = self.init_test().unpack()
with pytest.raises(SyntaxError):
sheerka.select_objects(context, [], 00)
def test_i_can_select_objects_with_args(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
assert sheerka.select_objects(context, lst, "prop1", "prop2") == (
('a11', 10),
('a21', 3.14),
({1, 'v'}, 171),
([0, 1], {'key': 'value'}))
def test_i_can_select_objects_when_container(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
container = sheerka.new(BuiltinConcepts.EXPLANATION, body=lst, digest="xxx", command="text")
res = sheerka.select_objects(context, container, "prop1", "prop2")
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
assert res.digest == "xxx"
assert res.command == "text"
assert res.body == (('a11', 10),
('a21', 3.14),
({1, 'v'}, 171),
([0, 1], {'key': 'value'}))
def test_i_can_select_objects_with_complicated_request(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab)]
assert sheerka.select_objects(context, lst, "self.prop2 + 5") == (15, 8.14, 0xab + 5)
assert sheerka.select_objects(context, lst, "isinstance(self.prop1, str)") == (True, True, False)
def test_error_when_collecting_returns_are_managed(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10), A("a21", {"key": "value"})]
res = sheerka.select_objects(context, lst, "self.prop2 + 5")
assert len(res) == 2
assert res[0] == 15
assert isinstance(res[1], TypeError)
def test_i_can_select_objects_using_kwargs(self):
sheerka, context = self.init_test().unpack()
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
assert sheerka.select_objects(context, lst, p1="prop1", p2="prop2") == (
{"p1": "a11", "p2": 10},
{"p1": "a21", "p2": 3.14},
{"p1": {1, "v"}, "p2": 0xab},
{"p1": [0, 1], "p2": {"key": "value"}},
)
def test_i_can_collect_attributes(self):
sheerka = self.get_sheerka()
lst = [A("", ""),
B("", ""),
Concept("foo").def_var("a").auto_init(),
Concept("bar").def_var("y").def_var("x").auto_init()]
res = sheerka.collect_attributes(lst)
assert sheerka.isinstance(res, BuiltinConcepts.TO_DICT)
assert res.body == {
"A": ["prop1", "prop2"],
"B": ["fake_prop1", "fake_prop2"],
"foo": ["a", 'body', 'id', 'key', 'name'],
"bar": ['body', 'id', 'key', 'name', "x", "y"] # attributes are sorted
}
+12 -741
View File
@@ -1,5 +1,3 @@
import ast
import pytest
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
@@ -7,26 +5,20 @@ from core.concept import Concept, DEFINITION_TYPE_DEF
from core.global_symbols import RULE_COMPARISON_CONTEXT, NotFound, EVENT_RULE_DELETED
from core.rule import Rule, ACTION_TYPE_PRINT, ACTION_TYPE_EXEC
from core.sheerka.Sheerka import RECOGNIZED_BY_ID, RECOGNIZED_BY_NAME
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules
from core.sheerka.services.SheerkaExecute import ParserInput
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleActionParser, \
FormatAstRawText, FormatAstVariable, FormatAstSequence, FormatAstFunction, \
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, FormatAstDict, \
FormatAstMulti, \
PythonCodeEmitter, FormatAstNode, ReteConditionExprVisitor, PythonConditionExprVisitor, \
CompiledCondition
PythonCodeEmitter, FormatAstNode, ReteConditionExprVisitor
from core.tokenizer import Token, TokenKind
from evaluators.PythonEvaluator import Expando
from parsers.BaseParser import ErrorSink
from parsers.ExpressionParser import ExpressionParser
from parsers.PythonParser import PythonNode
from sheerkarete.common import V
from sheerkarete.conditions import Condition, AndConditions, FilterCondition
from sheerkarete.conditions import FilterCondition
from sheerkarete.network import ReteNetwork
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import get_rete_conditions, NEGCOND, \
NCCOND
from tests.parsers.parsers_utils import get_rete_conditions, NEGCOND, NCCOND
seq = FormatAstSequence
raw = FormatAstRawText
@@ -188,7 +180,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
rule = service.init_rule(context, rule)
assert len(rule.error_sink["when"]) > 0
assert sheerka.is_error(rule.error_sink["when"][0])
assert sheerka.has_error(context, rule.error_sink["when"][0])
assert "print" not in rule.error_sink
assert "then" not in rule.error_sink
assert rule.metadata.is_compiled
@@ -210,7 +202,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
other_action_type = ACTION_TYPE_PRINT if action_type == ACTION_TYPE_EXEC else ACTION_TYPE_EXEC
assert sheerka.is_error(rule.error_sink[action_type])
assert sheerka.has_error(context, rule.error_sink[action_type])
assert other_action_type not in rule.error_sink
assert "when" not in rule.error_sink
assert rule.metadata.is_compiled
@@ -282,30 +274,6 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
assert parser.error_sink == expected_error
@pytest.mark.parametrize("text, compiled_text", [
("a == 5", "a == 5"),
("foo > 5", "foo > 5"),
("func() == 5", "func() == 5"),
("not a == 5", "not (a == 5)"),
("not foo > 5", "not (foo > 5)"),
("not func() == 5", "not (func() == 5)"),
])
def test_i_can_compile_predicate_when_pure_python(self, text, compiled_text):
sheerka, context, *concepts = self.init_concepts("foo")
service = sheerka.services[SheerkaRuleManager.NAME]
ast_ = ast.parse(compiled_text, "<source>", 'eval')
expected_python_node = PythonNode(compiled_text, ast_)
compilation_result = service.compile_when(context, "test", text)
res = compilation_result.python_conditions
assert len(res) == 1
assert isinstance(res[0], CompiledCondition)
assert res[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(res[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(res[0].return_value) == expected_python_node
assert res[0].concept is None
def test_i_can_get_rule_priorities(self):
sheerka, context, rule_true, rule_false = self.init_test().with_format_rules(("True", "True"),
("False", "False")).unpack()
@@ -499,20 +467,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
res = sheerka.get_exec_rules()
assert res == [r2, r3, r1]
@pytest.mark.skip
def test_i_can_compile_rete_using_name(self):
sheerka, context, *concepts = self.init_test().unpack()
service = sheerka.services[SheerkaRuleManager.NAME]
text = "__ret"
compilation_result = service.compile_when(context, "test", text)
res = compilation_result.rete_disjunctions
assert len(res) == 1
assert isinstance(res[0], AndConditions)
assert res[0].conditions == [Condition(V("__x_00__"), "__name__", "__ret")]
def test_i_can_properly_copy_a_rule(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaRuleManager.NAME]
@@ -525,98 +479,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
for k, v in vars(rule).items():
assert getattr(clone, k) == getattr(rule, k)
@pytest.mark.parametrize("expression, expected_as_str, expected_variables", [
(
"__ret",
["#__x_00__|__name__|'__ret'"],
{"__ret"}
),
(
"__ret.status == True",
["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
{"__ret"}
),
(
"__ret.status",
["#__x_00__|__name__|'__ret.status'"],
{"__ret.status"}
),
(
"body",
["#__x_00__|__name__|'body'"],
{"body"}
),
(
"__ret and __ret.status",
["#__x_00__|__name__|'__ret'", "#__x_01__|__name__|'__ret.status'"],
{"__ret", "__ret.status"}
),
])
def test_i_can_get_rete_conditions(self, expression, expected_as_str, expected_variables):
sheerka, context = self.init_test().unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
return_value = ReturnValueConcept("Test", True, None)
if "__ret" in expected_variables:
network.add_obj("__ret", return_value)
if "__ret.status" in expected_variables:
network.add_obj("__ret.status", return_value.status)
if "body" in expected_variables:
network.add_obj("body", return_value.body)
matches = list(network.matches)
assert len(matches) == 1
def test_i_can_get_rete_conditions_when_no_attribute(self):
sheerka, context = self.init_test().unpack()
expression = "a == 10"
expected_as_str = ["#__x_00__|__name__|'a'", "#__x_00__|__self__|10"]
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
network.add_obj("a", 10)
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.skip("No ready yet for SheerkaFilterCondition")
def test_i_can_get_rete_conditions_when_function(self):
sheerka, context, greetings = self.init_test().with_concepts(
@@ -652,235 +514,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
# matches = list(network.matches)
# assert len(matches) == 1
@pytest.mark.parametrize("test_name, expression, variable_name, expected_as_str", [
(
"recognize by name",
"recognize(__ret.body, greetings)",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"]
),
(
"recognize by id",
"recognize(__ret.body, c:|1001:)",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|id|'1001'"]
),
(
"recognize by name using c_str",
"recognize(__ret.body, c:greetings:)",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"]
),
(
"recognize by name and add other conditions (str)",
"recognize(__ret.body, greetings) and __ret.body.a == 'my friend'",
"my friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|'my friend'"]
),
(
"recognize by name and add other conditions (sheerka)",
"recognize(__ret.body, greetings) and __ret.body.a == sheerka",
"sheerka",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|'__sheerka__'"]
),
(
"recognize by name and add other conditions (concept)",
"recognize(__ret.body, greetings) and __ret.body.a == foo",
"foo",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'"]
),
(
"recognize by instance",
"recognize(__ret.body, hello sheerka)",
"sheerka",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'__sheerka__'"]
),
(
"recognize by instance",
"recognize(__ret.body, hello 'my friend')",
"my friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'my friend'"]
),
(
"recognize by instance",
"recognize(__ret.body, hello foo)",
"foo",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'",
]
),
(
"recognize by instance when long concept",
"recognize(__ret.body, hello my best friend)",
"my best friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'my best friend'",
]
),
])
def test_i_can_get_rete_using_recognize_function(self, test_name, expression, variable_name, expected_as_str):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": sheerka
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
network.add_obj("__ret", ReturnValueConcept("Test", True, to_recognize))
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.parametrize("expression, variable_name, expected_as_str", [
(
"greetings",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"]
),
(
"c:|1001:",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|id|'1001'"]
),
(
"hello foo",
"foo",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'",
]
),
(
"hello my best friend",
"my best friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'my best friend'",
]
),
])
def test_i_can_get_rete_when_a_concept_is_recognized(self, expression, variable_name, expected_as_str):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": sheerka
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
network.add_obj("__ret", ReturnValueConcept("Test", True, to_recognize))
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.parametrize("expression, bag_key, expected", [
("not __ret", "__other", [NEGCOND("#__x_00__|__name__|'__ret'")]),
("not not __ret", "__ret", ["#__x_00__|__name__|'__ret'"]),
@@ -894,6 +527,10 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'__sheerka__'"])]),
("__ret and not __error", "__ret", ["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__error'")]),
("not recognize(self, hello sheerka)", "__ret", ["#__x_00__|__name__|'self'",
NCCOND(["#__x_00__|__is_concept__|True",
"#__x_00__|key|'hello __var__0'",
"#__x_00__|a|'__sheerka__'"])]),
])
def test_i_can_get_rete_using_not(self, expression, bag_key, expected):
sheerka, context, greetings, foo = self.init_test().with_concepts(
@@ -914,7 +551,7 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
assert conditions == [expected_conditions]
@pytest.mark.skip("I am not sure yet of what I want to get")
@pytest.mark.parametrize("expression, expected_as_str", [
@pytest.mark.parametrize("expression, expected_as_list_of_str", [
(
"eval(__ret.body, 'foo' starts with 'f')",
["#__x_00__|__name__|'__ret'",
@@ -926,7 +563,7 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
"$eval(__x_01__, a, b, c)"]
),
])
def test_i_can_get_rete_conditions_using_eval_function(self, expression, expected_as_str):
def test_i_can_get_rete_conditions_using_eval_function(self, expression, expected_as_list_of_str):
sheerka, context, start_with = self.init_test().with_concepts(
Concept("x starts with y",
pre="is_question",
@@ -935,7 +572,7 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
expected = get_rete_conditions(*expected_as_list_of_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
@@ -961,372 +598,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.parametrize("expression, expected_compiled, expected_variables", [
("__ret", None, {"__ret"}),
("__ret.status == True", "__ret.status == True", {"__ret"}),
("__ret.status", None, {"__ret.status"}),
("body", None, {"body"}),
("__ret and __ret.status", None, {"__ret", "__ret.status"})
])
def test_i_can_get_compiled_conditions(self, expression, expected_compiled, expected_variables):
sheerka, context = self.init_test().unpack()
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].concept is None
assert conditions[0].variables == expected_variables
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
return_value = ReturnValueConcept("Test", True, None)
bag = {}
if "__ret" in expected_variables:
bag["__ret"] = return_value
if "__ret.status" in expected_variables:
bag["__ret.status"] = return_value.status
if "body" in expected_variables:
bag["body"] = return_value.body
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
def test_i_can_get_compiled_conditions_when_no_attribute(self):
sheerka, context = self.init_test().unpack()
expression = "a == 10"
expected_compiled = "a == 10"
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
assert conditions[0].concept is None
assert conditions[0].variables == {"a"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
bag = {"a": 10}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
def test_i_can_get_compiled_conditions_when_function(self):
sheerka, context, greetings = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
).unpack()
expression = "isinstance(a, greetings)"
expected_compiled = "isinstance(a, greetings)"
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
assert conditions[0].concept is None
assert conditions[0].variables == {"a"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
bag = {"a": sheerka.new(greetings, a="my friend")}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
@pytest.mark.parametrize("expression, variable_name, expected_compiled", [
(
"recognize(__ret.body, greetings)",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'"
),
(
"recognize(__ret.body, c:|1001:)",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'"
),
(
"recognize(__ret.body, c:greetings:)",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'"
),
(
"recognize(__ret.body, greetings) and __ret.body.a == 'my friend'",
"my friend",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __x_00__.a == 'my friend'"
),
(
"recognize(__ret.body, greetings) and __ret.body.a == sheerka",
"sheerka",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and is_sheerka(__x_00__.a)"""
),
(
"recognize(__ret.body, greetings) and __ret.body.a == foo",
"foo",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
),
(
"recognize(__ret.body, hello sheerka)",
"sheerka",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and is_sheerka(__x_00__.a)"""
),
(
"recognize(__ret.body, hello 'my friend')",
"my friend",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == 'my friend'"""
),
(
"recognize(__ret.body, hello foo)",
"foo",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
),
(
"recognize(__ret.body, hello my best friend)",
"my best friend",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'my best friend'"""
),
])
def test_i_can_get_compiled_using_recognize_function(self, expression, variable_name, expected_compiled):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'exec')
expected_python_node = PythonNode(expected_compiled, ast_, expected_compiled)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].concept is None
assert conditions[0].variables == {"__ret"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": Expando("sheerka", {})
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
bag = {"__ret": ReturnValueConcept("Test", True, to_recognize)}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_using_recognize_function", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
@pytest.mark.parametrize("expression, variable_name, expected_compiled", [
(
"greetings",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'"
),
(
"c:|1001:",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'"
),
(
"hello foo",
"foo",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
),
(
"hello my best friend",
"my best friend",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'my best friend'"""
),
])
def test_i_can_get_compiled_when_a_concept_is_recognized(self, expression, variable_name, expected_compiled):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'exec')
expected_python_node = PythonNode(expected_compiled, ast_, expected_compiled)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].concept is None
assert conditions[0].variables == {"__ret"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": Expando("sheerka", {})
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
bag = {"__ret": ReturnValueConcept("Test", True, to_recognize)}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_using_recognize_function", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
@pytest.mark.parametrize("expression, expected_compiled, variables, not_variables", [
("not __ret", None, set(), {"__ret"}),
("not not __ret", None, {"__ret"}, set()),
("not __ret.status == True", "not (__ret.status == True)", {"__ret"}, set()),
("not __ret.status", None, set(), {"__ret.status"},),
("__ret and not __ret.status", None, {"__ret"}, {"__ret.status"}),
("not recognize(__ret.body, hello sheerka)", """__x_00__ = __ret.body
not (isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and is_sheerka(__x_00__.a))""", {"__ret"},
set()),
("__ret and not __error", None, {"__ret"}, {"__error"}),
])
def test_i_can_get_compiled_condition_using_not(self, expression, expected_compiled, variables, not_variables):
sheerka, context, greetings, foo = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
).unpack()
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
if "\n" in expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'exec')
else:
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].variables == variables
assert conditions[0].not_variables == not_variables
assert conditions[0].concept is None
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
ret_val_key = "__ret" if "__ret" in conditions[0].variables else "__other"
bag = {ret_val_key: ReturnValueConcept("Test", False, None)}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
def test_rules_are_initialized_at_startup(self):
File diff suppressed because it is too large Load Diff
+11
View File
@@ -182,6 +182,17 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka):
concept = Concept("foo", pre=pre)
assert core.builtin_helpers.is_a_question(context, concept) == expected
def test_context_hints_are_reset_when_call_evaluate_from_source(self):
sheerka, context, one = self.init_concepts(Concept("one", body="1"))
context.add_to_global_hints(BuiltinConcepts.EVAL_BODY_REQUESTED)
context.add_to_protected_hints(BuiltinConcepts.EVAL_BODY_REQUESTED)
context.add_to_private_hints(BuiltinConcepts.EVAL_BODY_REQUESTED)
res = core.builtin_helpers.evaluate_from_source(context, "one", eval_body=False)
evaluated = [r for r in res if r.status][0].body
assert evaluated.body is NotInit
# @pytest.mark.parametrize("return_values", [
# None,
# []
+12 -12
View File
@@ -439,27 +439,27 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
def test_i_can_get_error_for_simple_objects(self, obj, expected):
sheerka, context = self.init_test().unpack()
assert sheerka.get_errors(obj) == expected
assert sheerka.get_errors(context, obj) == expected
def test_i_can_get_error_when_builtin_concept_in_error(self):
sheerka, context = self.init_test().unpack()
obj = sheerka.new(BuiltinConcepts.ONTOLOGY_ALREADY_DEFINED)
assert sheerka.get_errors(obj) == [obj]
assert sheerka.get_errors(context, obj) == [obj]
def test_i_can_get_error_when_return_value(self):
sheerka, context = self.init_test().unpack()
error = sheerka.err("an error")
ret_val = ReturnValueConcept("Test", False, sheerka.err("an error"))
assert sheerka.get_errors(ret_val) == [error]
assert sheerka.get_errors(context, ret_val) == [error]
def test_i_can_get_inner_error(self):
sheerka, context = self.init_test().unpack()
error = sheerka.err("an error")
ret_val = ReturnValueConcept("Test", False, sheerka.err("an error"))
assert sheerka.get_errors(ret_val) == [error]
assert sheerka.get_errors(context, ret_val) == [error]
def test_i_can_get_error_when_embedded_errors(self):
sheerka, context = self.init_test().unpack()
@@ -470,7 +470,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
error = sheerka.err([concept_eval_error, unknown_concept, not_an_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(ret_val)
errors_found = sheerka.get_errors(context, ret_val)
assert errors_found == [error, concept_eval_error, unknown_concept]
@@ -488,7 +488,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
multiple_error = sheerka.new(BuiltinConcepts.MULTIPLE_ERRORS, body=[python_error, value_not_found])
ret_val_2 = ReturnValueConcept("Test", False, multiple_error)
errors_found = sheerka.get_errors([ret_val_1, ret_val_2])
errors_found = sheerka.get_errors(context, [ret_val_1, ret_val_2])
assert errors_found == [error, concept_eval_error, unknown_concept,
multiple_error, python_error, value_not_found]
@@ -502,7 +502,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(ret_val, __type=BuiltinConcepts.CONCEPT_EVAL_ERROR)
errors_found = sheerka.get_errors(context, ret_val, __type=BuiltinConcepts.CONCEPT_EVAL_ERROR)
assert errors_found == [concept_eval_error]
def test_i_can_filter_error_by_class_name(self):
@@ -514,7 +514,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(ret_val, __type="PythonErrorNode")
errors_found = sheerka.get_errors(context, ret_val, __type="PythonErrorNode")
assert errors_found == [python_error]
def test_i_can_filter_error_by_concept_attribute(self):
@@ -526,7 +526,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(ret_val, concept_ref="a_concept_ref")
errors_found = sheerka.get_errors(context, ret_val, concept_ref="a_concept_ref")
assert errors_found == [unknown_concept]
def test_i_can_filter_error_by_class_attribute(self):
@@ -538,7 +538,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
error = sheerka.err([concept_eval_error, unknown_concept, python_error])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(ret_val, source="error source")
errors_found = sheerka.get_errors(context, ret_val, source="error source")
assert errors_found == [python_error]
def test_i_can_filter_error_on_multiple_criteria(self):
@@ -550,14 +550,14 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
error = sheerka.err([concept_eval_error, unknown_concept, value_not_found])
ret_val = ReturnValueConcept("Test", False, error)
errors_found = sheerka.get_errors(ret_val, __type="ValueNotFound", item="an_item", value="a value")
errors_found = sheerka.get_errors(context, ret_val, __type="ValueNotFound", item="an_item", value="a value")
assert errors_found == [value_not_found]
def test_i_cannot_get_error_when_return_value_s_status_is_true(self):
sheerka, context = self.init_test().unpack()
ret_val = ReturnValueConcept("Test", True, sheerka.err("an error"))
assert sheerka.get_errors(ret_val) == []
assert sheerka.get_errors(context, ret_val) == []
class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
+25
View File
@@ -469,3 +469,28 @@ def test_tokens_are_matching_when_eof_differs():
tokens2 = Tokenizer(expression2, yield_eof=False)
assert core.utils.tokens_are_matching(tokens1, tokens2)
def test_sheerka_hasattr_get_attr():
class A:
def __init__(self, property_value):
self.property_value = property_value
def as_bag(self):
return {"prop": self.property_value}
# test object with bag
a = A("foo")
assert core.utils.sheerka_hasattr(a, "prop")
assert core.utils.sheerka_getattr(a, "prop") == "foo"
assert not core.utils.sheerka_hasattr(a, "property_value")
with pytest.raises(AttributeError):
core.utils.sheerka_getattr(a, "property_value")
# test for concept
concept = Concept("foo").def_var("a", "value").auto_init()
assert core.utils.sheerka_hasattr(concept, "a")
assert core.utils.sheerka_getattr(concept, "a") == "value"
assert not core.utils.sheerka_hasattr(concept, "b")
with pytest.raises(AttributeError):
core.utils.sheerka_getattr(concept, "b")