Added first version of DebugManager. Implemented draft of the rule engine

This commit is contained in:
2020-11-20 13:41:45 +01:00
parent cd066881b4
commit 315f8ea09b
156 changed files with 8388 additions and 2852 deletions
+55
View File
@@ -0,0 +1,55 @@
from out.OutVisitor import OutVisitor
from core.sheerka.services.SheerkaRuleManager import FormatAstNode
class ConsoleVisitor(OutVisitor):
"""
Prints to the console
"""
COLORS = {
"reset": "\u001b[0m",
"black": "\u001b[30m",
"red": "\u001b[31m",
"green": "\u001b[32m",
"yellow": "\u001b[33m",
"blue": "\u001b[34m",
"magenta": "\u001b[35m",
"cyan": "\u001b[36m",
"white": "\u001b[37m",
}
def __init__(self):
self.out = print
def finalize(self):
self.out("")
def visit_FormatAstRawText(self, context, format_ast, bag):
self.out(format_ast.text, end="")
def visit_FormatAstVariable(self, context, format_ast, bag):
if isinstance(format_ast.value, FormatAstNode):
self.visit(context, format_ast.value, bag)
return
self.out(format_ast.value, end="")
def visit_FormatAstVariableNotFound(self, context, format_ast, bag):
self.out(self.COLORS["red"] + format_ast.name + self.COLORS["reset"], end="")
def visit_FormatAstSequence(self, context, format_ast, bag):
for item in format_ast.items:
self.visit(context, item, bag)
def visit_FormatAstList(self, context, format_ast, bag):
first = True
for item in format_ast.items:
if not first:
self.out("") # print new line
self.visit(context, item, bag)
first = False
def visit_FormatAstColor(self, context, format_ast, bag):
self.out(self.COLORS[format_ast.color], end="")
self.visit(context, format_ast.format_ast, bag)
self.out(self.COLORS["reset"], end="")
+140
View File
@@ -0,0 +1,140 @@
from core.sheerka.services.SheerkaRuleManager import FormatAstVariable, FormatAstVariableNotFound, FormatAstSequence, \
FormatAstColor, FormatAstList, FormatAstRawText
from core.utils import evaluate_expression, as_bag
from out.OutVisitor import OutVisitor
fstring = compile('f"{value:{format}}"', "DeveloperVisitor.fstring", mode="eval")
class DeveloperVisitor(OutVisitor):
"""
This visitor is used to resolve all the variables as well as all the lists
Once completed, it will be passed to the ConsoleVisitor for console print
"""
def __init__(self, sheerka_out, already_seen, list_recursion_depth):
self._result = None
self.sheerka_out = sheerka_out
self.already_seen = already_seen
self.list_recursion_depth = list_recursion_depth
def visit_FormatAstRawText(self, context, format_ast, bag):
if context.debug_enabled:
context.debug_entering("DeveloperVisitor", "visit_FormatAstRawText", format_ast=format_ast, bag=bag)
return self.set_result(format_ast)
def visit_FormatAstVariable(self, context, format_ast, bag):
if context.debug_enabled:
context.debug_entering("DeveloperVisitor", "visit_FormatAstVariable", format_ast=format_ast, bag=bag)
try:
value = evaluate_expression(format_ast.name, bag)
sub_bag = {
"__obj": value,
format_ast.name: value
}
try:
index = format_ast.name.rindex(".")
sub_bag[format_ast.name[index + 1:]] = value
except ValueError:
pass
res = self.sheerka_out.create_out_tree_recursive(context, sub_bag, self)
if format_ast.format:
res = eval(fstring, {"value": res, "format": format_ast.format})
return self.set_result(FormatAstVariable(format_ast.name,
format_ast.format,
res,
format_ast.index))
except NameError as error:
context.debug("DeveloperVisitor", "visit_FormatAstList", "evaluate_expression", error, is_error=True)
return self.set_result(FormatAstVariableNotFound(format_ast.name))
def visit_FormatAstSequence(self, context, format_ast, bag):
if context.debug_enabled:
context.debug_entering("DeveloperVisitor", "visit_FormatAstSequence", format_ast=format_ast, bag=bag)
return self.set_result(FormatAstSequence([self.visit(context, item, bag) for item in format_ast.items]))
def visit_FormatAstColor(self, context, format_ast, bag):
if context.debug_enabled:
context.debug_entering("DeveloperVisitor", "visit_FormatAstColor", format_ast=format_ast, bag=bag)
return self.set_result(FormatAstColor(format_ast.color, self.visit(context, format_ast.format_ast, bag)))
def visit_FormatAstList(self, context, format_ast, bag):
if context.debug_enabled:
context.debug_entering("DeveloperVisitor", "visit_FormatAstList", format_ast=format_ast, bag=bag)
try:
value = evaluate_expression(format_ast.variable, bag)
if value is None:
return self.set_result(FormatAstVariable(format_ast.variable, format_ast.format, None))
if hasattr(value, "__iter__"):
items = value
else:
# the variable does not resolve to an iterable, let's look at one of its attribute
items_props = format_ast.items_prop or "body"
items = evaluate_expression(f"self.{items_props}", {"self": value})
if not hasattr(items, "__iter__"):
# Definition error ? No list found
return self.set_result(FormatAstVariable(format_ast.variable, None, value))
recursion_depth, recurse_on = self.get_recurse_info(value, format_ast.recursion_depth, format_ast.recurse_on)
result = [] # TODO change into generator
for i, item in enumerate(items):
bag["__item"] = item
sub_visitor = DeveloperVisitor(self.sheerka_out, set(), self.list_recursion_depth)
result.append(sub_visitor.visit(context, FormatAstVariable("__item", None, item, i), bag))
# recursion management
recursion_depth, recurse_on = self.get_recurse_info(item, recursion_depth, recurse_on)
if recursion_depth > 0:
sub_items = evaluate_expression(recurse_on, as_bag(item))
if sub_items and hasattr(sub_items, "__iter__"):
sub_visitor = DeveloperVisitor(self.sheerka_out, set(), self.list_recursion_depth + 1)
bag[f"__{recurse_on}"] = sub_items
sub_items = sub_visitor.visit(context, FormatAstList(f"__{recurse_on}",
None,
recurse_on,
recursion_depth - 1), bag)
result.append(sub_items)
return self.set_result(FormatAstList(variable=format_ast.variable,
items_prop=format_ast.items_prop,
recurse_on=recurse_on,
recursion_depth=recursion_depth,
items=result))
except NameError as error:
context.debug("DeveloperVisitor", "visit_FormatAstList", "evaluate_expression", error, is_error=True)
var_name = format_ast.variable if error.args[0] == format_ast.variable else \
format_ast.variable + "." + error.args[0]
return self.set_result(FormatAstVariableNotFound(var_name))
def visit_FormatAstFunction(self, context, format_ast, bag):
if context.debug_enabled:
context.debug_entering("DeveloperVisitor", "visit_FormatAstFunction", format_ast=format_ast, bag=bag)
unknown = FormatAstColor("red", FormatAstRawText(f"function '{format_ast.name}' is unknown"))
return self.set_result(unknown)
def set_result(self, result):
self._result = result
return result
def get_result(self):
return self._result
@staticmethod
def get_recurse_info(obj, recursion_depth, recurse_on):
depth, on = 0, None
if hasattr(obj, "get_format_instr"):
depth = obj.get_format_instr("recursion_depth")
on = obj.get_format_instr("recurse_on")
depth = depth or recursion_depth
on = on or recurse_on
return depth or 0, on
+10
View File
@@ -0,0 +1,10 @@
class OutVisitor:
def visit(self, context, format_ast, bag):
name = format_ast.__class__.__name__
method = 'visit_' + name
visit_method = getattr(self, method, self.generic_visit)
return visit_method(context, format_ast, bag)
def generic_visit(self, context, format_ast, bag):
pass
View File