Refactored to allow ConceptEvaluator
This commit is contained in:
+67
-48
@@ -8,6 +8,10 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ConceptParts(Enum):
|
||||
"""
|
||||
Helper class, Note quite sure that is it that useful
|
||||
I guess, I was learning nums with Python...
|
||||
"""
|
||||
WHERE = "where"
|
||||
PRE = "pre"
|
||||
POST = "post"
|
||||
@@ -20,21 +24,36 @@ class Concept:
|
||||
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")
|
||||
props_to_serialize = ("id", "is_builtin", "key", "name", "where", "pre", "post", "body", "desc", "obj")
|
||||
props_for_digest = ("is_builtin", "key", "name", "where", "pre", "post", "body", "desc")
|
||||
concept_parts = set(item.value for item in ConceptParts)
|
||||
|
||||
PROPERTY_PREFIX = "__var__"
|
||||
|
||||
def __init__(self, name=None, is_builtin=False, where=None, pre=None, post=None, body=None, desc=None, key=None):
|
||||
self.name = name
|
||||
def __init__(self, name=None,
|
||||
is_builtin=False,
|
||||
is_unique=False,
|
||||
key=None,
|
||||
where=None,
|
||||
pre=None,
|
||||
post=None,
|
||||
body=None,
|
||||
desc=None,
|
||||
obj=None):
|
||||
|
||||
self.name = str(name) if name else None
|
||||
self.is_builtin = is_builtin
|
||||
self.is_unique = is_unique
|
||||
self.key = str(key) if key else None # name od the concept, where prop are replaced. to ease search
|
||||
|
||||
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.id = None # unique identifier for a concept. The id will never be modified
|
||||
|
||||
self.obj = obj # main of principal property of the concept
|
||||
self.props = {} # list of Property for this concept
|
||||
self.functions = {} # list of helper functions
|
||||
|
||||
@@ -46,11 +65,19 @@ class Concept:
|
||||
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
|
||||
|
||||
# check the attributes
|
||||
for prop in self.props_to_serialize:
|
||||
if getattr(self, prop) != getattr(other, prop):
|
||||
print(prop)
|
||||
return False
|
||||
|
||||
# check the props (Concept variables)
|
||||
for var_name, p in self.props.items():
|
||||
if p != other.props[var_name]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
@@ -68,7 +95,7 @@ class Concept:
|
||||
:return:
|
||||
"""
|
||||
if self.key is not None:
|
||||
return self.key
|
||||
return self
|
||||
|
||||
if tokens is None:
|
||||
tokens = iter(Tokenizer(self.name))
|
||||
@@ -100,10 +127,11 @@ class Concept:
|
||||
So the values are kept in cache.
|
||||
|
||||
For concepts loaded from sdp, these ASTs must be created again
|
||||
TODO : Seems to be a service method. Can be put somewhere else
|
||||
:param codes:
|
||||
:return:
|
||||
"""
|
||||
possibles_codes = set(item.value for item in ConceptParts)
|
||||
possibles_codes = self.concept_parts
|
||||
if codes is None:
|
||||
return
|
||||
for key in codes:
|
||||
@@ -117,14 +145,17 @@ class Concept:
|
||||
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()
|
||||
return hashlib.sha256(f"Concept:{self.to_dict(self.props_for_digest)}".encode("utf-8")).hexdigest()
|
||||
|
||||
def to_dict(self):
|
||||
def to_dict(self, props_to_use=None):
|
||||
"""
|
||||
Returns a dict representing 'self'
|
||||
:return:
|
||||
"""
|
||||
props_as_dict = dict((prop, getattr(self, prop)) for prop in self.props_to_serialize)
|
||||
|
||||
props_to_use = props_to_use or self.props_to_serialize
|
||||
|
||||
props_as_dict = dict((prop, getattr(self, prop)) for prop in props_to_use)
|
||||
props_as_dict["props"] = [(p, self.props[p].value) for p in self.props]
|
||||
return props_as_dict
|
||||
|
||||
@@ -150,51 +181,30 @@ class Concept:
|
||||
:param other:
|
||||
:return:
|
||||
"""
|
||||
for prop in self.props_to_serialize:
|
||||
setattr(self, prop, getattr(other, prop))
|
||||
if other is None:
|
||||
return self
|
||||
|
||||
self.from_dict(other.to_dict())
|
||||
# for prop in self.props_to_serialize:
|
||||
# setattr(self, prop, getattr(other, prop))
|
||||
|
||||
return self
|
||||
|
||||
def set_prop(self, prop_name, prop_value):
|
||||
def set_prop(self, prop_name, prop_value=None):
|
||||
self.props[prop_name] = Property(prop_name, prop_value)
|
||||
return self
|
||||
|
||||
def set_prop_by_index(self, index, prop_value):
|
||||
prop_name = list(self.props.keys())[index]
|
||||
self.props[prop_name] = Property(prop_name, prop_value)
|
||||
|
||||
class ErrorConcept(Concept):
|
||||
NAME = "Error"
|
||||
|
||||
def __init__(self, where=None, pre=None, post=None, body=None, desc=None):
|
||||
Concept.__init__(self, self.NAME, is_builtin=True, where=where, pre=pre, post=post, body=body, desc=desc)
|
||||
self.key = self.NAME
|
||||
|
||||
def __repr__(self):
|
||||
return f"({self.id}){self.name}: {self.body}"
|
||||
|
||||
|
||||
class TooManySuccessConcept(Concept):
|
||||
NAME = "Too many successful items"
|
||||
|
||||
def __init__(self, items=None):
|
||||
super().__init__(self.NAME, body=items)
|
||||
self.key = self.NAME
|
||||
|
||||
|
||||
class ReturnValueConcept(Concept):
|
||||
NAME = "Return Value"
|
||||
|
||||
def __init__(self, return_value=None):
|
||||
super().__init__(self.NAME, body=return_value)
|
||||
self.key = self.NAME
|
||||
|
||||
def __repr__(self):
|
||||
return f"({self.id}){self.name}: {self.body}"
|
||||
return self
|
||||
|
||||
|
||||
class Property:
|
||||
"""
|
||||
Defines a behaviour of Concept
|
||||
Defines the variables of a concept
|
||||
It as its specific class, because from experience,
|
||||
property management is more complex than a key/value pair
|
||||
"""
|
||||
|
||||
def __init__(self, name, value):
|
||||
@@ -203,3 +213,12 @@ class Property:
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.name}={self.value}"
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, Property):
|
||||
return False
|
||||
|
||||
return self.name == other.name and self.value == other.value
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.name, self.value))
|
||||
|
||||
Reference in New Issue
Block a user