Refactored ExecutionContext serialization (added sheerkapickle) and added History management
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
from core.builtin_concepts import UserInputConcept, ReturnValueConcept, BuiltinConcepts
|
||||
from core.sheerka.Sheerka import Sheerka
|
||||
from evaluators.BaseEvaluator import BaseEvaluator
|
||||
from parsers.BaseParser import BaseParser
|
||||
from sheerkapickle.handlers import BaseHandler, registry
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE as CONCEPT_PROPERTIES_TO_SERIALIZE, ConceptParts
|
||||
from core.sheerka.ExecutionContext import ExecutionContext, PROPERTIES_TO_SERIALIZE as CONTEXT_PROPERTIES_TO_SERIALIZE
|
||||
|
||||
default_concept = Concept()
|
||||
CONCEPT_ID = "concept/id"
|
||||
|
||||
|
||||
class ConceptHandler(BaseHandler):
|
||||
|
||||
def flatten(self, obj: Concept, data):
|
||||
pickler = self.context
|
||||
sheerka = self.sheerka
|
||||
|
||||
if obj.id:
|
||||
ref = sheerka.get_by_id(obj.id)
|
||||
data[CONCEPT_ID] = (obj.key, obj.id)
|
||||
else:
|
||||
ref = default_concept
|
||||
|
||||
# transform metadata
|
||||
for prop in CONCEPT_PROPERTIES_TO_SERIALIZE:
|
||||
value = getattr(obj.metadata, prop)
|
||||
ref_value = getattr(ref.metadata, prop)
|
||||
if value != ref_value:
|
||||
data["meta." + prop] = pickler.flatten(value)
|
||||
|
||||
# transform value
|
||||
for metadata, value in obj.values.items():
|
||||
ref_value = ref.values[metadata] if metadata in ref.values else None
|
||||
if value != ref_value:
|
||||
data[metadata.value] = pickler.flatten(value)
|
||||
|
||||
# transform properties
|
||||
for prop in obj.props:
|
||||
value = obj.props[prop].value
|
||||
if prop not in ref.props or value != ref.props[prop].value:
|
||||
if "props" not in data:
|
||||
data["props"] = []
|
||||
data["props"].append((prop, pickler.flatten(value)))
|
||||
|
||||
return data
|
||||
|
||||
def new(self, data):
|
||||
sheerka = self.sheerka
|
||||
return sheerka.new(tuple(data[CONCEPT_ID])) if CONCEPT_ID in data else Concept()
|
||||
|
||||
def restore(self, data, instance):
|
||||
pickler = self.context
|
||||
|
||||
for key, value in data.items():
|
||||
if key.startswith("_sheerka/") or key == CONCEPT_ID:
|
||||
continue
|
||||
|
||||
resolved_value = pickler.restore(data[key])
|
||||
|
||||
if key.startswith("meta."):
|
||||
# get metadata
|
||||
resolved_prop = key[5:]
|
||||
if resolved_prop == "props":
|
||||
for prop_name, prop_value in resolved_value:
|
||||
instance.def_prop(prop_name, prop_value)
|
||||
else:
|
||||
setattr(instance.metadata, resolved_prop, resolved_value)
|
||||
elif key == "props":
|
||||
# get properties
|
||||
for prop_name, prop_value in resolved_value:
|
||||
instance.set_prop(prop_name, prop_value)
|
||||
else:
|
||||
# get value
|
||||
instance.set_metadata_value(ConceptParts(key), resolved_value)
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class UserInputHandler(BaseHandler):
|
||||
|
||||
def flatten(self, obj: UserInputConcept, data):
|
||||
data[CONCEPT_ID] = (obj.key, obj.id)
|
||||
data["user_name"] = obj.user_name
|
||||
data["text"] = BaseParser.get_text_from_tokens(obj.text) if isinstance(obj.text, list) else obj.text
|
||||
return data
|
||||
|
||||
def new(self, data):
|
||||
sheerka = self.sheerka
|
||||
|
||||
instance = sheerka.new(tuple(data[CONCEPT_ID]), body=data["text"], user_name=data["user_name"])
|
||||
return instance
|
||||
|
||||
def restore(self, data, instance):
|
||||
return instance
|
||||
|
||||
|
||||
class ReturnValueHandler(BaseHandler):
|
||||
|
||||
def flatten(self, obj: ReturnValueConcept, data):
|
||||
pickler = self.context
|
||||
|
||||
data["who"] = f"c:{obj.who.id}:" if isinstance(obj.who, Concept) else \
|
||||
obj.who.name if isinstance(obj.who, (BaseParser, BaseEvaluator)) else \
|
||||
obj.who
|
||||
data["status"] = obj.status
|
||||
data["value"] = pickler.flatten(obj.value)
|
||||
if obj.parents:
|
||||
data["parents"] = pickler.flatten(obj.parents)
|
||||
return data
|
||||
|
||||
def new(self, data):
|
||||
sheerka = self.sheerka
|
||||
instance = sheerka.ret(data["who"], data["status"], None)
|
||||
return instance
|
||||
|
||||
def restore(self, data, instance):
|
||||
pickler = self.context
|
||||
|
||||
instance.value = pickler.restore(data["value"])
|
||||
if "parents" in data:
|
||||
instance.parents = pickler.restore(data["parents"])
|
||||
return instance
|
||||
|
||||
|
||||
# class BuiltinConceptsHandler(BaseHandler):
|
||||
#
|
||||
# def flatten(self, obj: BuiltinConcepts, data):
|
||||
# return data
|
||||
#
|
||||
# def restore(self, obj):
|
||||
# pass
|
||||
|
||||
|
||||
class SheerkaHandler(BaseHandler):
|
||||
|
||||
def flatten(self, obj: BuiltinConcepts, data):
|
||||
return data
|
||||
|
||||
def new(self, data):
|
||||
return self.sheerka
|
||||
|
||||
def restore(self, data, instance):
|
||||
return instance
|
||||
|
||||
|
||||
class ExecutionContextHandler(BaseHandler):
|
||||
|
||||
def flatten(self, obj, data):
|
||||
pickler = self.context
|
||||
|
||||
for prop in CONTEXT_PROPERTIES_TO_SERIALIZE:
|
||||
if prop == "who":
|
||||
value = str(getattr(obj, prop))
|
||||
else:
|
||||
value = getattr(obj, prop)
|
||||
|
||||
if value is not None:
|
||||
data[prop] = pickler.flatten(value)
|
||||
|
||||
return data
|
||||
|
||||
def new(self, data):
|
||||
return ExecutionContext(data["who"], None, None)
|
||||
|
||||
def restore(self, data, instance):
|
||||
pickler = self.context
|
||||
|
||||
for prop in CONTEXT_PROPERTIES_TO_SERIALIZE:
|
||||
if prop not in data or prop == "who":
|
||||
continue
|
||||
setattr(instance, prop, pickler.restore(data[prop]))
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def initialize_pickle_handlers():
|
||||
registry.register(Concept, ConceptHandler, True)
|
||||
registry.register(UserInputConcept, UserInputHandler, True)
|
||||
registry.register(ReturnValueConcept, ReturnValueHandler, True)
|
||||
registry.register(Sheerka, SheerkaHandler, True)
|
||||
registry.register(ExecutionContext, ExecutionContextHandler, True)
|
||||
Reference in New Issue
Block a user