First but not optimized version of AstFormatDict
This commit is contained in:
@@ -113,7 +113,8 @@ class Sheerka(Concept):
|
||||
self.methods_with_context = {"test_using_context"} # only the names, the method is defined in sheerka_methods
|
||||
self.sheerka_methods = {
|
||||
"test": SheerkaMethod(self.test, False),
|
||||
"test_using_context": SheerkaMethod(self.test_using_context, False)
|
||||
"test_using_context": SheerkaMethod(self.test_using_context, False),
|
||||
"test_dict": SheerkaMethod(self.test_dict, False)
|
||||
}
|
||||
self.sheerka_pipeables = {}
|
||||
|
||||
@@ -1028,6 +1029,20 @@ class Sheerka(Concept):
|
||||
# uncomment the following line to enable colors
|
||||
# logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)
|
||||
|
||||
def test_dict(self):
|
||||
bag2 = {
|
||||
"alpha": "value4",
|
||||
"beta": ["item1", "item2", "item3", ]
|
||||
}
|
||||
bag = {
|
||||
"a": "value1",
|
||||
"baba": "value2",
|
||||
"c": "value1",
|
||||
"de": ["item1", "item2", "item3", ],
|
||||
"e": bag2
|
||||
}
|
||||
return self.new(BuiltinConcepts.TO_DICT, body=bag)
|
||||
|
||||
|
||||
def to_profile():
|
||||
sheerka = Sheerka()
|
||||
|
||||
@@ -3,6 +3,7 @@ import time
|
||||
from os import path
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, BuiltinContainers
|
||||
from core.builtin_helpers import ensure_concept
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.sheerka_service import BaseService
|
||||
|
||||
@@ -22,6 +23,7 @@ class SheerkaAdmin(BaseService):
|
||||
self.sheerka.bind_service_method(self.cache, False)
|
||||
self.sheerka.bind_service_method(self.restore, True)
|
||||
self.sheerka.bind_service_method(self.concepts, False)
|
||||
self.sheerka.bind_service_method(self.desc, False)
|
||||
self.sheerka.bind_service_method(self.last_created_concept, False)
|
||||
self.sheerka.bind_service_method(self.last_ret, False)
|
||||
self.sheerka.bind_service_method(self.last_error_ret, False)
|
||||
@@ -122,6 +124,28 @@ class SheerkaAdmin(BaseService):
|
||||
def concepts(self):
|
||||
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=self.sheerka.sdp.list(self.sheerka.CONCEPTS_BY_ID_ENTRY))
|
||||
|
||||
def desc(self, *concepts):
|
||||
ensure_concept(*concepts)
|
||||
res = []
|
||||
for c in concepts:
|
||||
bag = {
|
||||
"id": c.id,
|
||||
"name": c.name,
|
||||
"key": c.key,
|
||||
"definition": c.get_metadata().definition,
|
||||
"type": c.get_metadata().definition_type,
|
||||
"body": c.get_metadata().body,
|
||||
"where": c.get_metadata().where,
|
||||
"pre": c.get_metadata().pre,
|
||||
"post": c.get_metadata().post,
|
||||
"ret": c.get_metadata().ret,
|
||||
"vars": c.get_metadata().variables,
|
||||
"props": c.get_metadata().props,
|
||||
}
|
||||
res.append(self.sheerka.new(BuiltinConcepts.TO_DICT, body=bag))
|
||||
|
||||
return res[0] if len(res) == 1 else self.sheerka.new(BuiltinConcepts.TO_LIST, body=res)
|
||||
|
||||
def format_rules(self):
|
||||
return self.sheerka.new(BuiltinConcepts.TO_LIST, items=self.sheerka.get_format_rules())
|
||||
|
||||
|
||||
@@ -34,13 +34,16 @@ class BaseDebugLogger:
|
||||
def debug_entering(self, **kwargs):
|
||||
pass
|
||||
|
||||
def debug_var(self, name, value, is_error=False):
|
||||
def debug_var(self, name, value, is_error=False, hint=None):
|
||||
pass
|
||||
|
||||
def debug_rule(self, rule, results):
|
||||
pass
|
||||
|
||||
def debug_log(self, text):
|
||||
def debug_log(self, text, is_error=False):
|
||||
pass
|
||||
|
||||
def is_enabled(self):
|
||||
pass
|
||||
|
||||
|
||||
@@ -48,6 +51,9 @@ class NullDebugLogger(BaseDebugLogger):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def is_enabled(self):
|
||||
return False
|
||||
|
||||
|
||||
class ConsoleDebugLogger(BaseDebugLogger):
|
||||
|
||||
@@ -60,6 +66,9 @@ class ConsoleDebugLogger(BaseDebugLogger):
|
||||
self.debug_id = debug_id
|
||||
self.is_highlighted = ""
|
||||
|
||||
def is_enabled(self):
|
||||
return True
|
||||
|
||||
def debug_entering(self, **kwargs):
|
||||
super().debug_entering(**kwargs)
|
||||
|
||||
@@ -71,17 +80,18 @@ class ConsoleDebugLogger(BaseDebugLogger):
|
||||
self.debug_manager.debug(self.prefix() + str_text)
|
||||
self.debug_manager.debug(self.prefix() + str_vars)
|
||||
|
||||
def debug_var(self, name, value, is_error=False):
|
||||
enabled = self.debug_manager.compute_var_debug(self.service_name,
|
||||
self.method_name,
|
||||
self.context_id,
|
||||
name,
|
||||
self.context_id)
|
||||
def debug_var(self, name, value, is_error=False, hint=None):
|
||||
enabled = is_error or self.debug_manager.compute_var_debug(self.service_name,
|
||||
self.method_name,
|
||||
self.context_id,
|
||||
name,
|
||||
self.context_id)
|
||||
if enabled == False:
|
||||
return
|
||||
|
||||
color = 'red' if is_error else 'green'
|
||||
str_text = f"{CCM[color]}..{name}={CCM['reset']}"
|
||||
hint_str = f"({hint})" if hint is not None else ""
|
||||
str_text = f"{CCM[color]}..{name}{hint_str}={CCM['reset']}"
|
||||
str_vars = "" if isinstance(enabled, str) else pp.pformat(value)
|
||||
if "\n" not in str(str_vars):
|
||||
self.debug_manager.debug(self.prefix() + str_text + str_vars)
|
||||
@@ -101,8 +111,9 @@ class ConsoleDebugLogger(BaseDebugLogger):
|
||||
self.debug_manager.debug(self.prefix() + str_text)
|
||||
self.debug_manager.debug(self.prefix() + str_vars)
|
||||
|
||||
def debug_log(self, text):
|
||||
self.debug_manager.debug(self.prefix() + f"{CCM['blue']}..{text}{CCM['reset']}")
|
||||
def debug_log(self, text, is_error=False):
|
||||
color = 'red' if is_error else 'blue'
|
||||
self.debug_manager.debug(self.prefix() + f"{CCM[color]}..{text}{CCM['reset']}")
|
||||
|
||||
def prefix(self):
|
||||
return f"[{self.context_id:2}][{self.debug_id:2}] {self.is_highlighted}"
|
||||
@@ -271,12 +282,8 @@ class SheerkaDebugManager(BaseService):
|
||||
res = {}
|
||||
for prop in props:
|
||||
res[prop] = evaluate_expression(prop, bag)
|
||||
# res = {
|
||||
# "return_values": to_inspect.values.get("return_values", None)
|
||||
# }
|
||||
|
||||
pp.pprint(res)
|
||||
return None
|
||||
return self.sheerka.new(BuiltinConcepts.TO_DICT, body=res)
|
||||
|
||||
def debug(self, *args, **kwargs):
|
||||
print(*args, **kwargs)
|
||||
@@ -437,4 +444,4 @@ class SheerkaDebugManager(BaseService):
|
||||
return self.sheerka.ret(SheerkaDebugManager.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||
|
||||
def get_debug_settings(self):
|
||||
return self.debug_vars_settings
|
||||
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=self.debug_vars_settings)
|
||||
|
||||
@@ -21,7 +21,7 @@ class SheerkaDump(BaseService):
|
||||
super().__init__(sheerka)
|
||||
|
||||
def initialize(self):
|
||||
self.sheerka.bind_service_method(self.dump_desc, True, "desc") # has_side_effect 'cause concept is evaluated
|
||||
self.sheerka.bind_service_method(self.dump_desc, True, "old_desc") # has_side_effect 'cause concept is evaluated
|
||||
self.sheerka.bind_service_method(self.dump_sdp, False, "dump_sdp")
|
||||
|
||||
def dump_desc(self, *concept_names, eval=False):
|
||||
|
||||
@@ -16,7 +16,8 @@ class SheerkaOut(BaseService):
|
||||
self.sheerka.bind_service_method(self.process_return_values, False)
|
||||
|
||||
def create_out_tree(self, context, obj):
|
||||
return self.create_out_tree_recursive(context, {'__obj': obj}, DeveloperVisitor(self, set(), 0))
|
||||
debugger = context.get_debugger("Out.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):
|
||||
debugger = context.get_debugger(SheerkaOut.NAME, "create_out_tree")
|
||||
@@ -40,8 +41,7 @@ class SheerkaOut(BaseService):
|
||||
visitor.already_seen.add(rule.id)
|
||||
|
||||
bag.update(as_bag(current_obj)) # update with the current obj attributes
|
||||
visitor.visit(context, rule.compiled_action, bag)
|
||||
res = visitor.get_result()
|
||||
res = visitor.visit(context, rule.compiled_action, bag)
|
||||
|
||||
if res is None:
|
||||
debugger.debug_log(f"No matching rule.")
|
||||
@@ -67,9 +67,7 @@ class SheerkaOut(BaseService):
|
||||
|
||||
if out_tree:
|
||||
for visitor in self.out_visitors:
|
||||
visitor.visit(context, out_tree, None)
|
||||
if hasattr(visitor, "finalize"):
|
||||
visitor.finalize()
|
||||
visitor.visit(out_tree)
|
||||
|
||||
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||
return self.sheerka.ret(self.NAME, False, self.sheerka.new(BuiltinConcepts.NO_RESULT))
|
||||
|
||||
@@ -63,6 +63,15 @@ class FormatAstNode:
|
||||
|
||||
return ", ".join(repr(item) for item in items)
|
||||
|
||||
def clone(self, instance, props, **kwargs):
|
||||
for prop_name in props:
|
||||
setattr(instance, prop_name, getattr(self, prop_name))
|
||||
|
||||
for k, v in kwargs.items():
|
||||
setattr(instance, k, v)
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormatAstRawText(FormatAstNode):
|
||||
@@ -73,9 +82,15 @@ class FormatAstRawText(FormatAstNode):
|
||||
class FormatAstVariable(FormatAstNode):
|
||||
name: str
|
||||
format: Union[str, None] = None
|
||||
debug: bool = False
|
||||
value: object = None
|
||||
index: object = None
|
||||
|
||||
def clone(self, **kwargs):
|
||||
return super().clone(FormatAstVariable(self.name),
|
||||
("format", "debug", "value", "index"),
|
||||
**kwargs)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormatAstVariableNotFound(FormatAstNode):
|
||||
@@ -93,29 +108,50 @@ class FormatAstList(FormatAstNode):
|
||||
items_prop: str = None # where to search the list if variable does not resolve to an iterable
|
||||
recurse_on: str = None
|
||||
recursion_depth: int = 0
|
||||
debug: bool = False
|
||||
prefix: str = None
|
||||
suffix: str = None
|
||||
show_index: bool = False
|
||||
|
||||
items: object = None
|
||||
|
||||
def clone(self, **kwargs):
|
||||
return super().clone(
|
||||
FormatAstList(self.variable),
|
||||
("items_prop", "recurse_on", "recursion_depth", "debug", "prefix", "suffix", "show_index", "items"),
|
||||
**kwargs)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormatAstDict(FormatAstNode):
|
||||
variable: str
|
||||
items_prop: str = None # where to search the dict if variable does not resolve to an iterable
|
||||
debug: bool = False
|
||||
prefix: str = None
|
||||
suffix: str = None
|
||||
|
||||
items: object = None
|
||||
|
||||
def clone(self, **kwargs):
|
||||
return super().clone(
|
||||
FormatAstDict(self.variable),
|
||||
("items_prop", "debug", "prefix", "suffix", "items"),
|
||||
**kwargs)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormatAstColor(FormatAstNode):
|
||||
def __init__(self, color, format_ast):
|
||||
self.color = color
|
||||
self.format_ast = format_ast
|
||||
color: str
|
||||
format_ast: FormatAstNode
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.color}({self.format_ast})"
|
||||
|
||||
def __eq__(self, other):
|
||||
if id(self) == id(other):
|
||||
return True
|
||||
|
||||
if not isinstance(other, FormatAstColor):
|
||||
return False
|
||||
|
||||
return self.color == other.color and self.format_ast == other.format_ast
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.color, self.format_ast))
|
||||
def clone(self, **kwargs):
|
||||
return super().clone(
|
||||
FormatAstColor(self.color, self.format_ast),
|
||||
(),
|
||||
**kwargs)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -125,21 +161,19 @@ class FormatAstFunction(FormatAstNode):
|
||||
kwargs: dict = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormatAstSequence(FormatAstNode):
|
||||
def __init__(self, items):
|
||||
self.items = items
|
||||
items: list
|
||||
debug: bool = False
|
||||
|
||||
def __repr__(self):
|
||||
return "FormatAstSequence(" + self.repr_value(self.items) + ")"
|
||||
|
||||
def __eq__(self, other):
|
||||
if id(self) == id(other):
|
||||
return True
|
||||
|
||||
if not isinstance(other, FormatAstSequence):
|
||||
return False
|
||||
|
||||
return self.items == other.items
|
||||
def clone(self, **kwargs):
|
||||
return super().clone(
|
||||
FormatAstSequence(self.items),
|
||||
("debug",),
|
||||
**kwargs)
|
||||
|
||||
|
||||
class FormatRuleParser(IterParser):
|
||||
@@ -170,6 +204,9 @@ class FormatRuleParser(IterParser):
|
||||
if value[0] in ("'", '"'):
|
||||
return value[1:-1]
|
||||
|
||||
if value in ("True", "False"):
|
||||
return bool(value)
|
||||
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
@@ -278,6 +315,8 @@ class FormatRuleParser(IterParser):
|
||||
return self.return_color(func_name.value, args, kwargs)
|
||||
elif func_name.value == "list":
|
||||
return self.return_list(args, kwargs)
|
||||
elif func_name.value == "dict":
|
||||
return self.return_dict(args, kwargs)
|
||||
|
||||
return FormatAstFunction(func_name.value, self.to_text(args), self.to_text(kwargs))
|
||||
|
||||
@@ -347,13 +386,19 @@ class FormatRuleParser(IterParser):
|
||||
return FormatAstColor(color, FormatAstVariable(variable, vformat))
|
||||
|
||||
def return_list(self, args, kwargs):
|
||||
"""
|
||||
Looking for variable_name, [recurse_on], [recursion_depth], [items_prop]
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
len_args = len(args)
|
||||
if len_args < 1:
|
||||
self.error_sink = FormatRuleSyntaxError("variable name not found", None)
|
||||
return None
|
||||
|
||||
if len_args > 3:
|
||||
self.error_sink = FormatRuleSyntaxError("too many positional arguments", args[3][0])
|
||||
if len_args > 4:
|
||||
self.error_sink = FormatRuleSyntaxError("too many positional arguments", args[4][0])
|
||||
return None
|
||||
|
||||
variable_name = get_text_from_tokens(args[0])
|
||||
@@ -364,6 +409,10 @@ class FormatRuleParser(IterParser):
|
||||
elif len_args == 3:
|
||||
recursion_depth = self.to_value(args[1])
|
||||
recurse_on = self.to_value(args[2])
|
||||
elif len_args == 4:
|
||||
recursion_depth = self.to_value(args[1])
|
||||
recurse_on = self.to_value(args[2])
|
||||
items_prop = self.to_value(args[3])
|
||||
|
||||
if "recurse_on" in kwargs:
|
||||
recurse_on = self.to_value(kwargs["recurse_on"])
|
||||
@@ -383,6 +432,34 @@ class FormatRuleParser(IterParser):
|
||||
|
||||
return FormatAstList(variable_name, items_prop, recurse_on, recursion_depth)
|
||||
|
||||
def return_dict(self, args, kwargs):
|
||||
len_args = len(args)
|
||||
if len_args < 1:
|
||||
self.error_sink = FormatRuleSyntaxError("variable name not found", None)
|
||||
return None
|
||||
|
||||
if len_args > 1:
|
||||
self.error_sink = FormatRuleSyntaxError("too many positional arguments", args[1][0])
|
||||
return None
|
||||
|
||||
variable_name = get_text_from_tokens(args[0])
|
||||
|
||||
kwargs_parameters = {}
|
||||
for prop in ("items_prop", "prefix", "suffix", "debug"):
|
||||
if prop in kwargs:
|
||||
kwargs_parameters[prop] = self.to_value(kwargs[prop])
|
||||
|
||||
if "debug" in kwargs_parameters:
|
||||
if "prefix" not in kwargs_parameters:
|
||||
kwargs_parameters["prefix"] = "{"
|
||||
if "suffix" not in kwargs_parameters:
|
||||
kwargs_parameters["suffix"] = "}"
|
||||
|
||||
if self.error_sink:
|
||||
return None
|
||||
|
||||
return FormatAstDict(variable_name, **kwargs_parameters)
|
||||
|
||||
|
||||
@dataclass()
|
||||
class RulePredicate:
|
||||
@@ -556,6 +633,9 @@ class SheerkaRuleManager(BaseService):
|
||||
Rule("print", "Display formatted list",
|
||||
"isinstance(__ret_container, BuiltinConcepts.TO_LIST)",
|
||||
"list(__ret_container)"),
|
||||
Rule("print", "Display formatted dict",
|
||||
"isinstance(__ret_container, BuiltinConcepts.TO_DICT)",
|
||||
"dict(__ret_container)"),
|
||||
]
|
||||
|
||||
for r in rules:
|
||||
|
||||
Reference in New Issue
Block a user