Fixed error when desc() returns multiple results

This commit is contained in:
2020-12-04 17:37:06 +01:00
parent 8b86998225
commit d364878ddb
16 changed files with 408 additions and 19 deletions
+8
View File
@@ -106,6 +106,7 @@ class BuiltinConcepts:
# formatting
TO_LIST = "__TO_LIST"
TO_DICT = "__TO_DICT"
TO_MULTI = "__TO_MULTI" # used when there are multiple output to display
AllBuiltinConcepts = [v for n, v in BuiltinConcepts.__dict__.items() if not n.startswith("__")]
@@ -178,6 +179,13 @@ BuiltinContainers = [
BuiltinConcepts.EXPLANATION,
BuiltinConcepts.TO_LIST,
BuiltinConcepts.TO_DICT,
BuiltinConcepts.TO_MULTI,
]
BuiltinOutConcepts = [
BuiltinConcepts.TO_LIST,
BuiltinConcepts.TO_DICT,
BuiltinConcepts.TO_MULTI,
]
"""
+13
View File
@@ -916,6 +916,19 @@ class Sheerka(Concept):
return a.key == b_key
@staticmethod
def isin(a, b):
"""
True if the concept is the list
:param a:
:param b:
:return:
"""
if not isinstance(a, Concept):
return False
return a.key in b
@staticmethod
def get_unknown(metadata):
"""
@@ -8,6 +8,7 @@ from core.sheerka.ExecutionContext import ExecutionContext
from core.sheerka.services.sheerka_service import BaseService
from core.utils import CONSOLE_COLORS_MAP as CCM, CONSOLE_COLUMNS, PRIMITIVES_TYPES
from core.utils import evaluate_expression, as_bag
from parsers.BaseNodeParser import SourceCodeWithConceptNode, UnrecognizedTokensNode
pp = pprint.PrettyPrinter(indent=2, width=CONSOLE_COLUMNS)
@@ -15,7 +16,7 @@ NotFound = "** Not Found **"
class ConceptDebugObj:
def __init__(self, concept):
def __init__(self, concept, **kwargs):
self.concept = concept
self.attrs = concept.as_debug_bag(lambda x: ConceptDebugObj(x), True)
@@ -46,12 +47,37 @@ class ConceptDebugObj:
class ConceptNodeDebugObj:
def __init__(self, concept_node):
def __init__(self, concept_node, **kwargs):
self.concept_node = concept_node
self.concept_debug = ConceptDebugObj(concept_node.concept)
def __repr__(self):
return f"ConceptNode({self.concept_debug.concept_repr()})"
return f"ConceptNodeDbg({self.concept_debug.concept_repr()})"
class SourceCodeWithConceptNodeDebugObj:
def __init__(self, source_code_node, **kwargs):
self.source_code_node = source_code_node
def __repr__(self):
debug_repr = SheerkaDebugManager.get_debug_repr
res = f"SourceCodeNodeDbg('{debug_repr(self.source_code_node.first, inside_source_code=True)}' "
first = True
for node in self.source_code_node.nodes:
res += (", " if not first else "") + str(debug_repr(node))
first = False
return res + f" '{debug_repr(self.source_code_node.last, inside_source_code=True)}')"
class UnrecognizedTokensNodeDebugOjb:
def __init__(self, unrec_node, **kwargs):
self.unrec_node = unrec_node
self.inside_source_code = kwargs.get("inside_source_code", False)
def __repr__(self):
if self.inside_source_code:
return self.unrec_node.source
return f"UnrecNodeDbg('{self.unrec_node.source}')"
class BaseDebugLogger:
@@ -678,16 +704,21 @@ class SheerkaDebugManager(BaseService):
return self.get_inner_values(obj.body, **kwargs)
def get_debug_repr(self, obj, **kwargs):
@staticmethod
def get_debug_repr(obj, **kwargs):
if kwargs.get("as_bag", False):
forced_props = self.get_concept_forced_props(obj) if isinstance(obj, Concept) else None
return self.as_debug_bag(obj, True, forced_props)
forced_props = SheerkaDebugManager.get_concept_forced_props(obj) if isinstance(obj, Concept) else None
return SheerkaDebugManager.as_debug_bag(obj, True, forced_props)
from parsers.BaseNodeParser import ConceptNode
if isinstance(obj, Concept):
return ConceptDebugObj(obj)
return ConceptDebugObj(obj, **kwargs)
elif isinstance(obj, ConceptNode):
return ConceptNodeDebugObj(obj)
return ConceptNodeDebugObj(obj, **kwargs)
elif isinstance(obj, SourceCodeWithConceptNode):
return SourceCodeWithConceptNodeDebugObj(obj, **kwargs)
elif isinstance(obj, UnrecognizedTokensNode):
return UnrecognizedTokensNodeDebugOjb(obj, **kwargs)
else:
return obj
+1 -1
View File
@@ -16,7 +16,7 @@ class SheerkaOut(BaseService):
self.sheerka.bind_service_method(self.process_return_values, False)
def create_out_tree(self, context, obj):
debugger = context.get_debugger("Out.visitor", "create_out_tree")
debugger = context.get_debugger("Visitor", "create_out_tree")
return self.create_out_tree_recursive(context, {'__obj': obj}, DeveloperVisitor(self, debugger, set(), 0))
def create_out_tree_recursive(self, context, bag, visitor):
@@ -119,7 +119,9 @@ class FormatAstList(FormatAstNode):
def clone(self, **kwargs):
return super().clone(
FormatAstList(self.variable),
("items_prop", "recurse_on", "recursion_depth", "debug", "prefix", "suffix", "show_index", "index", "items"),
(
"items_prop", "recurse_on", "recursion_depth", "debug", "prefix", "suffix", "show_index", "index",
"items"),
**kwargs)
@@ -177,6 +179,25 @@ class FormatAstSequence(FormatAstNode):
**kwargs)
@dataclass
class FormatAstMulti(FormatAstNode):
"""
Used when there are multiple out to print, but they are not related
Just print them one by one
"""
variable: str
items: list = None
def __repr__(self):
return f"FormatAstMulti({self.variable}, items={self.items})"
def clone(self, **kwargs):
return super().clone(
FormatAstMulti(self.variable),
("items",),
**kwargs)
class FormatRuleParser(IterParser):
@staticmethod
@@ -318,6 +339,8 @@ class FormatRuleParser(IterParser):
return self.return_list(args, kwargs)
elif func_name.value == "dict":
return self.return_dict(args, kwargs)
elif func_name.value == "multi":
return self.return_multi(args, kwargs)
return FormatAstFunction(func_name.value, self.to_text(args), self.to_text(kwargs))
@@ -461,6 +484,17 @@ class FormatRuleParser(IterParser):
return FormatAstDict(variable_name, **kwargs_parameters)
def return_multi(self, args, kwargs):
if len(kwargs) > 0:
self.error_sink = FormatRuleSyntaxError("keyword arguments are not supported", None)
return None
if len(args) > 1:
self.error_sink = FormatRuleSyntaxError("too many positional arguments", args[1][0])
return None
return FormatAstMulti(get_text_from_tokens(args[0]))
@dataclass()
class RulePredicate:
@@ -620,25 +654,43 @@ class SheerkaRuleManager(BaseService):
def init_builtin_rules(self, context):
# self.sheerka.init_log.debug("Initializing default rules")
rules = [
# [0] Rule #1 Rule #2 in debug
Rule("print", "Print return values", "__rets", "list(__rets)"),
# [1] Rule #2 in debug
Rule("print", "Print ReturnValue",
"__ret",
"\\ReturnValue(who={__ret.who}, status={__ret.status}, value={__ret.value})"),
# [2] Rule #3 in debug
Rule("print", "Failed ReturnValue in red",
"__ret and not __ret.status",
"red(__ret)"),
# [3] Rule #4 in debug
Rule("print", "List explanations",
"isinstance(__ret_container, BuiltinConcepts.EXPLANATION)",
"blue(__ret_container.digest) : {__ret_container.command}\nlist(__ret_container)"),
# [4] Rule #5 in debug
Rule("print", "Print ExecutionContext",
"isinstance(__obj, ExecutionContext)",
"[{id:3}] {__tab}{desc} ({status})"),
# [6] Rule #7 in debug
Rule("print", "Display formatted list",
"isinstance(__ret_container, BuiltinConcepts.TO_LIST)",
"list(__ret_container)"),
# [7] Rule #8 in debug
Rule("print", "Display formatted dict",
"isinstance(__ret_container, BuiltinConcepts.TO_DICT)",
"dict(__ret_container)"),
# [8] Rule #9 in debug
Rule("print", "Display multiple outputs",
"isinstance(__ret_container, BuiltinConcepts.TO_MULTI)",
"multi(__ret_container)"),
]
for r in rules:
@@ -648,6 +700,10 @@ class SheerkaRuleManager(BaseService):
self.sheerka.set_is_less_than(context, BuiltinConcepts.PRECEDENCE, rules[1], rules[3], RULE_COMPARISON_CONTEXT)
self.sheerka.set_is_less_than(context, BuiltinConcepts.PRECEDENCE, rules[1], rules[5], RULE_COMPARISON_CONTEXT)
self.sheerka.set_is_less_than(context, BuiltinConcepts.PRECEDENCE, rules[1], rules[6], RULE_COMPARISON_CONTEXT)
self.sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, rules[7], rules[6],
RULE_COMPARISON_CONTEXT)
self.sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, rules[7], rules[5],
RULE_COMPARISON_CONTEXT)
self.sheerka.set_is_greatest(context, BuiltinConcepts.PRECEDENCE, rules[0], RULE_COMPARISON_CONTEXT)
def get_rule_by_id(self, rule_id):
+44
View File
@@ -0,0 +1,44 @@
from core.builtin_concepts import BuiltinConcepts, BuiltinOutConcepts
from evaluators.BaseEvaluator import AllReturnValuesEvaluator
from parsers.BaseParser import BaseParser
class MultipleOutEvaluator(AllReturnValuesEvaluator):
"""
Used to filter the responses
when too many success but these success are different output to print
"""
NAME = "MultipleOut"
def __init__(self):
super().__init__(self.NAME, [BuiltinConcepts.AFTER_EVALUATION], 61)
self.success = []
def reset(self):
super().reset()
self.success.clear()
def matches(self, context, return_values):
to_process = False
for ret in return_values:
if ret.status and ret.who.startswith(BaseParser.PREFIX):
return False
elif ret.status and context.sheerka.isinstance(ret.body, BuiltinConcepts.REDUCE_REQUESTED):
to_process = True
self.eaten.append(ret)
elif ret.status and ret.who.startswith(self.PREFIX):
if context.sheerka.isin(ret.body, BuiltinOutConcepts):
self.success.append(ret)
self.eaten.append(ret)
else:
return False
elif not ret.status:
self.eaten.append(ret)
return to_process and len(self.success) > 1
def eval(self, context, return_values):
to_multi = context.sheerka.new(BuiltinConcepts.TO_MULTI, body=[r.body for r in self.success])
return context.sheerka.ret(self.name, True, to_multi, parents=self.eaten)
+3
View File
@@ -100,6 +100,9 @@ class AsStrVisitor(OutVisitor):
result += format_ast.suffix
return result
def visit_FormatAstMulti(self, format_ast):
return "\n".join(self.visit(item) for item in format_ast.items)
@staticmethod
def debug_activated(node):
return isinstance(node, FormatAstNode) and hasattr(node, "debug") and node.debug
+3
View File
@@ -51,3 +51,6 @@ class ConsoleVisitor(AsStrVisitor):
visitor = AsStrVisitor(expand, width=self.console_width)
res = visitor.visit_FormatAstDict(format_ast)
self.out(res)
def visit_FormatAstMulti(self, format_ast):
self.out(super().visit_FormatAstMulti(format_ast))
+24
View File
@@ -26,6 +26,8 @@ class DeveloperVisitor:
return visit_method(context, format_ast, bag)
def generic_visit(self, context, format_ast, bag):
name = format_ast.__class__.__name__
self.debugger.debug_log(f"method '{name}' is not implemented", is_error=True)
pass
def visit_FormatAstRawText(self, context, format_ast, bag):
@@ -191,6 +193,28 @@ class DeveloperVisitor:
format_ast.variable + "." + error.args[0]
return FormatAstVariableNotFound(var_name)
def visit_FormatAstMulti(self, context, format_ast, bag):
if self.debugger.is_enabled():
debug_bag = {"format_ast": format_ast, "bag": bag}
self.debugger.debug_log(f"Entering visit_FormatAstMulti with {debug_bag}")
try:
value = evaluate_expression(format_ast.variable, bag)
res = []
for item in value.body:
sub_bag = {"__obj": item, format_ast.variable: item}
visitor = DeveloperVisitor(self.sheerka_out, self.debugger, set(), self.list_recursion_depth)
res.append(self.sheerka_out.create_out_tree_recursive(context, sub_bag, visitor))
format_ast.items = res
return format_ast
except NameError as error:
self.debugger.debug_log(error, is_error=True)
var_name = format_ast.variable if error.args[0] == format_ast.variable else \
format_ast.variable + "." + error.args[0]
return FormatAstVariableNotFound(var_name)
@staticmethod
def get_recurse_info(obj, recursion_depth, recurse_on):
depth, on = 0, None