Fixed error when desc() returns multiple results
This commit is contained in:
@@ -25,3 +25,14 @@ def concept x has a y as hasa(x,y) pre is_question()
|
|||||||
# no need to auto eval as it's a question
|
# no need to auto eval as it's a question
|
||||||
def concept x has an y as hasa(x,y) pre is_question()
|
def concept x has an y as hasa(x,y) pre is_question()
|
||||||
# no need to auto eval as it's a question
|
# no need to auto eval as it's a question
|
||||||
|
|
||||||
|
# default
|
||||||
|
def concept male
|
||||||
|
def concept female
|
||||||
|
def concept man
|
||||||
|
man is a male
|
||||||
|
def concept woman
|
||||||
|
woman is a female
|
||||||
|
def concept human
|
||||||
|
man is a human
|
||||||
|
woman is a human
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ class BuiltinConcepts:
|
|||||||
# formatting
|
# formatting
|
||||||
TO_LIST = "__TO_LIST"
|
TO_LIST = "__TO_LIST"
|
||||||
TO_DICT = "__TO_DICT"
|
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("__")]
|
AllBuiltinConcepts = [v for n, v in BuiltinConcepts.__dict__.items() if not n.startswith("__")]
|
||||||
@@ -178,6 +179,13 @@ BuiltinContainers = [
|
|||||||
BuiltinConcepts.EXPLANATION,
|
BuiltinConcepts.EXPLANATION,
|
||||||
BuiltinConcepts.TO_LIST,
|
BuiltinConcepts.TO_LIST,
|
||||||
BuiltinConcepts.TO_DICT,
|
BuiltinConcepts.TO_DICT,
|
||||||
|
BuiltinConcepts.TO_MULTI,
|
||||||
|
]
|
||||||
|
|
||||||
|
BuiltinOutConcepts = [
|
||||||
|
BuiltinConcepts.TO_LIST,
|
||||||
|
BuiltinConcepts.TO_DICT,
|
||||||
|
BuiltinConcepts.TO_MULTI,
|
||||||
]
|
]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -916,6 +916,19 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
return a.key == b_key
|
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
|
@staticmethod
|
||||||
def get_unknown(metadata):
|
def get_unknown(metadata):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from core.sheerka.ExecutionContext import ExecutionContext
|
|||||||
from core.sheerka.services.sheerka_service import BaseService
|
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 CONSOLE_COLORS_MAP as CCM, CONSOLE_COLUMNS, PRIMITIVES_TYPES
|
||||||
from core.utils import evaluate_expression, as_bag
|
from core.utils import evaluate_expression, as_bag
|
||||||
|
from parsers.BaseNodeParser import SourceCodeWithConceptNode, UnrecognizedTokensNode
|
||||||
|
|
||||||
pp = pprint.PrettyPrinter(indent=2, width=CONSOLE_COLUMNS)
|
pp = pprint.PrettyPrinter(indent=2, width=CONSOLE_COLUMNS)
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ NotFound = "** Not Found **"
|
|||||||
|
|
||||||
|
|
||||||
class ConceptDebugObj:
|
class ConceptDebugObj:
|
||||||
def __init__(self, concept):
|
def __init__(self, concept, **kwargs):
|
||||||
self.concept = concept
|
self.concept = concept
|
||||||
self.attrs = concept.as_debug_bag(lambda x: ConceptDebugObj(x), True)
|
self.attrs = concept.as_debug_bag(lambda x: ConceptDebugObj(x), True)
|
||||||
|
|
||||||
@@ -46,12 +47,37 @@ class ConceptDebugObj:
|
|||||||
|
|
||||||
|
|
||||||
class ConceptNodeDebugObj:
|
class ConceptNodeDebugObj:
|
||||||
def __init__(self, concept_node):
|
def __init__(self, concept_node, **kwargs):
|
||||||
self.concept_node = concept_node
|
self.concept_node = concept_node
|
||||||
self.concept_debug = ConceptDebugObj(concept_node.concept)
|
self.concept_debug = ConceptDebugObj(concept_node.concept)
|
||||||
|
|
||||||
def __repr__(self):
|
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:
|
class BaseDebugLogger:
|
||||||
@@ -678,16 +704,21 @@ class SheerkaDebugManager(BaseService):
|
|||||||
|
|
||||||
return self.get_inner_values(obj.body, **kwargs)
|
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):
|
if kwargs.get("as_bag", False):
|
||||||
forced_props = self.get_concept_forced_props(obj) if isinstance(obj, Concept) else None
|
forced_props = SheerkaDebugManager.get_concept_forced_props(obj) if isinstance(obj, Concept) else None
|
||||||
return self.as_debug_bag(obj, True, forced_props)
|
return SheerkaDebugManager.as_debug_bag(obj, True, forced_props)
|
||||||
|
|
||||||
from parsers.BaseNodeParser import ConceptNode
|
from parsers.BaseNodeParser import ConceptNode
|
||||||
if isinstance(obj, Concept):
|
if isinstance(obj, Concept):
|
||||||
return ConceptDebugObj(obj)
|
return ConceptDebugObj(obj, **kwargs)
|
||||||
elif isinstance(obj, ConceptNode):
|
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:
|
else:
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class SheerkaOut(BaseService):
|
|||||||
self.sheerka.bind_service_method(self.process_return_values, False)
|
self.sheerka.bind_service_method(self.process_return_values, False)
|
||||||
|
|
||||||
def create_out_tree(self, context, obj):
|
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))
|
return self.create_out_tree_recursive(context, {'__obj': obj}, DeveloperVisitor(self, debugger, set(), 0))
|
||||||
|
|
||||||
def create_out_tree_recursive(self, context, bag, visitor):
|
def create_out_tree_recursive(self, context, bag, visitor):
|
||||||
|
|||||||
@@ -119,7 +119,9 @@ class FormatAstList(FormatAstNode):
|
|||||||
def clone(self, **kwargs):
|
def clone(self, **kwargs):
|
||||||
return super().clone(
|
return super().clone(
|
||||||
FormatAstList(self.variable),
|
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)
|
**kwargs)
|
||||||
|
|
||||||
|
|
||||||
@@ -177,6 +179,25 @@ class FormatAstSequence(FormatAstNode):
|
|||||||
**kwargs)
|
**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):
|
class FormatRuleParser(IterParser):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -318,6 +339,8 @@ class FormatRuleParser(IterParser):
|
|||||||
return self.return_list(args, kwargs)
|
return self.return_list(args, kwargs)
|
||||||
elif func_name.value == "dict":
|
elif func_name.value == "dict":
|
||||||
return self.return_dict(args, kwargs)
|
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))
|
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)
|
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()
|
@dataclass()
|
||||||
class RulePredicate:
|
class RulePredicate:
|
||||||
@@ -620,25 +654,43 @@ class SheerkaRuleManager(BaseService):
|
|||||||
def init_builtin_rules(self, context):
|
def init_builtin_rules(self, context):
|
||||||
# self.sheerka.init_log.debug("Initializing default rules")
|
# self.sheerka.init_log.debug("Initializing default rules")
|
||||||
rules = [
|
rules = [
|
||||||
|
# [0] Rule #1 Rule #2 in debug
|
||||||
Rule("print", "Print return values", "__rets", "list(__rets)"),
|
Rule("print", "Print return values", "__rets", "list(__rets)"),
|
||||||
|
|
||||||
|
# [1] Rule #2 in debug
|
||||||
Rule("print", "Print ReturnValue",
|
Rule("print", "Print ReturnValue",
|
||||||
"__ret",
|
"__ret",
|
||||||
"\\ReturnValue(who={__ret.who}, status={__ret.status}, value={__ret.value})"),
|
"\\ReturnValue(who={__ret.who}, status={__ret.status}, value={__ret.value})"),
|
||||||
|
|
||||||
|
# [2] Rule #3 in debug
|
||||||
Rule("print", "Failed ReturnValue in red",
|
Rule("print", "Failed ReturnValue in red",
|
||||||
"__ret and not __ret.status",
|
"__ret and not __ret.status",
|
||||||
"red(__ret)"),
|
"red(__ret)"),
|
||||||
|
|
||||||
|
# [3] Rule #4 in debug
|
||||||
Rule("print", "List explanations",
|
Rule("print", "List explanations",
|
||||||
"isinstance(__ret_container, BuiltinConcepts.EXPLANATION)",
|
"isinstance(__ret_container, BuiltinConcepts.EXPLANATION)",
|
||||||
"blue(__ret_container.digest) : {__ret_container.command}\nlist(__ret_container)"),
|
"blue(__ret_container.digest) : {__ret_container.command}\nlist(__ret_container)"),
|
||||||
|
|
||||||
|
# [4] Rule #5 in debug
|
||||||
Rule("print", "Print ExecutionContext",
|
Rule("print", "Print ExecutionContext",
|
||||||
"isinstance(__obj, ExecutionContext)",
|
"isinstance(__obj, ExecutionContext)",
|
||||||
"[{id:3}] {__tab}{desc} ({status})"),
|
"[{id:3}] {__tab}{desc} ({status})"),
|
||||||
|
|
||||||
|
# [6] Rule #7 in debug
|
||||||
Rule("print", "Display formatted list",
|
Rule("print", "Display formatted list",
|
||||||
"isinstance(__ret_container, BuiltinConcepts.TO_LIST)",
|
"isinstance(__ret_container, BuiltinConcepts.TO_LIST)",
|
||||||
"list(__ret_container)"),
|
"list(__ret_container)"),
|
||||||
|
|
||||||
|
# [7] Rule #8 in debug
|
||||||
Rule("print", "Display formatted dict",
|
Rule("print", "Display formatted dict",
|
||||||
"isinstance(__ret_container, BuiltinConcepts.TO_DICT)",
|
"isinstance(__ret_container, BuiltinConcepts.TO_DICT)",
|
||||||
"dict(__ret_container)"),
|
"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:
|
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[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[5], RULE_COMPARISON_CONTEXT)
|
||||||
self.sheerka.set_is_less_than(context, BuiltinConcepts.PRECEDENCE, rules[1], rules[6], 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)
|
self.sheerka.set_is_greatest(context, BuiltinConcepts.PRECEDENCE, rules[0], RULE_COMPARISON_CONTEXT)
|
||||||
|
|
||||||
def get_rule_by_id(self, rule_id):
|
def get_rule_by_id(self, rule_id):
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -100,6 +100,9 @@ class AsStrVisitor(OutVisitor):
|
|||||||
result += format_ast.suffix
|
result += format_ast.suffix
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def visit_FormatAstMulti(self, format_ast):
|
||||||
|
return "\n".join(self.visit(item) for item in format_ast.items)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def debug_activated(node):
|
def debug_activated(node):
|
||||||
return isinstance(node, FormatAstNode) and hasattr(node, "debug") and node.debug
|
return isinstance(node, FormatAstNode) and hasattr(node, "debug") and node.debug
|
||||||
|
|||||||
@@ -51,3 +51,6 @@ class ConsoleVisitor(AsStrVisitor):
|
|||||||
visitor = AsStrVisitor(expand, width=self.console_width)
|
visitor = AsStrVisitor(expand, width=self.console_width)
|
||||||
res = visitor.visit_FormatAstDict(format_ast)
|
res = visitor.visit_FormatAstDict(format_ast)
|
||||||
self.out(res)
|
self.out(res)
|
||||||
|
|
||||||
|
def visit_FormatAstMulti(self, format_ast):
|
||||||
|
self.out(super().visit_FormatAstMulti(format_ast))
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class DeveloperVisitor:
|
|||||||
return visit_method(context, format_ast, bag)
|
return visit_method(context, format_ast, bag)
|
||||||
|
|
||||||
def generic_visit(self, 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
|
pass
|
||||||
|
|
||||||
def visit_FormatAstRawText(self, context, format_ast, bag):
|
def visit_FormatAstRawText(self, context, format_ast, bag):
|
||||||
@@ -191,6 +193,28 @@ class DeveloperVisitor:
|
|||||||
format_ast.variable + "." + error.args[0]
|
format_ast.variable + "." + error.args[0]
|
||||||
return FormatAstVariableNotFound(var_name)
|
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
|
@staticmethod
|
||||||
def get_recurse_info(obj, recursion_depth, recurse_on):
|
def get_recurse_info(obj, recursion_depth, recurse_on):
|
||||||
depth, on = 0, None
|
depth, on = 0, None
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from core.global_symbols import RULE_COMPARISON_CONTEXT
|
|||||||
from core.rule import Rule
|
from core.rule import Rule
|
||||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleParser, \
|
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleParser, \
|
||||||
FormatAstRawText, FormatAstVariable, FormatAstSequence, FormatAstFunction, \
|
FormatAstRawText, FormatAstVariable, FormatAstSequence, FormatAstFunction, \
|
||||||
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, RulePredicate, FormatAstDict
|
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, RulePredicate, FormatAstDict, FormatAstMulti
|
||||||
from core.tokenizer import Token, TokenKind
|
from core.tokenizer import Token, TokenKind
|
||||||
from parsers.BaseNodeParser import SourceCodeWithConceptNode, SourceCodeNode
|
from parsers.BaseNodeParser import SourceCodeWithConceptNode, SourceCodeNode
|
||||||
from parsers.PythonParser import PythonNode
|
from parsers.PythonParser import PythonNode
|
||||||
@@ -114,7 +114,8 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
|||||||
(r"\not_a_function(a={var})", seq([raw("not_a_function(a="), var("var"), raw(")")])),
|
(r"\not_a_function(a={var})", seq([raw("not_a_function(a="), var("var"), raw(")")])),
|
||||||
("dict(var_name)", FormatAstDict("var_name")),
|
("dict(var_name)", FormatAstDict("var_name")),
|
||||||
("dict(var_name, items_prop='props')", FormatAstDict("var_name", items_prop='props')),
|
("dict(var_name, items_prop='props')", FormatAstDict("var_name", items_prop='props')),
|
||||||
("dict(var_name, debug=True)", FormatAstDict("var_name", debug=True, prefix="{", suffix="}"))
|
("dict(var_name, debug=True)", FormatAstDict("var_name", debug=True, prefix="{", suffix="}")),
|
||||||
|
("multi(var_name)", FormatAstMulti("var_name")),
|
||||||
])
|
])
|
||||||
def test_i_can_parse_format_rule(self, text, expected):
|
def test_i_can_parse_format_rule(self, text, expected):
|
||||||
assert FormatRuleParser(text).parse() == expected
|
assert FormatRuleParser(text).parse() == expected
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||||
|
from core.concept import Concept
|
||||||
|
from evaluators.BaseEvaluator import BaseEvaluator
|
||||||
|
from parsers.BaseParser import BaseParser
|
||||||
|
|
||||||
|
reduced_requested = ReturnValueConcept("Sheerka", True, Concept(name=BuiltinConcepts.REDUCE_REQUESTED,
|
||||||
|
key=BuiltinConcepts.REDUCE_REQUESTED))
|
||||||
|
|
||||||
|
|
||||||
|
def ret_val(value="value", who="who", status=True):
|
||||||
|
return ReturnValueConcept(who, status, value)
|
||||||
|
|
||||||
|
|
||||||
|
def p_ret_val(value="value", parser="parser", status=True):
|
||||||
|
return ReturnValueConcept(BaseParser.PREFIX + parser, status, value)
|
||||||
|
|
||||||
|
|
||||||
|
def e_ret_val(value="value", evaluator="evaluator", status=True):
|
||||||
|
return ReturnValueConcept(BaseEvaluator.PREFIX + evaluator, status, value)
|
||||||
|
|
||||||
|
|
||||||
|
def p_ret_val_false(value="value", parser="parser"):
|
||||||
|
return p_ret_val(value, parser, status=False)
|
||||||
|
|
||||||
|
|
||||||
|
def p_ret_val_true(value="value", parser="parser"):
|
||||||
|
return p_ret_val(value, parser, status=True)
|
||||||
|
|
||||||
|
|
||||||
|
def e_ret_val_false(value="value", parser="parser"):
|
||||||
|
return e_ret_val(value, parser, status=False)
|
||||||
|
|
||||||
|
|
||||||
|
def e_ret_val_true(value="value", parser="parser"):
|
||||||
|
return e_ret_val(value, parser, status=True)
|
||||||
|
|
||||||
|
|
||||||
|
def e_ret_val_new(key, evaluator="evaluator", status=True, **kwargs):
|
||||||
|
body = new_concept(key, **kwargs)
|
||||||
|
return e_ret_val(body, evaluator, status)
|
||||||
|
|
||||||
|
|
||||||
|
def new_concept(key, **kwargs):
|
||||||
|
res = Concept(key=key, name=key, is_builtin=False, is_unique=False)
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
to_use = "#" + k + "#" if k in ("body", "pre", "post", "ret") else k
|
||||||
|
res.set_value(to_use, v)
|
||||||
|
|
||||||
|
res.get_metadata().is_evaluated = True
|
||||||
|
return res
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import pytest
|
||||||
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
|
from evaluators.MultipleOutEvaluator import MultipleOutEvaluator
|
||||||
|
|
||||||
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||||
|
from tests.evaluators.EvaluatorTestsUtils import reduced_requested, e_ret_val_new, p_ret_val_false, p_ret_val_true, \
|
||||||
|
e_ret_val_false, e_ret_val
|
||||||
|
|
||||||
|
|
||||||
|
class TestMultipleOutEvaluator(TestUsingMemoryBasedSheerka):
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("return_values, expected", [
|
||||||
|
([reduced_requested,
|
||||||
|
e_ret_val_new(BuiltinConcepts.TO_DICT, body={}),
|
||||||
|
e_ret_val_new(BuiltinConcepts.TO_DICT, body={}),
|
||||||
|
p_ret_val_false("value"),
|
||||||
|
e_ret_val_false()], True),
|
||||||
|
|
||||||
|
# only one to_dict
|
||||||
|
([reduced_requested, e_ret_val_new(BuiltinConcepts.TO_DICT, body={})], False),
|
||||||
|
|
||||||
|
# reduce request missing
|
||||||
|
([e_ret_val_new(BuiltinConcepts.TO_DICT, body={}), e_ret_val_new(BuiltinConcepts.TO_DICT, body={})], False),
|
||||||
|
|
||||||
|
# parser result not evaluated
|
||||||
|
([reduced_requested,
|
||||||
|
e_ret_val_new(BuiltinConcepts.TO_DICT, body={}),
|
||||||
|
e_ret_val_new(BuiltinConcepts.TO_DICT, body={}),
|
||||||
|
p_ret_val_true("value")], False),
|
||||||
|
])
|
||||||
|
def test_i_can_match(self, return_values, expected):
|
||||||
|
sheerka, context = self.init_concepts()
|
||||||
|
evaluator = MultipleOutEvaluator()
|
||||||
|
|
||||||
|
assert evaluator.matches(context, return_values) == expected
|
||||||
|
|
||||||
|
def test_i_can_eval(self):
|
||||||
|
sheerka, context = self.init_concepts()
|
||||||
|
evaluator = MultipleOutEvaluator()
|
||||||
|
|
||||||
|
first_out = sheerka.new(BuiltinConcepts.TO_DICT, body={"a": 1})
|
||||||
|
second_out = sheerka.new(BuiltinConcepts.TO_DICT, body={"b": 1})
|
||||||
|
|
||||||
|
return_values = [reduced_requested,
|
||||||
|
e_ret_val(first_out),
|
||||||
|
e_ret_val(second_out),
|
||||||
|
p_ret_val_false("value"),
|
||||||
|
e_ret_val_false()]
|
||||||
|
|
||||||
|
evaluator.matches(context, return_values)
|
||||||
|
res = evaluator.eval(context, return_values)
|
||||||
|
|
||||||
|
assert sheerka.isinstance(res, BuiltinConcepts.RETURN_VALUE)
|
||||||
|
assert res.body == sheerka.new(BuiltinConcepts.TO_MULTI, body=[first_out, second_out])
|
||||||
|
assert res.parents == return_values
|
||||||
@@ -14,3 +14,41 @@ class TestSheerkaNonRegDisplay(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
assert captured.out == "ReturnValue(who=evaluators.OneSuccess, status=True, value=(1001)one)\n"
|
assert captured.out == "ReturnValue(who=evaluators.OneSuccess, status=True, value=(1001)one)\n"
|
||||||
|
|
||||||
|
def test_i_can_display_multiple_concepts_description(self, capsys):
|
||||||
|
init = [
|
||||||
|
"def concept foo as 1",
|
||||||
|
"def concept foo as 2",
|
||||||
|
]
|
||||||
|
sheerka = self.init_scenario(init)
|
||||||
|
capsys.readouterr()
|
||||||
|
|
||||||
|
sheerka.enable_process_return_values = True
|
||||||
|
sheerka.evaluate_user_input("desc(foo)")
|
||||||
|
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert captured.out == """id : 1001
|
||||||
|
name : foo
|
||||||
|
key : foo
|
||||||
|
definition: None
|
||||||
|
type : None
|
||||||
|
body : 1
|
||||||
|
where : None
|
||||||
|
pre : None
|
||||||
|
post : None
|
||||||
|
ret : None
|
||||||
|
vars : []
|
||||||
|
props : {}
|
||||||
|
id : 1002
|
||||||
|
name : foo
|
||||||
|
key : foo
|
||||||
|
definition: None
|
||||||
|
type : None
|
||||||
|
body : 2
|
||||||
|
where : None
|
||||||
|
pre : None
|
||||||
|
post : None
|
||||||
|
ret : None
|
||||||
|
vars : []
|
||||||
|
props : {}
|
||||||
|
"""
|
||||||
|
|||||||
@@ -1183,6 +1183,19 @@ as:
|
|||||||
assert sheerka.get_attr(res[0].body, sheerka.new("size")) == sheerka.new("little")
|
assert sheerka.get_attr(res[0].body, sheerka.new("size")) == sheerka.new("little")
|
||||||
assert sheerka.get_attr(res[0].body, sheerka.new("adjective")) == sheerka.new("beautiful")
|
assert sheerka.get_attr(res[0].body, sheerka.new("adjective")) == sheerka.new("beautiful")
|
||||||
|
|
||||||
|
def test_i_can_display_multiple_concepts_using_desc_command(self):
|
||||||
|
init = [
|
||||||
|
"def concept foo as 1",
|
||||||
|
"def concept foo as 2",
|
||||||
|
]
|
||||||
|
sheerka = self.init_scenario(init)
|
||||||
|
|
||||||
|
res = sheerka.evaluate_user_input("desc(foo)")
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
assert res[0].status
|
||||||
|
assert sheerka.isinstance(res[0].body, BuiltinConcepts.TO_MULTI)
|
||||||
|
|
||||||
|
|
||||||
class TestSheerkaNonRegFile(TestUsingFileBasedSheerka):
|
class TestSheerkaNonRegFile(TestUsingFileBasedSheerka):
|
||||||
def test_i_can_def_several_concepts(self):
|
def test_i_can_def_several_concepts(self):
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
from core.sheerka.services.SheerkaDebugManager import NullDebugLogger
|
from core.sheerka.services.SheerkaDebugManager import NullDebugLogger
|
||||||
from core.sheerka.services.SheerkaOut import SheerkaOut
|
from core.sheerka.services.SheerkaOut import SheerkaOut
|
||||||
from core.sheerka.services.SheerkaRuleManager import FormatAstList, FormatAstVariable
|
from core.sheerka.services.SheerkaRuleManager import FormatAstList, FormatAstVariable, FormatAstDict, FormatAstMulti
|
||||||
from out.DeveloperVisitor import DeveloperVisitor
|
from out.DeveloperVisitor import DeveloperVisitor
|
||||||
|
|
||||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||||
@@ -12,10 +13,10 @@ class TestDeveloperVisitor(TestUsingMemoryBasedSheerka):
|
|||||||
service_out = sheerka.services[SheerkaOut.NAME]
|
service_out = sheerka.services[SheerkaOut.NAME]
|
||||||
dev_visitor = DeveloperVisitor(service_out, NullDebugLogger(), set(), 0)
|
dev_visitor = DeveloperVisitor(service_out, NullDebugLogger(), set(), 0)
|
||||||
|
|
||||||
bag = {"a": ["a", "b", "c"]}
|
bag = {"to_format": ["a", "b", "c"]}
|
||||||
|
|
||||||
res = dev_visitor.visit(context, FormatAstList("a"), bag)
|
res = dev_visitor.visit(context, FormatAstList("to_format"), bag)
|
||||||
assert res == FormatAstList(variable="a", items=[
|
assert res == FormatAstList(variable="to_format", items=[
|
||||||
FormatAstVariable(name="__item", index=0, value="a"),
|
FormatAstVariable(name="__item", index=0, value="a"),
|
||||||
FormatAstVariable(name="__item", index=1, value="b"),
|
FormatAstVariable(name="__item", index=1, value="b"),
|
||||||
FormatAstVariable(name="__item", index=2, value="c"),
|
FormatAstVariable(name="__item", index=2, value="c"),
|
||||||
@@ -26,10 +27,10 @@ class TestDeveloperVisitor(TestUsingMemoryBasedSheerka):
|
|||||||
service_out = sheerka.services[SheerkaOut.NAME]
|
service_out = sheerka.services[SheerkaOut.NAME]
|
||||||
dev_visitor = DeveloperVisitor(service_out, NullDebugLogger(), set(), 0)
|
dev_visitor = DeveloperVisitor(service_out, NullDebugLogger(), set(), 0)
|
||||||
|
|
||||||
bag = {"a": [["a1", "a2"], ["b1"]]}
|
bag = {"to_format": [["a1", "a2"], ["b1"]]}
|
||||||
|
|
||||||
res = dev_visitor.visit(context, FormatAstList("a"), bag)
|
res = dev_visitor.visit(context, FormatAstList("to_format"), bag)
|
||||||
assert res == FormatAstList(variable="a", items=[
|
assert res == FormatAstList(variable="to_format", items=[
|
||||||
FormatAstList(variable="__item", index=0, debug=True, prefix='[', suffix=']', items=[
|
FormatAstList(variable="__item", index=0, debug=True, prefix='[', suffix=']', items=[
|
||||||
FormatAstVariable(name="__item", index=0, debug=True, value="a1"),
|
FormatAstVariable(name="__item", index=0, debug=True, value="a1"),
|
||||||
FormatAstVariable(name="__item", index=1, debug=True, value="a2"),
|
FormatAstVariable(name="__item", index=1, debug=True, value="a2"),
|
||||||
@@ -38,3 +39,41 @@ class TestDeveloperVisitor(TestUsingMemoryBasedSheerka):
|
|||||||
FormatAstVariable(name="__item", index=0, debug=True, value="b1"),
|
FormatAstVariable(name="__item", index=0, debug=True, value="b1"),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_i_can_develop_dict(self):
|
||||||
|
sheerka, context = self.init_concepts()
|
||||||
|
service_out = sheerka.services[SheerkaOut.NAME]
|
||||||
|
dev_visitor = DeveloperVisitor(service_out, NullDebugLogger(), set(), 0)
|
||||||
|
|
||||||
|
bag = {"to_format": {"a": "value1", "b": 3.14}}
|
||||||
|
|
||||||
|
res = dev_visitor.visit(context, FormatAstDict("to_format"), bag)
|
||||||
|
|
||||||
|
assert res == FormatAstDict(variable='to_format', items=[
|
||||||
|
(FormatAstVariable(name='__key', index=0, value='a'),
|
||||||
|
FormatAstVariable(name='__value', index='a', value='value1')),
|
||||||
|
(FormatAstVariable(name='__key', index=1, value='b'),
|
||||||
|
FormatAstVariable(name='__value', index='b', value=3.14))])
|
||||||
|
|
||||||
|
def test_i_can_develop_multi(self):
|
||||||
|
sheerka, context, *rules = self.init_format_rules(
|
||||||
|
("isinstance(to_format, BuiltinConcepts.TO_DICT)", "dict(to_format)"))
|
||||||
|
service_out = sheerka.services[SheerkaOut.NAME]
|
||||||
|
dev_visitor = DeveloperVisitor(service_out, NullDebugLogger(), set(), 0)
|
||||||
|
|
||||||
|
item1 = sheerka.new(BuiltinConcepts.TO_DICT, body={"a1": "value1"})
|
||||||
|
item2 = sheerka.new(BuiltinConcepts.TO_DICT, body={"a2": "value2"})
|
||||||
|
|
||||||
|
bag = {"to_format": sheerka.new(BuiltinConcepts.TO_MULTI, body=[item1, item2])}
|
||||||
|
|
||||||
|
res = dev_visitor.visit(context, FormatAstMulti("to_format"), bag)
|
||||||
|
|
||||||
|
assert res == FormatAstMulti("to_format", items=[
|
||||||
|
FormatAstDict(variable='to_format', items=[
|
||||||
|
(FormatAstVariable(name='__key', index=0, value='a1'),
|
||||||
|
FormatAstVariable(name='__value', index='a1', value='value1'))]),
|
||||||
|
|
||||||
|
FormatAstDict(variable='to_format', items=[
|
||||||
|
(FormatAstVariable(name='__key', index=0, value='a2'),
|
||||||
|
FormatAstVariable(name='__value', index='a2', value='value2'))])
|
||||||
|
])
|
||||||
|
|||||||
Reference in New Issue
Block a user