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)