import hashlib from enum import Enum import logging log = logging.getLogger(__name__) class ConceptParts(Enum): WHERE = "where" PRE = "pre" POST = "post" BODY = "body" class Concept: """ Default concept object A concept is a the base object of our universe Everything is a concept """ props_to_serialize = ("id", "is_builtin", "name", "where", "pre", "post", "body", "desc") def __init__(self, name=None, is_builtin=False, where=None, pre=None, post=None, body=None, desc=None, key=None): self.name = name self.is_builtin = is_builtin self.where = where # condition to recognize variables in name self.pre = pre # list of pre conditions before calling the main function self.post = post # list of post conditions after calling the main function self.body = body # main method, can also be the value of the concept self.desc = desc self.id = None self.key = key self.props = [] # list of Property for this concept self.functions = {} # list of helper functions self.codes = {} # cached ast for the where, pre, post and body parts def __repr__(self): return f"({self.id}){self.name}" def __eq__(self, other): if not isinstance(other, Concept): return False return self.name == other.name and \ self.where == other.where and \ self.pre == other.pre and \ self.post == other.post and \ self.body == other.body def __hash__(self): return hash(self.name) def get_key(self): return self.key def add_codes(self, codes): """ From a dict of <ConceptParts, AST> fill the codes :param codes: :return: """ possibles_codes = set(item.value for item in ConceptParts) if codes is None: return for key in codes: if key in possibles_codes: self.codes[ConceptParts(key)] = codes[key] def get_digest(self): """ Returns the digest of the event :return: hexa form of the sha256 """ return hashlib.sha256(f"Concept:{self.name}{self.pre}{self.post}{self.body}".encode("utf-8")).hexdigest() def to_dict(self): props_as_dict = dict((prop, getattr(self, prop)) for prop in self.props_to_serialize) props_as_dict["props"] = [(p.name, p.value) for p in self.props] return props_as_dict def from_dict(self, as_dict): for prop in self.props_to_serialize: if prop in as_dict: setattr(self, prop, as_dict[prop]) if "props" in as_dict: for n, v in as_dict["props"]: self.props.append(Property(n, v)) return self def update_from(self, other): for prop in self.props_to_serialize: setattr(self, prop, getattr(other, prop)) class ErrorConcept(Concept): def __init__(self, where=None, pre=None, post=None, body=None, desc=None): Concept.__init__(self, "error", is_builtin=True, where=where, pre=pre, post=post, body=body, desc=desc) def __repr__(self): return f"({self.id}){self.name} : {self.body}" class Property: """ Defines a behaviour of Concept """ def __init__(self, name, value): self.name = name self.value = value