162 lines
4.9 KiB
Python
162 lines
4.9 KiB
Python
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
|