Added first version of DebugManager. Implemented draft of the rule engine
This commit is contained in:
@@ -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="")
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user