224 lines
7.5 KiB
Python
224 lines
7.5 KiB
Python
import core.utils
|
|
from core.builtin_concepts import UserInputConcept, ReturnValueConcept, BuiltinConcepts
|
|
from core.concept import Concept, PROPERTIES_TO_SERIALIZE as CONCEPT_PROPERTIES_TO_SERIALIZE
|
|
from core.global_symbols import NotInit
|
|
from core.rule import Rule
|
|
from core.sheerka.ExecutionContext import ExecutionContext, PROPERTIES_TO_SERIALIZE as CONTEXT_PROPERTIES_TO_SERIALIZE
|
|
from core.sheerka.Sheerka import Sheerka
|
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
|
from evaluators.BaseEvaluator import BaseEvaluator
|
|
from parsers.BaseParser import BaseParser
|
|
from parsers.PythonParser import PythonNode
|
|
from sheerkapickle.handlers import BaseHandler, registry
|
|
|
|
default_concept = Concept()
|
|
default_concept_values = default_concept.values()
|
|
CONCEPT_ID = "concept/id"
|
|
RULE_ID = "rule/id"
|
|
|
|
|
|
class ConceptHandler(BaseHandler):
|
|
|
|
def flatten(self, obj: Concept, data):
|
|
pickler = self.context
|
|
sheerka = self.sheerka
|
|
|
|
if obj.get_metadata().full_serialization:
|
|
ref = default_concept
|
|
ref_values = default_concept_values
|
|
else:
|
|
ref = sheerka.get_by_id(obj.id)
|
|
ref_values = ref.values()
|
|
data[CONCEPT_ID] = (obj.key, obj.id)
|
|
|
|
# transform metadata
|
|
for name in CONCEPT_PROPERTIES_TO_SERIALIZE:
|
|
value = getattr(obj.get_metadata(), name)
|
|
ref_value = getattr(ref.get_metadata(), name)
|
|
if value != ref_value:
|
|
value_to_use = [list(t) for t in value] if name == "variables" else value
|
|
data["meta." + name] = pickler.flatten(value_to_use)
|
|
|
|
# # transform values
|
|
for name, value in obj.values().items():
|
|
if name not in ref_values or value != ref_values[name]:
|
|
if "values" not in data:
|
|
data["values"] = []
|
|
data["values"].append((pickler.flatten(name), 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 == "variables":
|
|
for prop_name, prop_value in resolved_value:
|
|
instance.def_var(prop_name, prop_value)
|
|
else:
|
|
setattr(instance.get_metadata(), resolved_prop, resolved_value)
|
|
elif key == "values":
|
|
# get properties
|
|
for prop_name, prop_value in resolved_value:
|
|
instance.set_value(prop_name, NotInit if prop_value is None else prop_value)
|
|
else:
|
|
raise Exception("Sanity check as it's not possible yet")
|
|
|
|
# instance.freeze_definition_hash()
|
|
return instance
|
|
|
|
|
|
class UserInputHandler(ConceptHandler):
|
|
|
|
def flatten(self, obj: UserInputConcept, data):
|
|
data[CONCEPT_ID] = (obj.key, obj.id)
|
|
data["user_name"] = obj.user_name
|
|
data["text"] = core.utils.get_text_from_tokens(obj.text) if isinstance(obj.text, list) else \
|
|
obj.text.as_text() if isinstance(obj.text, ParserInput) else \
|
|
obj.text
|
|
return data
|
|
|
|
def new(self, data):
|
|
return UserInputConcept.__new__(UserInputConcept)
|
|
|
|
def restore(self, data, instance):
|
|
instance.__init__(data["text"], data["user_name"])
|
|
instance.get_metadata().key = data[CONCEPT_ID][0]
|
|
instance.get_metadata().id = data[CONCEPT_ID][1]
|
|
instance.freeze_definition_hash()
|
|
return instance
|
|
|
|
|
|
class ReturnValueHandler(BaseHandler):
|
|
|
|
def flatten(self, obj: ReturnValueConcept, data):
|
|
pickler = self.context
|
|
|
|
data[CONCEPT_ID] = (obj.key, obj.id)
|
|
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):
|
|
return ReturnValueConcept.__new__(ReturnValueConcept)
|
|
|
|
def restore(self, data, instance):
|
|
pickler = self.context
|
|
|
|
instance.__init__(data["who"], data["status"], pickler.restore(data["value"]))
|
|
if "parents" in data:
|
|
instance.parents = pickler.restore(data["parents"])
|
|
|
|
instance.get_metadata().key = data[CONCEPT_ID][0]
|
|
instance.get_metadata().id = data[CONCEPT_ID][1]
|
|
instance.freeze_definition_hash()
|
|
return instance
|
|
|
|
|
|
class SheerkaHandler(ConceptHandler):
|
|
|
|
# def flatten(self, obj: BuiltinConcepts, data):
|
|
# return ConceptHandler().flatten()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 in ("who", "action", "action_context"):
|
|
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, self.sheerka, BuiltinConcepts.NOP, 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
|
|
|
|
|
|
class RuleContextHandler(BaseHandler):
|
|
|
|
def flatten(self, obj, data):
|
|
data[RULE_ID] = obj.id
|
|
data["name"] = obj.metadata.name
|
|
data["predicate"] = obj.metadata.predicate
|
|
data["action_type"] = obj.metadata.action_type
|
|
data["action"] = obj.metadata.action
|
|
return data
|
|
|
|
def new(self, data):
|
|
return Rule(data["action_type"], data["name"], data["predicate"], data["action"])
|
|
|
|
def restore(self, data, instance):
|
|
instance.metadata.id = data[RULE_ID]
|
|
return instance
|
|
|
|
|
|
class PythonNodeHandler(BaseHandler):
|
|
|
|
def flatten(self, obj, data):
|
|
pickler = self.context
|
|
|
|
data["source"] = obj.source
|
|
data["ast_str"] = obj.ast_str
|
|
data["objects"] = pickler.flatten(obj.objects)
|
|
return data
|
|
|
|
def new(self, data):
|
|
return PythonNode.__new__(PythonNode)
|
|
|
|
def restore(self, data, instance):
|
|
pickler = self.context
|
|
|
|
instance.__init__(data["source"], objects=pickler.restore(data["objects"]))
|
|
instance.ast_str = data["ast_str"]
|
|
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)
|
|
registry.register(Rule, RuleContextHandler, True)
|
|
registry.register(PythonNode, PythonNodeHandler, True)
|