Fixed #51 : Added unit tests

This commit is contained in:
2021-03-19 10:38:38 +01:00
parent 6a8011ec12
commit 36e3ce0bcb
4 changed files with 145 additions and 6 deletions
+2 -1
View File
@@ -31,7 +31,8 @@ class Rule:
rule_id=None,
is_enabled=None):
self.metadata = RuleMetadata(action_type, name, predicate, action, id=rule_id, is_enabled=is_enabled)
self.compiled_predicates = None
self.compiled_predicates = None # old version (to remove when possible)
self.compiled_conditions = None # new version
self.compiled_action = None
from core.sheerka.services.SheerkaComparisonManager import SheerkaComparisonManager
self.priority = priority if priority is not None else SheerkaComparisonManager.DEFAULT_COMPARISON_VALUE
@@ -85,7 +85,7 @@ class SheerkaEvaluateRules(BaseService):
results.setdefault(LOW_PRIORITY_RULES, []).append(rule)
continue
res = self.evaluate_rule(sub_context, rule, bag)
res = self.evaluate_rule_old(sub_context, rule, bag)
ok = res.status and self.sheerka.is_success(self.sheerka.objvalue(res))
results.setdefault(ok, []).append(rule)
if ok and success_priority is None:
@@ -96,9 +96,9 @@ class SheerkaEvaluateRules(BaseService):
sub_context.add_values(rules_result=results)
return results
def evaluate_rule(self, context, rule, bag):
def evaluate_rule_old(self, context, rule, bag):
"""
Evaluate all the predicate
Evaluate the conditions
:param context:
:param rule:
:param bag:
@@ -132,6 +132,47 @@ class SheerkaEvaluateRules(BaseService):
return expect_one(context, results)
def evaluate_rule(self, context, rule, bag):
"""
Evaluate the conditions
:param context:
:param rule:
:param bag:
:return:
"""
bag_variables = set(bag.keys())
results = []
for compiled_condition in rule.compiled_conditions:
if compiled_condition.variables.intersection(bag_variables) != compiled_condition.variables:
continue
if compiled_condition.return_value is None:
# We only want to test the existence of a data
results.append(context.sheerka.ret(self.NAME, True, True))
else:
# do not forget to reset the 'is_evaluated' in the case of a concept
if compiled_condition.evaluator_type == ConceptEvaluator.NAME:
compiled_condition.concept.get_metadata().is_evaluated = False
evaluator = self.evaluators_by_name[compiled_condition.evaluator]
res = evaluator.eval(context, compiled_condition.return_value)
if res.status and isinstance(res.body, bool) and res.body:
# one successful value found. No need to look any further
results = [res]
break
else:
results.append(res)
debugger = context.get_debugger(SheerkaEvaluateRules.NAME, "evaluate_rule", new_debug_id=False)
debugger.debug_rule(rule, results)
return expect_one(context, results)
def remove_from_rete_memory(self, lst):
if lst is None:
return
@@ -628,6 +628,18 @@ class RuleCompiledPredicate:
variables: Set[str] = None # TODO: set of required variables
@dataclass()
class CompiledCondition:
"""
The 'when' expression is parsed to have a ReturnValueConcept or a Concept that can then be evaluated
Depending on the evaluator, the 'predicate' attribute or the 'concept' attribute will be used
"""
evaluator_type: Union[str, None] # PythonEvaluator.NAME | ConceptEvaluator.NAME
return_value: Union[ReturnValueConcept, None] # compiled source as ReturnValue
variables: Set[str]
concept: Union[Concept, None] = None # compiled source as concept
@dataclass
class CompiledWhenResult:
"""
@@ -1298,4 +1310,18 @@ class ReteConditionExprVisitor(ExpressionVisitor):
class PythonConditionExprVisitor(ExpressionVisitor):
pass
def __init__(self, context):
self.context = context
self.var_counter = 0
self.variables = set()
def get_conditions(self, expr_node):
self.var_counter = 0
self.variables.clear()
condition = self.visit(expr_node)
return [condition]
def visit_VariableNode(self, expr_node: VariableNode):
# no evaluator to call, simply check that the variable is in the bag
return CompiledCondition(None, None, {expr_node.name})