Working on #50 : Adding unit tests

This commit is contained in:
2021-03-12 14:14:17 +01:00
parent ba9ba5bcb3
commit 42bc6abf97
3 changed files with 91 additions and 5 deletions
@@ -17,11 +17,12 @@ from core.tokenizer import Keywords, TokenKind, Token, IterParser
from core.utils import index_tokens, COLORS, get_text_from_tokens
from evaluators.ConceptEvaluator import ConceptEvaluator
from evaluators.PythonEvaluator import PythonEvaluator, Expando
from parsers.BaseExpressionParser import AndNode, ExpressionVisitor, VariableNode, ComparisonNode
from parsers.BaseNodeParser import SourceCodeWithConceptNode, ConceptNode, SourceCodeNode
from parsers.LogicalOperatorParser import LogicalOperatorParser
from parsers.PythonParser import PythonNode
from parsers.BaseExpressionParser import AndNode
from sheerkarete.conditions import AndConditions
from sheerkarete.common import V
from sheerkarete.conditions import AndConditions, Condition
CONCEPTS_ONLY_PARSERS = ["ExactConcept", "Bnf", "Sya", "Sequence"]
@@ -1118,3 +1119,51 @@ class SheerkaRuleManager(BaseService):
return return_value.body.body.concept
return None
class ReteConditionExprVisitor(ExpressionVisitor):
def __init__(self, context):
self.context = context
self.var_counter = 0
self.variables = {}
self.res = []
def add_variable(self, target):
var_name = f"__x_{self.var_counter:02}__"
self.var_counter += 1
self.variables[target] = var_name
return var_name
def init_variable_if_needed(self, node):
if node.name not in self.variables:
var_name = self.add_variable(node.name)
self.res.append(Condition(V(var_name), "__name__", node.name))
return V(self.variables[node.name])
def get_conditions(self, expr_node):
self.res.clear()
self.var_counter = 0
self.variables.clear()
self.visit(expr_node)
return AndConditions(self.res)
def visit_VariableNode(self, expr_node):
var_name = self.init_variable_if_needed(expr_node)
if expr_node.attributes_str is not None:
self.res.append(Condition(var_name, expr_node.attributes_str, True))
def visit_AndNode(self, expr_node: AndNode):
for node in expr_node.parts:
self.visit(node)
def visit_ComparisonNode(self, expr_node: ComparisonNode):
if isinstance(expr_node.left, VariableNode):
left = self.init_variable_if_needed(expr_node.left)
attr = expr_node.left.attributes_str or "__self__"
right = eval(get_text_from_tokens(expr_node.right.tokens))
self.res.append(Condition(left, attr, right))
else:
raise FailedToCompileError(expr_node)
+38 -2
View File
@@ -7,20 +7,23 @@ from core.concept import Concept, DEFINITION_TYPE_DEF, DoNotResolve
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.SheerkaExecute import ParserInput
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleActionParser, \
FormatAstRawText, FormatAstVariable, FormatAstSequence, FormatAstFunction, \
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, RuleCompiledPredicate, FormatAstDict, \
FormatAstMulti, \
PythonCodeEmitter, NoConditionFound, FormatAstNode
PythonCodeEmitter, NoConditionFound, FormatAstNode, ReteConditionExprVisitor
from core.sheerka.services.sheerka_service import FailedToCompileError
from core.tokenizer import Token, TokenKind
from parsers.BaseNodeParser import SourceCodeWithConceptNode, SourceCodeNode
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
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import CMV, CC, compare_with_test_object, get_test_obj
from tests.parsers.parsers_utils import CMV, CC, compare_with_test_object, get_test_obj, get_rete_conditions
seq = FormatAstSequence
raw = FormatAstRawText
@@ -1007,6 +1010,39 @@ 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", [
(
"__ret",
["#__x_00__|__name__|'__ret'"],
),
(
"__ret.status == True",
["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
),
(
"__ret.status",
["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
),
(
"__ret and __ret.status",
["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
),
])
def test_i_can_get_rete_conditions(self, expression, expected_as_str):
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
class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
def test_rules_are_initialized_at_startup(self):
+2 -1
View File
@@ -54,7 +54,8 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
("func(var.attr)", FN("func(", ")", [VAR("var.attr")])),
("func(var1.attr1 and var2.attr2)", FN("func(", ")", [AND(VAR("var1.attr1"), VAR("var2.attr2"))])),
("func(var1.attr1 > var2.attr2)", FN("func(", ")", [GT(VAR("var1.attr1"), VAR("var2.attr2"))])),
("func1(var1) and func2(var2)", AND(FN("func1(", ")", [VAR("var1")]), FN("func2(", (")", 1), [VAR("var2")])))
("func1(var1) and func2(var2)", AND(FN("func1(", ")", [VAR("var1")]), FN("func2(", (")", 1), [VAR("var2")]))),
("__ret", VAR("__ret")),
])
def test_i_can_parse_input(self, expression, expected):
sheerka, context, parser, parser_input, error_sink = self.init_parser_with_source(expression)