from enum import Enum from core.concept import Concept class BuiltinConcepts(Enum): """ List of builtin concepts that do no need any specific implementation Please note that the value of the enum is informal. It is not used in the system For example, the concept 'NODE' DOES NOT have the key, the id or whatever 200 The key if the name of the concept The id is a sequential number given just before the concept is saved in sdp The values of the enum is not used the code """ SHEERKA = "sheerka" BEFORE_PARSING = "before parsing" # activated before evaluation by the parsers PARSING = "parsing" # activated during the parsing. It contains the text to parse AFTER_PARSING = "after parsing" # after parsing BEFORE_EVALUATION = "before evaluation" # before evaluation EVALUATION = "evaluation" # activated when the parsing process seems to be finished AFTER_EVALUATION = "after evaluation" # activated when the parsing process seems to be finished BEFORE_RENDERING = "before rendering" # activate before the output is rendered RENDERING = "rendering" # rendering the response from sheerka AFTER_RENDERING = "after rendering" # rendering the response from sheerka USER_INPUT = "user input" # represent an input from an user SUCCESS = "success" ERROR = "error" UNKNOWN_CONCEPT = "unknown concept" # the request concept is not recognized RETURN_VALUE = "return value" # a value is returned CONCEPT_TOO_LONG = "concept too long" # concept cannot be processed by exactConcept parser NEW_CONCEPT = "new concept" # when a new concept is added UNKNOWN_PROPERTY = "unknown property" # when requesting for a unknown property PARSER_RESULT = "parser result" TOO_MANY_SUCCESS = "too many success" # when expecting a limited number of successful return value TOO_MANY_ERRORS = "too many errors" # when expecting a limited number of successful return value NOT_FOR_ME = "not for me" # a parser recognize that the entry is not meant for it IS_EMPTY = "is empty" # when a set is empty INVALID_RETURN_VALUE = "invalid return value" # the return value of an evaluator is not correct CONCEPT_ALREADY_DEFINED = "concept already defined" # when you try to add the same concept twice NOP = "no operation" # no operation concept. Does nothing CONCEPT_EVAL_ERROR = "concept evaluation error" # cannot evaluate a property or metadata of a concept ENUMERATION = "enum" # represents a list or a set LIST = "list" # represents a list CONCEPT_ALREADY_IN_SET = "concept already in set" EVALUATOR_PRE_PROCESS = "evaluator pre process" # used modify / tweak behaviour of evaluators CONCEPT_EVAL_REQUESTED = "concept eval requested" REDUCE_REQUESTED = "reduce requested" # remove meaningless error when possible NODE = "node" GENERIC_NODE = "generic node" IDENTIFIER_NODE = "identifier node" def __repr__(self): return "__" + self.name def __str__(self): return "__" + self.name BuiltinUnique = [ BuiltinConcepts.BEFORE_PARSING, BuiltinConcepts.PARSING, BuiltinConcepts.AFTER_PARSING, BuiltinConcepts.BEFORE_EVALUATION, BuiltinConcepts.EVALUATION, BuiltinConcepts.AFTER_EVALUATION, BuiltinConcepts.BEFORE_RENDERING, BuiltinConcepts.RENDERING, BuiltinConcepts.AFTER_RENDERING, BuiltinConcepts.SUCCESS, BuiltinConcepts.NOP, BuiltinConcepts.CONCEPT_EVAL_REQUESTED, BuiltinConcepts.REDUCE_REQUESTED, ] BuiltinErrors = [str(e) for e in { BuiltinConcepts.ERROR, BuiltinConcepts.UNKNOWN_CONCEPT, BuiltinConcepts.CONCEPT_TOO_LONG, BuiltinConcepts.UNKNOWN_PROPERTY, BuiltinConcepts.TOO_MANY_SUCCESS, BuiltinConcepts.TOO_MANY_ERRORS, BuiltinConcepts.INVALID_RETURN_VALUE, BuiltinConcepts.CONCEPT_ALREADY_DEFINED, BuiltinConcepts.CONCEPT_EVAL_ERROR, BuiltinConcepts.CONCEPT_ALREADY_IN_SET, }] """ Some concepts have a specific implementation It's mainly to ease the usage """ class UserInputConcept(Concept): def __init__(self, text=None, user_name=None): super().__init__(BuiltinConcepts.USER_INPUT, True, False, BuiltinConcepts.USER_INPUT, text) self.set_prop("user_name", user_name) @property def text(self): return self.body @property def user_name(self): return self.props["user_name"].value def __repr__(self): return f"({self.id}){self.name}: '{self.body}'" class ErrorConcept(Concept): def __init__(self, error=None): super().__init__(BuiltinConcepts.ERROR, True, False, BuiltinConcepts.ERROR, error) def __repr__(self): return f"({self.id}){self.name}: {self.body}" class ReturnValueConcept(Concept): """ This class represents the result of a data flow processing It's the main input for the evaluators """ def __init__(self, who=None, status=None, value=None, message=None, parents=None): super().__init__(BuiltinConcepts.RETURN_VALUE, True, False, BuiltinConcepts.RETURN_VALUE, value) self.set_prop("who", who) self.set_prop("status", status) self.set_prop("message", message) self.set_prop("parents", parents) @property def who(self): return self.props["who"].value @who.setter def who(self, value): self.set_prop("who", value) @property def status(self): return self.props["status"].value @status.setter def status(self, value): self.set_prop("status", value) @property def value(self): return self.body @value.setter def value(self, value): self.metadata.body = value @property def message(self): return self.props["message"].value @message.setter def message(self, value): self.set_prop("message", value) @property def parents(self): return self.props["parents"].value @parents.setter def parents(self, value): self.set_prop("parents", value) def __repr__(self): return f"ReturnValue(who={self.who}, status={self.status}, value={self.value}, message={self.message})" def __eq__(self, other): if not isinstance(other, ReturnValueConcept): return False return self.who == other.who and \ self.status == other.status and \ self.value == other.value and \ self.message == other.message def __hash__(self): if hasattr(self.value, "__iter__") and not isinstance(self.value, str): value_hash = hash(tuple(self.value)) else: value_hash = hash(self.value) return hash((self.who, self.status, value_hash)) class UnknownPropertyConcept(Concept): """ This error is raised when, during sheerka.new(), an unknown property is asked """ def __init__(self, property_name=None, concept=None): super().__init__(BuiltinConcepts.UNKNOWN_PROPERTY, True, False, BuiltinConcepts.UNKNOWN_PROPERTY, property_name) self.set_prop("concept", concept) def __repr__(self): return f"UnknownProperty(property={self.property_name}, concept={self.concept})" @property def concept(self): return self.props["concept"].value @property def property_name(self): return self.body class ParserResultConcept(Concept): """ Result of a parsing """ def __init__(self, parser=None, source=None, value=None, try_parsed=None): super().__init__(BuiltinConcepts.PARSER_RESULT, True, False, BuiltinConcepts.PARSER_RESULT, value) self.set_prop("parser", parser) self.set_prop("source", source) self.set_prop("try_parsed", try_parsed) # in case of error, what was found before the error def __repr__(self): text = f"ParserResult(parser={self.props['parser'].value}" source = self.props['source'].value text += f", source='{source}')" if source else f", body='{self.body}')" return text def __eq__(self, other): if not isinstance(other, ParserResultConcept): return False return self.source == other.source and \ self.parser == other.parser and \ self.body == other.body and \ self.try_parsed == other.try_parsed def __hash__(self): return hash(self.metadata.name) @property def value(self): return self.body @property def try_parsed(self): return self.props["try_parsed"].value @property def source(self): return self.props["source"].value @property def parser(self): return self.props["parser"].value class InvalidReturnValueConcept(Concept): """ Error returned when an evaluator is not correctly coded The accepted return value are ReturnValueConcept, list of ReturnValueConcept or None """ def __init__(self, return_value=None, evaluator=None): super().__init__( BuiltinConcepts.INVALID_RETURN_VALUE, True, False, BuiltinConcepts.INVALID_RETURN_VALUE, return_value) self.set_prop("evaluator", evaluator) class ConceptEvalError(Concept): def __init__(self, error=None, concept=None, property_name=None): super().__init__(BuiltinConcepts.CONCEPT_EVAL_ERROR, True, False, BuiltinConcepts.CONCEPT_EVAL_ERROR, error) self.set_prop("concept", concept) self.set_prop("property_name", property_name) def __repr__(self): return f"ConceptEvalError(error={self.error}, concept={self.concept}, property={self.property_name})" @property def error(self): return self.body @property def concept(self): return self.props["concept"].value @property def property_name(self): return self.props["property_name"].value class EnumerationConcept(Concept): def __init__(self, iteration=None): super().__init__(BuiltinConcepts.ENUMERATION, True, False, BuiltinConcepts.ENUMERATION, iteration) def __iter__(self): return iter(self.body) class ListConcept(Concept): def __init__(self, items=None): super().__init__(BuiltinConcepts.LIST, True, False, BuiltinConcepts.LIST, items or []) def append(self, obj): self.body.append(obj) def __len__(self): return len(self.body) def __getitem__(self, key): return self.body[key] def __setitem__(self, key, value): self.body[key] = value def __iter__(self): return iter(self.body) def __contains__(self, item): return item in self.body class ConceptAlreadyInSet(Concept): def __init__(self, concept=None, concept_set=None): super().__init__(BuiltinConcepts.CONCEPT_ALREADY_IN_SET, True, False, BuiltinConcepts.CONCEPT_ALREADY_IN_SET, concept) self.set_prop("concept_set", concept_set) def __repr__(self): return f"ConceptAlreadyInSet(concept={self.concept}, concept_set={self.concept_set})" @property def concept(self): return self.body @property def concept_set(self): return self.props["concept_set"].value