Refactored ExecutionContext serialization (added sheerkapickle) and added History management
This commit is contained in:
@@ -4,9 +4,22 @@ import time
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
from sheerkapickle.SheerkaPickler import SheerkaPickler
|
||||
|
||||
DEBUG_TAB_SIZE = 4
|
||||
|
||||
PROPERTIES_TO_SERIALIZE = ("_id",
|
||||
"_bag",
|
||||
"_start",
|
||||
"_stop",
|
||||
"who",
|
||||
"desc",
|
||||
"children",
|
||||
"inputs",
|
||||
"values",
|
||||
"obj",
|
||||
"concepts")
|
||||
|
||||
|
||||
class ExecutionContext:
|
||||
"""
|
||||
@@ -31,7 +44,7 @@ class ExecutionContext:
|
||||
**kwargs):
|
||||
|
||||
self._parent = None
|
||||
self._id = ExecutionContext.get_id(event.get_digest())
|
||||
self._id = ExecutionContext.get_id(event.get_digest()) if event else None
|
||||
self._tab = ""
|
||||
self._bag = {} # other variables
|
||||
self._start = 0
|
||||
@@ -90,6 +103,26 @@ class ExecutionContext:
|
||||
msg += ")"
|
||||
return msg
|
||||
|
||||
def __eq__(self, other):
|
||||
if id(self) == id(other):
|
||||
return True
|
||||
|
||||
if not isinstance(other, ExecutionContext):
|
||||
return False
|
||||
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
if prop == "who":
|
||||
value = str(getattr(self, prop))
|
||||
other_value = str(getattr(other, prop))
|
||||
else:
|
||||
value = getattr(self, prop)
|
||||
other_value = getattr(other, prop)
|
||||
|
||||
if value != other_value:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def add_preprocess(self, name, **kwargs):
|
||||
preprocess = self.sheerka.new(BuiltinConcepts.EVALUATOR_PRE_PROCESS)
|
||||
preprocess.set_prop("name", name)
|
||||
@@ -189,10 +222,6 @@ class ExecutionContext:
|
||||
to_str = self.return_value_to_str(r)
|
||||
logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str)
|
||||
|
||||
def to_dict(self):
|
||||
from core.sheerka_transform import SheerkaTransform
|
||||
st = SheerkaTransform(self.sheerka)
|
||||
return st.to_dict(self)
|
||||
|
||||
@staticmethod
|
||||
def return_value_to_str(r):
|
||||
|
||||
@@ -39,7 +39,8 @@ class SheerkaDump:
|
||||
self.sheerka.log.info(f"name : {c.name}")
|
||||
self.sheerka.log.info(f"bnf : {c.metadata.definition}")
|
||||
self.sheerka.log.info(f"key : {c.key}")
|
||||
self.sheerka.log.info(f"body : {c.body}")
|
||||
self.sheerka.log.info(f"body : {c.metadata.body}")
|
||||
self.sheerka.log.info(f"value : {c.body}")
|
||||
self.sheerka.log.info(f"digest : {c.get_digest()}")
|
||||
first = False
|
||||
|
||||
@@ -57,7 +58,7 @@ class SheerkaDump:
|
||||
|
||||
while True:
|
||||
try:
|
||||
if h.user != self.sheerka.name:
|
||||
if h.event.user != self.sheerka.name:
|
||||
self.sheerka.log.info(h)
|
||||
count += 1
|
||||
h = next(history)
|
||||
@@ -218,7 +218,7 @@ class SheerkaExecute:
|
||||
|
||||
for step in execution_steps:
|
||||
copy = return_values[:] if hasattr(return_values, "__iter__") else [return_values]
|
||||
with execution_context.push(step=step, iteration=0, desc=f"{step=}", return_values=copy) as sub_context:
|
||||
with execution_context.push(step=step, iteration=0, desc=f"{step=}") as sub_context:
|
||||
sub_context.log(logger or self.sheerka.log, f"{step=}, context='{sub_context}'")
|
||||
|
||||
if step == BuiltinConcepts.PARSING:
|
||||
@@ -0,0 +1,74 @@
|
||||
from collections import namedtuple
|
||||
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
hist = namedtuple("History", "text status") # tests purposes only
|
||||
|
||||
|
||||
class History:
|
||||
def __init__(self, event: Event, result):
|
||||
self.event = event
|
||||
self.result = result
|
||||
self._status = None
|
||||
|
||||
def __str__(self):
|
||||
msg = f"{self.event.get_digest()} {self.event.date.strftime('%d/%m/%Y %H:%M:%S')} : {self.event.message}"
|
||||
status = self.status
|
||||
if status is not None:
|
||||
msg += f" => {status}"
|
||||
return msg
|
||||
|
||||
def __repr__(self):
|
||||
return f"event={self.event!r}, status={self.status}, result={self.result}"
|
||||
|
||||
def __eq__(self, other):
|
||||
if id(self) == id(other):
|
||||
return True
|
||||
|
||||
if isinstance(other, hist):
|
||||
return self.event.message == other.text and self.status == other.status
|
||||
|
||||
if not isinstance(other, History):
|
||||
return False
|
||||
|
||||
return self.event == other.event and self.result == other.result
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
if self._status:
|
||||
return self._status
|
||||
|
||||
if not self.result or "return_values" not in self.result.values:
|
||||
return
|
||||
|
||||
if hasattr(self.result.values["return_values"], "__iter__"):
|
||||
if len(self.result.values["return_values"]) != 1:
|
||||
self._status = False
|
||||
return self._status
|
||||
else:
|
||||
self._status = self.result.values["return_values"][0].status
|
||||
return self._status
|
||||
else:
|
||||
self._status = self.result.values["return_values"].status
|
||||
return self._status
|
||||
|
||||
|
||||
class SheerkaHistoryManager:
|
||||
def __init__(self, sheerka):
|
||||
self.sheerka = sheerka
|
||||
|
||||
def history(self, depth_or_digest, start):
|
||||
"""
|
||||
Load history
|
||||
:param depth_or_digest: number of items or digest
|
||||
:param start:
|
||||
:return:
|
||||
"""
|
||||
|
||||
events = list(self.sheerka.sdp.load_events(depth_or_digest, start))
|
||||
for event in events:
|
||||
try:
|
||||
result = self.sheerka.sdp.load_result(self.sheerka, event.get_digest())
|
||||
except (IOError, KeyError):
|
||||
result = None
|
||||
yield History(event, result)
|
||||
+36
-10
@@ -2,11 +2,12 @@ from core.builtin_concepts import BuiltinConcepts, ErrorConcept, ReturnValueConc
|
||||
UnknownConcept
|
||||
from core.concept import Concept, ConceptParts, PROPERTIES_FOR_NEW
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka.SheerkaCreateNewConcept import SheerkaCreateNewConcept
|
||||
from core.sheerka.SheerkaDump import SheerkaDump
|
||||
from core.sheerka.SheerkaEvaluateConcept import SheerkaEvaluateConcept
|
||||
from core.sheerka.SheerkaExecute import SheerkaExecute
|
||||
from core.sheerka.SheerkaSetsManager import SheerkaSetsManager
|
||||
from core.sheerka.Services.SheerkaCreateNewConcept import SheerkaCreateNewConcept
|
||||
from core.sheerka.Services.SheerkaDump import SheerkaDump
|
||||
from core.sheerka.Services.SheerkaEvaluateConcept import SheerkaEvaluateConcept
|
||||
from core.sheerka.Services.SheerkaExecute import SheerkaExecute
|
||||
from core.sheerka.Services.SheerkaHistoryManager import SheerkaHistoryManager
|
||||
from core.sheerka.Services.SheerkaSetsManager import SheerkaSetsManager
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event
|
||||
import core.utils
|
||||
import core.builtin_helpers
|
||||
@@ -21,7 +22,7 @@ import logging
|
||||
# BuiltinConcepts.AFTER_EVALUATION]
|
||||
|
||||
CONCEPT_LEXER_PARSER_CLASS = "parsers.ConceptLexerParser.ConceptLexerParser"
|
||||
|
||||
CONCEPTS_FILE = "_concepts.txt"
|
||||
|
||||
class Sheerka(Concept):
|
||||
"""
|
||||
@@ -81,6 +82,7 @@ class Sheerka(Concept):
|
||||
self.dump_handler = SheerkaDump(self)
|
||||
self.sets_handler = SheerkaSetsManager(self)
|
||||
self.evaluate_concept_handler = SheerkaEvaluateConcept(self)
|
||||
self.history_handler = SheerkaHistoryManager(self)
|
||||
|
||||
def initialize(self, root_folder: str = None):
|
||||
"""
|
||||
@@ -92,6 +94,9 @@ class Sheerka(Concept):
|
||||
"""
|
||||
|
||||
try:
|
||||
from sheerkapickle.sheerka_handlers import initialize_pickle_handlers
|
||||
initialize_pickle_handlers()
|
||||
|
||||
self.sdp = SheerkaDataProvider(root_folder)
|
||||
if self.sdp.first_time:
|
||||
self.sdp.set_key(self.USER_CONCEPTS_KEYS, 1000)
|
||||
@@ -104,11 +109,16 @@ class Sheerka(Concept):
|
||||
self.initialize_builtin_parsers()
|
||||
self.initialize_builtin_evaluators()
|
||||
self.initialize_concepts_definitions(exec_context)
|
||||
res = ReturnValueConcept(self, True, self)
|
||||
|
||||
exec_context.add_values(return_values=res)
|
||||
if not self.skip_builtins_in_db:
|
||||
self.sdp.save_result(self, exec_context)
|
||||
|
||||
except IOError as e:
|
||||
return ReturnValueConcept(self, False, self.get(BuiltinConcepts.ERROR), e)
|
||||
res = ReturnValueConcept(self, False, self.get(BuiltinConcepts.ERROR), e)
|
||||
|
||||
return ReturnValueConcept(self, True, self)
|
||||
return res
|
||||
|
||||
def initialize_builtin_concepts(self):
|
||||
"""
|
||||
@@ -232,7 +242,12 @@ class Sheerka(Concept):
|
||||
execution_context.add_values(return_values=ret)
|
||||
|
||||
if not self.skip_builtins_in_db:
|
||||
self.sdp.save_result(execution_context)
|
||||
self.sdp.save_result(self, execution_context)
|
||||
|
||||
#hack to save valid concept definition
|
||||
if len(ret) == 1 and ret[0].status and self.isinstance(ret[0].value, BuiltinConcepts.NEW_CONCEPT):
|
||||
with open(CONCEPTS_FILE, "a") as f:
|
||||
f.write(text + "\n")
|
||||
return ret
|
||||
|
||||
def execute(self, execution_context, return_values, execution_steps, logger=None):
|
||||
@@ -549,8 +564,19 @@ class Sheerka(Concept):
|
||||
|
||||
def history(self, page=10, start=0):
|
||||
"""Gets the history of all commands"""
|
||||
return self.sdp.load_events(page, start)
|
||||
return self.history_handler.history(page, start)
|
||||
|
||||
def restore(self):
|
||||
"""
|
||||
Restore the state with all previous valid concept definitions
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
with open(CONCEPTS_FILE, "r") as f:
|
||||
for line in f.readlines():
|
||||
self.evaluate_user_input(line)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
def test(self):
|
||||
return f"I have access to Sheerka !"
|
||||
|
||||
Reference in New Issue
Block a user