First but not optimized version of AstFormatDict

This commit is contained in:
2020-11-24 13:43:04 +01:00
parent ab30ab3345
commit cac732bd93
21 changed files with 898 additions and 217 deletions
+16 -1
View File
@@ -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()
+24
View File
@@ -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)
+1 -1
View File
@@ -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):
+4 -6
View File
@@ -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))
+106 -26
View File
@@ -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: