Added first version of DebugManager. Implemented draft of the rule engine

This commit is contained in:
2020-11-20 13:41:45 +01:00
parent cd066881b4
commit 315f8ea09b
156 changed files with 8388 additions and 2852 deletions
+112 -50
View File
@@ -1,17 +1,26 @@
import logging
import os
import pprint
import time
from core.builtin_concepts import BuiltinConcepts, ParserResultConcept
from core.concept import Concept
from core.concept import Concept, get_concept_attrs
from core.global_symbols import CONTEXT_DISPOSED
from core.sheerka.services.SheerkaExecute import NO_MATCH
from core.sheerka.services.SheerkaMemory import SheerkaMemory
from core.sheerka_logger import get_logger
from core.utils import CONSOLE_COLORS_MAP as CCM
from sdp.sheerkaDataProvider import Event
try:
rows, columns = os.popen('stty size', 'r').read().split()
except ValueError:
rows, columns = 50, 80
pp = pprint.PrettyPrinter(indent=2, width=columns)
DEBUG_TAB_SIZE = 4
PROPERTIES_TO_SERIALIZE = ("_id",
"_bag",
"_children",
"_start",
"_stop",
@@ -50,19 +59,17 @@ class ExecutionContext:
logger=None,
global_hints=None,
errors=None,
**kwargs):
obj=None,
concepts=None):
self._id = ExecutionContext.get_id(event.get_digest()) if event else None
self._parent = None
self._children = []
self._tab = ""
self._bag = {} # context variables
self._start = 0 # when the execution starts (to measure elapsed time)
self._stop = 0 # when the execution stops (to measure elapses time)
self._logger = logger
self._format_instructions = None # how to print the execution context
self._stat_log = get_logger("stats")
self._show_stats = False
self._push = None
self.who = who # who is asking
self.event = event # what was the (original) trigger
@@ -70,6 +77,8 @@ class ExecutionContext:
self.action = action
self.action_context = action_context
self.desc = desc # human description of what is going on
self.preprocess_parsers = None
self.preprocess_evaluators = None
self.preprocess = None
self.stm = False # True if the context has short term memory entries
@@ -80,13 +89,11 @@ class ExecutionContext:
self.inputs = {} # what were the parameters of the execution context
self.values = {} # what was produced by the execution context
self.obj = kwargs.pop("obj", None) # current obj we are working on
self.obj = obj
self.concepts = concepts
self.concepts = kwargs.pop("concepts", {}) # known concepts specific to this context
# update the other elements
for k, v in kwargs.items():
self._bag[k] = v
self_debug, self.debug_mode = sheerka.get_context_debug_mode(self.id)
self.debug_enabled = self_debug is not None
@property
def elapsed(self):
@@ -117,24 +124,19 @@ class ExecutionContext:
"""
return self._children
def __getattr__(self, item):
if item in self._bag:
return self._bag[item]
raise AttributeError(f"'ExecutionContext' object has no attribute '{item}'")
def __enter__(self):
self._start = time.time_ns()
self.log_new()
# self.log_new()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if self._push:
return
if self.stm:
self.sheerka.services[SheerkaMemory.NAME].remove_context(self)
self.sheerka.publish(self, CONTEXT_DISPOSED)
self._stop = time.time_ns()
if self._show_stats:
self._stat_log.debug(f"[{self._id:2}]" + self._tab + "Execution time: " + self.elapsed_str)
def __repr__(self):
msg = f"ExecutionContext(who={self.who}, id={self._id}, action={self.action}, context={self.action_context}"
@@ -143,11 +145,6 @@ class ExecutionContext:
msg += ")"
return msg
# def __str__(self):
# msg = self.desc or "New Context"
# msg += f", who={self.who}, id={self.id}"
# return msg
def __eq__(self, other):
if id(self) == id(other):
return True
@@ -168,12 +165,12 @@ class ExecutionContext:
return True
def push(self, action: BuiltinConcepts, action_context, who=None, desc=None, logger=None, **kwargs):
def push(self, action: BuiltinConcepts, action_context, who=None, desc=None, logger=None, obj=None, concepts=None):
if self._push:
return self._push
who = who or self.who
logger = logger or self._logger
_kwargs = {"obj": self.obj, "concepts": self.concepts}
_kwargs.update(self._bag)
_kwargs.update(kwargs)
new = ExecutionContext(
who,
self.event,
@@ -184,19 +181,40 @@ class ExecutionContext:
logger,
self.global_hints,
self.errors,
**_kwargs)
obj or self.obj,
concepts or self.concepts)
new._parent = self
new._tab = self._tab + " " * DEBUG_TAB_SIZE
new.preprocess = self.preprocess
new.preprocess_parsers = self.preprocess_parsers
new.preprocess_evaluators = self.preprocess_evaluators
new.protected_hints.update(self.protected_hints)
if new.debug_mode is None and self.debug_mode == "protected":
new.debug_mode = "protected"
new.debug_enabled = True
self._children.append(new)
return new
def deactivate_push(self):
self._push = self.push(BuiltinConcepts.NOP, None)
self._push._push = self._push
if self.stm:
bag = self.sheerka.services[SheerkaMemory.NAME].get_all_short_term_memory(self)
self.sheerka.add_many_to_short_term_memory(self._push, bag)
def activate_push(self):
if self._push:
if self._push.stm:
self.sheerka.publish(self._push, CONTEXT_DISPOSED)
self._push._stop = time.time_ns()
self._push = None
def add_preprocess(self, name, **kwargs):
preprocess = self.sheerka.new(BuiltinConcepts.EVALUATOR_PRE_PROCESS)
preprocess.set_value("name", name)
preprocess.set_value("preprocess_name", name)
for k, v in kwargs.items():
preprocess.set_value(k, v)
@@ -206,13 +224,17 @@ class ExecutionContext:
return self
def add_inputs(self, **kwargs):
for k, v in kwargs.items():
self.inputs[k] = v
if self._push:
return
self.inputs.update(kwargs)
return self
def add_values(self, **kwargs):
for k, v in kwargs.items():
self.values[k] = v
if self._push:
return
self.values.update(kwargs)
return self
def add_to_short_term_memory(self, key, concept):
@@ -224,6 +246,9 @@ class ExecutionContext:
"""
self.sheerka.add_to_short_term_memory(self, key, concept)
def clear_short_term_memory(self):
self.sheerka.clear_short_term_memory(self)
def get_from_short_term_memory(self, key):
"""
@@ -237,11 +262,10 @@ class ExecutionContext:
if isinstance(self.obj, Concept):
if self.obj.key == key:
return self.obj
for var_name in self.obj.values:
if var_name == key:
value = self.obj.get_value(var_name)
if isinstance(value, Concept):
return value
if key in get_concept_attrs(self.obj):
value = self.obj.get_value(key)
if isinstance(value, Concept):
return value
# search in concepts
if self.concepts:
@@ -296,8 +320,34 @@ class ExecutionContext:
to_str = self.return_value_to_str(r)
self._logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str)
def debug(self, text):
print(text)
def get_debugger(self, who, method_name):
return self.sheerka.get_debugger(self, who, method_name)
def debug(self, who, method_name, variable_name, text, is_error=False):
activated = self.sheerka.debug_activated_for(who)
if activated:
str_text = pp.pformat(text)
color = 'red' if is_error else 'green'
if "\n" not in str(str_text):
self.sheerka.debug(
f"[{self._id:3}] {CCM[color]}{who}.{method_name}.{variable_name}: {CCM['reset']}{str_text}")
else:
self.sheerka.debug(f"[{self._id:3}] {CCM[color]}{who}.{method_name}.{variable_name}: {CCM['reset']}")
self.sheerka.debug(str_text)
def debug_entering(self, who, method_name, **kwargs):
if self.sheerka.debug_activated_for(who):
str_text = pp.pformat(kwargs)
if "\n" not in str(str_text):
self.sheerka.debug(
f"[{self._id:3}] {CCM['blue']}Entering {who}.{method_name} with {CCM['reset']}{str_text}")
else:
self.sheerka.debug(f"[{self._id:3}] {CCM['blue']}Entering {who}.{method_name}:{CCM['reset']}")
self.sheerka.debug(f"[{self._id:3}] {str_text}")
def debug_log(self, who, text):
if self.sheerka.debug_activated_for(who):
self.sheerka.debug(f"[{self._id:3}] {CCM['blue']}{text}{CCM['reset']}")
def get_parent(self):
return self._parent
@@ -384,9 +434,6 @@ class ExecutionContext:
And it removes the visibility from the other attributes/methods
"""
bag = {}
for k, v in self._bag.items():
bag[k] = v
bag["bag." + k] = v
for prop in ("id", "who", "action", "desc", "obj", "inputs", "values", "concepts"):
bag[prop] = getattr(self, prop)
bag["context"] = self.action_context
@@ -396,6 +443,7 @@ class ExecutionContext:
bag["elapsed"] = self.elapsed
bag["elapsed_str"] = self.elapsed_str
bag["digest"] = self.event.get_digest() if self.event else None
bag["_children"] = self._children
return bag
@staticmethod
@@ -438,3 +486,17 @@ class ExecutionContext:
break
current = current._parent
def has_parent(self, context_id):
current = self
while current._parent:
current = current._parent
if current.id == context_id:
return True
if current.id < context_id:
return False
return False