import dataclasses from enum import Enum from core.concept import Concept, PROPERTIES_TO_SERIALIZE from core.sheerka import ExecutionContext from core.tokenizer import Token from evaluators.BaseEvaluator import BaseEvaluator from parsers.BaseParser import BaseParser, Node from parsers.BnfParser import BnfParser from parsers.ConceptLexerParser import UnrecognizedTokensNode, ParsingExpression from parsers.PythonParser import PythonNode from sdp.sheerkaDataProvider import Event OBJ_TYPE_KEY = "__type__" OBJ_ID_KEY = "__id__" OBJ_NAME_KEY = "__name__" default_concept = Concept() class SheerkaTransformType(Enum): Concept = 1 Reference = 2 ExecutionContext = 3 Event = 4 Node = 5 Exception = 6 def __repr__(self): return self.__class__.__name__ + "." + self.name class SheerkaTransform: def __init__(self, sheerka): self.ids = {} self.sheerka = sheerka self.id_count = -1 def to_dict(self, obj): if isinstance(obj, (Concept, ExecutionContext, Event)): exists, _id = self.exist(obj) if exists: return { OBJ_TYPE_KEY: SheerkaTransformType.Reference, OBJ_ID_KEY: _id } else: self.id_count = self.id_count + 1 self.ids[obj] = self.id_count if isinstance(obj, Concept): return self.concept_to_dict(obj) elif isinstance(obj, ExecutionContext): return self.execution_context_to_dict(obj) elif isinstance(obj, Event): return { OBJ_TYPE_KEY: SheerkaTransformType.Event, OBJ_ID_KEY: self.id_count, 'digest': obj.get_digest()} elif isinstance(obj, (BaseParser, BaseEvaluator, BnfParser)): return obj.name elif isinstance(obj, Token): return obj.__dict__ elif isinstance(obj, PythonNode): return { OBJ_TYPE_KEY: SheerkaTransformType.Node, OBJ_NAME_KEY: "PythonNode", 'source': obj.source, 'ast_': obj.get_dump(obj.ast_) } elif isinstance(obj, Node): to_dict = { OBJ_TYPE_KEY: SheerkaTransformType.Node, OBJ_NAME_KEY: obj.__class__.__name__, } for k, v in obj.__dict__.items(): to_dict[k] = self.to_dict(v) return to_dict elif isinstance(obj, Exception): to_dict = { OBJ_TYPE_KEY: SheerkaTransformType.Exception, OBJ_NAME_KEY: obj.__class__.__name__, } for k, v in obj.__dict__.items(): to_dict[k] = self.to_dict(v) return to_dict elif isinstance(obj, ParsingExpression): return obj.__repr__() elif isinstance(obj, dict): return dict((str(k) if isinstance(k, Concept) else k, self.to_dict(v)) for k, v in obj.items()) elif hasattr(obj, "__iter__") and not isinstance(obj, str): return list(self.to_dict(o) for o in obj) else: return obj def concept_to_dict(self, obj: Concept): to_dict = { OBJ_TYPE_KEY: SheerkaTransformType.Concept, OBJ_ID_KEY: self.id_count, } if obj.id: ref = self.sheerka.get(obj.key, obj.id) to_dict["id"] = obj.id else: ref = default_concept # transform metadata for prop in PROPERTIES_TO_SERIALIZE: value = getattr(obj.metadata, prop) ref_value = getattr(ref.metadata, prop) if value != ref_value: to_dict["meta." + prop] = self.to_dict(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: to_dict[metadata.value] = self.to_dict(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 to_dict: to_dict["props"] = [] to_dict["props"].append((prop, self.to_dict(value))) return to_dict def execution_context_to_dict(self, obj: ExecutionContext): to_dict = { OBJ_TYPE_KEY: SheerkaTransformType.ExecutionContext, OBJ_ID_KEY: self.id_count } for property_name in obj.__dict__: if property_name == "sheerka": continue to_dict[property_name] = self.to_dict(getattr(obj, property_name)) return to_dict def exist(self, obj): for k, v in self.ids.items(): if id(k) == id(obj) or k == obj: return True, v return False, None