Refactord Concept class to regroup all builtins properties into a ConceptMetadata class
This commit is contained in:
+18
-16
@@ -58,7 +58,7 @@ class SuccessConcept(Concept):
|
|||||||
|
|
||||||
class ErrorConcept(Concept):
|
class ErrorConcept(Concept):
|
||||||
def __init__(self, error=None):
|
def __init__(self, error=None):
|
||||||
super().__init__(BuiltinConcepts.ERROR, True, False, BuiltinConcepts.ERROR, body=error)
|
super().__init__(BuiltinConcepts.ERROR, True, False, BuiltinConcepts.ERROR, error)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"({self.id}){self.name}: {self.body}"
|
return f"({self.id}){self.name}: {self.body}"
|
||||||
@@ -71,10 +71,9 @@ class ReturnValueConcept(Concept):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, who=None, status=None, value=None, message=None, parents=None):
|
def __init__(self, who=None, status=None, value=None, message=None, parents=None):
|
||||||
super().__init__(BuiltinConcepts.RETURN_VALUE, True, False, BuiltinConcepts.RETURN_VALUE)
|
super().__init__(BuiltinConcepts.RETURN_VALUE, True, False, BuiltinConcepts.RETURN_VALUE, value)
|
||||||
self.set_prop("who", who)
|
self.set_prop("who", who)
|
||||||
self.set_prop("status", status)
|
self.set_prop("status", status)
|
||||||
self.body = value
|
|
||||||
self.set_prop("message", message)
|
self.set_prop("message", message)
|
||||||
self.set_prop("parents", parents)
|
self.set_prop("parents", parents)
|
||||||
|
|
||||||
@@ -100,7 +99,7 @@ class ReturnValueConcept(Concept):
|
|||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
def value(self, value):
|
def value(self, value):
|
||||||
self.body = value
|
self.metadata.body = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def message(self):
|
def message(self):
|
||||||
@@ -140,9 +139,8 @@ class UnknownPropertyConcept(Concept):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, property_name=None, concept=None):
|
def __init__(self, property_name=None, concept=None):
|
||||||
super().__init__(BuiltinConcepts.UNKNOWN_PROPERTY, True, False, BuiltinConcepts.UNKNOWN_PROPERTY)
|
super().__init__(BuiltinConcepts.UNKNOWN_PROPERTY, True, False, BuiltinConcepts.UNKNOWN_PROPERTY, property_name)
|
||||||
self.set_prop("concept", concept)
|
self.set_prop("concept", concept)
|
||||||
self.body = property_name
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"UnknownProperty(property={self.property_name}, concept={self.concept})"
|
return f"UnknownProperty(property={self.property_name}, concept={self.concept})"
|
||||||
@@ -162,11 +160,10 @@ class ParserResultConcept(Concept):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parser=None, source=None, value=None, try_parsed=None):
|
def __init__(self, parser=None, source=None, value=None, try_parsed=None):
|
||||||
super().__init__(BuiltinConcepts.PARSER_RESULT, True, False, BuiltinConcepts.PARSER_RESULT)
|
super().__init__(BuiltinConcepts.PARSER_RESULT, True, False, BuiltinConcepts.PARSER_RESULT, value)
|
||||||
self.set_prop("parser", parser)
|
self.set_prop("parser", parser)
|
||||||
self.set_prop("source", source)
|
self.set_prop("source", source)
|
||||||
self.set_prop("try_parsed", try_parsed) # in case of error, what was found before the error
|
self.set_prop("try_parsed", try_parsed) # in case of error, what was found before the error
|
||||||
self.body = value
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"ParserResult({self.body})"
|
return f"ParserResult({self.body})"
|
||||||
@@ -205,9 +202,13 @@ class InvalidReturnValueConcept(Concept):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, return_value=None, evaluator=None):
|
def __init__(self, return_value=None, evaluator=None):
|
||||||
super().__init__(BuiltinConcepts.INVALID_RETURN_VALUE, True, False, BuiltinConcepts.INVALID_RETURN_VALUE)
|
super().__init__(
|
||||||
|
BuiltinConcepts.INVALID_RETURN_VALUE,
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
BuiltinConcepts.INVALID_RETURN_VALUE,
|
||||||
|
return_value)
|
||||||
self.set_prop("evaluator", evaluator)
|
self.set_prop("evaluator", evaluator)
|
||||||
self.body = return_value
|
|
||||||
|
|
||||||
|
|
||||||
class BeforeParsingConcept(Concept):
|
class BeforeParsingConcept(Concept):
|
||||||
@@ -227,10 +228,13 @@ class AfterEvaluationConcept(Concept):
|
|||||||
|
|
||||||
class PropertyEvalError(Concept):
|
class PropertyEvalError(Concept):
|
||||||
def __init__(self, property_name=None, concept=None, error=None):
|
def __init__(self, property_name=None, concept=None, error=None):
|
||||||
super().__init__(BuiltinConcepts.PROPERTY_EVAL_ERROR, True, False, BuiltinConcepts.PROPERTY_EVAL_ERROR)
|
super().__init__(BuiltinConcepts.PROPERTY_EVAL_ERROR,
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
BuiltinConcepts.PROPERTY_EVAL_ERROR,
|
||||||
|
property_name)
|
||||||
self.set_prop("concept", concept)
|
self.set_prop("concept", concept)
|
||||||
self.set_prop("error", error)
|
self.set_prop("error", error)
|
||||||
self.body = property_name
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"PropertyEvalError(property={self.property_name}, concept={self.concept}), error={self.error})"
|
return f"PropertyEvalError(property={self.property_name}, concept={self.concept}), error={self.error})"
|
||||||
@@ -250,8 +254,7 @@ class PropertyEvalError(Concept):
|
|||||||
|
|
||||||
class EnumerationConcept(Concept):
|
class EnumerationConcept(Concept):
|
||||||
def __init__(self, iteration=None):
|
def __init__(self, iteration=None):
|
||||||
super().__init__(BuiltinConcepts.ENUMERATION, True, False, BuiltinConcepts.ENUMERATION)
|
super().__init__(BuiltinConcepts.ENUMERATION, True, False, BuiltinConcepts.ENUMERATION, iteration)
|
||||||
self.body = iteration
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self.body)
|
return iter(self.body)
|
||||||
@@ -259,8 +262,7 @@ class EnumerationConcept(Concept):
|
|||||||
|
|
||||||
class ListConcept(Concept):
|
class ListConcept(Concept):
|
||||||
def __init__(self, items=None):
|
def __init__(self, items=None):
|
||||||
super().__init__(BuiltinConcepts.LIST, True, False, BuiltinConcepts.LIST)
|
super().__init__(BuiltinConcepts.LIST, True, False, BuiltinConcepts.LIST, items or [])
|
||||||
self.body = items or []
|
|
||||||
|
|
||||||
def append(self, obj):
|
def append(self, obj):
|
||||||
self.body.append(obj)
|
self.body.append(obj)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ def expect_one(context, return_values):
|
|||||||
return sheerka.ret(
|
return sheerka.ret(
|
||||||
context.who,
|
context.who,
|
||||||
False,
|
False,
|
||||||
sheerka.new(BuiltinConcepts.IS_EMPTY, obj=return_values),
|
sheerka.new(BuiltinConcepts.IS_EMPTY, body=return_values),
|
||||||
parents=return_values)
|
parents=return_values)
|
||||||
|
|
||||||
successful_results = [item for item in return_values if item.status]
|
successful_results = [item for item in return_values if item.status]
|
||||||
@@ -77,14 +77,14 @@ def expect_one(context, return_values):
|
|||||||
return sheerka.ret(
|
return sheerka.ret(
|
||||||
context.who,
|
context.who,
|
||||||
False,
|
False,
|
||||||
sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS, obj=successful_results),
|
sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS, body=successful_results),
|
||||||
parents=return_values)
|
parents=return_values)
|
||||||
|
|
||||||
# only errors, i cannot help you
|
# only errors, i cannot help you
|
||||||
return sheerka.ret(
|
return sheerka.ret(
|
||||||
context.who,
|
context.who,
|
||||||
False,
|
False,
|
||||||
sheerka.new(BuiltinConcepts.TOO_MANY_ERRORS, obj=return_values),
|
sheerka.new(BuiltinConcepts.TOO_MANY_ERRORS, body=return_values),
|
||||||
parents=return_values)
|
parents=return_values)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+79
-39
@@ -1,4 +1,5 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -6,6 +7,14 @@ from core.tokenizer import Tokenizer, TokenKind
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PROPERTIES_FOR_DIGEST = ("name", "key",
|
||||||
|
"definition", "definition_type",
|
||||||
|
"is_builtin", "is_unique",
|
||||||
|
"where", "pre", "post", "body",
|
||||||
|
"desc")
|
||||||
|
PROPERTIES_TO_SERIALIZE = PROPERTIES_FOR_DIGEST + tuple(["id"])
|
||||||
|
VARIABLE_PREFIX = "__var__"
|
||||||
|
|
||||||
|
|
||||||
class ConceptParts(Enum):
|
class ConceptParts(Enum):
|
||||||
"""
|
"""
|
||||||
@@ -17,6 +26,26 @@ class ConceptParts(Enum):
|
|||||||
POST = "post"
|
POST = "post"
|
||||||
BODY = "body"
|
BODY = "body"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_parts():
|
||||||
|
return set(item.value for item in ConceptParts)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ConceptMetadata:
|
||||||
|
name: str
|
||||||
|
is_builtin: bool
|
||||||
|
is_unique: bool
|
||||||
|
key: str # name od the concept, where prop are replaced. to ease search
|
||||||
|
body: str # main method, can also be the value of the concept
|
||||||
|
where: str # condition to recognize variables in name
|
||||||
|
pre: str # list of pre conditions before calling the main function
|
||||||
|
post: str # list of post conditions after calling the main function
|
||||||
|
definition: str # regex used to define the concept
|
||||||
|
definition_type: str # definition can be done with something else than regex
|
||||||
|
desc: str # possible description for the concept
|
||||||
|
id: str # unique identifier for a concept. The id will never be modified (but the key can)
|
||||||
|
|
||||||
|
|
||||||
class Concept:
|
class Concept:
|
||||||
"""
|
"""
|
||||||
@@ -24,51 +53,49 @@ class Concept:
|
|||||||
A concept is a the base object of our universe
|
A concept is a the base object of our universe
|
||||||
Everything is a concept
|
Everything is a concept
|
||||||
"""
|
"""
|
||||||
props_for_digest = ("is_builtin", "is_unique", "key", "name", "where", "pre", "post", "body", "desc")
|
|
||||||
props_to_serialize = ("id", "is_builtin", "is_unique", "key", "name", "where", "pre", "post", "body", "desc")
|
|
||||||
concept_parts = set(item.value for item in ConceptParts)
|
|
||||||
|
|
||||||
PROPERTY_PREFIX = "__var__"
|
|
||||||
|
|
||||||
def __init__(self, name=None,
|
def __init__(self, name=None,
|
||||||
is_builtin=False,
|
is_builtin=False,
|
||||||
is_unique=False,
|
is_unique=False,
|
||||||
key=None,
|
key=None,
|
||||||
|
body=None,
|
||||||
where=None,
|
where=None,
|
||||||
pre=None,
|
pre=None,
|
||||||
post=None,
|
post=None,
|
||||||
body=None,
|
definition=None,
|
||||||
|
definition_type=None,
|
||||||
desc=None,
|
desc=None,
|
||||||
obj=None):
|
id=None):
|
||||||
|
|
||||||
self.name = str(name) if name else None
|
metadata = ConceptMetadata(
|
||||||
self.is_builtin = is_builtin
|
str(name) if name else None,
|
||||||
self.is_unique = is_unique
|
is_builtin,
|
||||||
self.key = str(key) if key else None # name od the concept, where prop are replaced. to ease search
|
is_unique,
|
||||||
|
str(key) if key else None,
|
||||||
|
body,
|
||||||
|
where,
|
||||||
|
pre,
|
||||||
|
post,
|
||||||
|
definition,
|
||||||
|
definition_type,
|
||||||
|
desc,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
|
||||||
self.where = where # condition to recognize variables in name
|
self.metadata = metadata
|
||||||
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 # 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.props = {} # list of Property for this concept
|
||||||
self.functions = {} # list of helper functions
|
self.cached_asts = {} # cached ast for the where, pre, post and body parts
|
||||||
|
|
||||||
self.codes = {} # cached ast for the where, pre, post and body parts
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"({self.id}){self.name}"
|
return f"({self.metadata.id}){self.metadata.name}"
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Concept):
|
if not isinstance(other, Concept):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# check the attributes
|
# check the attributes
|
||||||
for prop in self.props_to_serialize:
|
for prop in PROPERTIES_TO_SERIALIZE:
|
||||||
if getattr(self, prop) != getattr(other, prop):
|
if getattr(self.metadata, prop) != getattr(other.metadata, prop):
|
||||||
# print(prop) # use full to know which id does not match
|
# print(prop) # use full to know which id does not match
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -80,10 +107,19 @@ class Concept:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.name)
|
return hash(self.metadata.name)
|
||||||
|
|
||||||
def get_key(self):
|
@property
|
||||||
return self.key
|
def name(self):
|
||||||
|
return self.metadata.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
return self.metadata.id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self):
|
||||||
|
return self.metadata.key
|
||||||
|
|
||||||
def init_key(self, tokens=None):
|
def init_key(self, tokens=None):
|
||||||
"""
|
"""
|
||||||
@@ -94,11 +130,11 @@ class Concept:
|
|||||||
:param tokens:
|
:param tokens:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if self.key is not None:
|
if self.metadata.key is not None:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
if tokens is None:
|
if tokens is None:
|
||||||
tokens = iter(Tokenizer(self.name))
|
tokens = iter(Tokenizer(self.metadata.name))
|
||||||
|
|
||||||
variables = list(self.props.keys())
|
variables = list(self.props.keys())
|
||||||
|
|
||||||
@@ -112,14 +148,18 @@ class Concept:
|
|||||||
if not first:
|
if not first:
|
||||||
key += " "
|
key += " "
|
||||||
if variables is not None and token.value in variables:
|
if variables is not None and token.value in variables:
|
||||||
key += self.PROPERTY_PREFIX + str(variables.index(token.value))
|
key += VARIABLE_PREFIX + str(variables.index(token.value))
|
||||||
else:
|
else:
|
||||||
key += token.value[1:-1] if token.type == TokenKind.STRING else token.value
|
key += token.value[1:-1] if token.type == TokenKind.STRING else token.value
|
||||||
first = False
|
first = False
|
||||||
|
|
||||||
self.key = key
|
self.metadata.key = key
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def body(self):
|
||||||
|
return self.metadata.body
|
||||||
|
|
||||||
def add_codes(self, codes):
|
def add_codes(self, codes):
|
||||||
"""
|
"""
|
||||||
Gets the ASTs for 'where', 'pre', 'post' and 'body'
|
Gets the ASTs for 'where', 'pre', 'post' and 'body'
|
||||||
@@ -131,12 +171,12 @@ class Concept:
|
|||||||
:param codes:
|
:param codes:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
possibles_codes = self.concept_parts
|
possibles_codes = ConceptParts.get_parts()
|
||||||
if codes is None:
|
if codes is None:
|
||||||
return
|
return
|
||||||
for key in codes:
|
for key in codes:
|
||||||
if key in possibles_codes:
|
if key in possibles_codes:
|
||||||
self.codes[ConceptParts(key)] = codes[key]
|
self.cached_asts[ConceptParts(key)] = codes[key]
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@@ -145,7 +185,7 @@ class Concept:
|
|||||||
Returns the digest of the event
|
Returns the digest of the event
|
||||||
:return: hexa form of the sha256
|
:return: hexa form of the sha256
|
||||||
"""
|
"""
|
||||||
return hashlib.sha256(f"Concept:{self.to_dict(self.props_for_digest)}".encode("utf-8")).hexdigest()
|
return hashlib.sha256(f"Concept:{self.to_dict(PROPERTIES_FOR_DIGEST)}".encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
def to_dict(self, props_to_use=None):
|
def to_dict(self, props_to_use=None):
|
||||||
"""
|
"""
|
||||||
@@ -153,9 +193,9 @@ class Concept:
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
props_to_use = props_to_use or self.props_to_serialize
|
props_to_use = props_to_use or PROPERTIES_TO_SERIALIZE
|
||||||
|
|
||||||
props_as_dict = dict((prop, getattr(self, prop)) for prop in props_to_use)
|
props_as_dict = dict((prop, getattr(self.metadata, prop)) for prop in props_to_use)
|
||||||
props_as_dict["props"] = [(p, self.props[p].value) for p in self.props]
|
props_as_dict["props"] = [(p, self.props[p].value) for p in self.props]
|
||||||
return props_as_dict
|
return props_as_dict
|
||||||
|
|
||||||
@@ -165,9 +205,9 @@ class Concept:
|
|||||||
:param as_dict:
|
:param as_dict:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
for prop in self.props_to_serialize:
|
for prop in PROPERTIES_TO_SERIALIZE:
|
||||||
if prop in as_dict:
|
if prop in as_dict:
|
||||||
setattr(self, prop, as_dict[prop])
|
setattr(self.metadata, prop, as_dict[prop])
|
||||||
if "props" in as_dict:
|
if "props" in as_dict:
|
||||||
for n, v in as_dict["props"]:
|
for n, v in as_dict["props"]:
|
||||||
self.set_prop(n, v)
|
self.set_prop(n, v)
|
||||||
|
|||||||
+48
-51
@@ -1,6 +1,6 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from core.builtin_concepts import BuiltinConcepts, ErrorConcept, ReturnValueConcept
|
from core.builtin_concepts import BuiltinConcepts, ErrorConcept, ReturnValueConcept
|
||||||
from core.concept import Concept, ConceptParts
|
from core.concept import Concept, ConceptParts, PROPERTIES_FOR_DIGEST
|
||||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||||
from parsers.BaseParser import BaseParser
|
from parsers.BaseParser import BaseParser
|
||||||
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event, SheerkaDataProviderDuplicateKeyError
|
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event, SheerkaDataProviderDuplicateKeyError
|
||||||
@@ -55,7 +55,7 @@ class Sheerka(Concept):
|
|||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.skip_builtins_in_db = skip_builtins_in_db
|
self.skip_builtins_in_db = skip_builtins_in_db
|
||||||
|
|
||||||
def initialize(self, root_folder=None):
|
def initialize(self, root_folder: str = None):
|
||||||
"""
|
"""
|
||||||
Starting Sheerka
|
Starting Sheerka
|
||||||
Loads the current configuration
|
Loads the current configuration
|
||||||
@@ -80,18 +80,6 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
return ReturnValueConcept(self, True, self)
|
return ReturnValueConcept(self, True, self)
|
||||||
|
|
||||||
def set_id_if_needed(self, obj, is_builtin):
|
|
||||||
"""
|
|
||||||
Set the key for the concept if needed
|
|
||||||
:param obj:
|
|
||||||
:param is_builtin:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if obj.id is not None:
|
|
||||||
return
|
|
||||||
obj.id = self.sdp.get_next_key(self.BUILTIN_CONCEPTS_KEYS if is_builtin else self.USER_CONCEPTS_KEYS)
|
|
||||||
log.debug(f"Setting id '{obj.id}' to concept '{obj.name}'.")
|
|
||||||
|
|
||||||
def initialize_builtin_concepts(self):
|
def initialize_builtin_concepts(self):
|
||||||
"""
|
"""
|
||||||
Initializes the builtin concepts
|
Initializes the builtin concepts
|
||||||
@@ -107,11 +95,11 @@ class Sheerka(Concept):
|
|||||||
else builtins_classes[str(key)]() if str(key) in builtins_classes \
|
else builtins_classes[str(key)]() if str(key) in builtins_classes \
|
||||||
else Concept(key, True, False, key)
|
else Concept(key, True, False, key)
|
||||||
|
|
||||||
if not concept.is_unique and str(key) in builtins_classes:
|
if not concept.metadata.is_unique and str(key) in builtins_classes:
|
||||||
self.builtin_cache[key] = builtins_classes[str(key)]
|
self.builtin_cache[key] = builtins_classes[str(key)]
|
||||||
|
|
||||||
if not self.skip_builtins_in_db:
|
if not self.skip_builtins_in_db:
|
||||||
from_db = self.sdp.get_safe(self.CONCEPTS_ENTRY, concept.key)
|
from_db = self.sdp.get_safe(self.CONCEPTS_ENTRY, concept.metadata.key)
|
||||||
if from_db is None:
|
if from_db is None:
|
||||||
log.debug(f"'{concept.name}' concept is not found in db. Adding.")
|
log.debug(f"'{concept.name}' concept is not found in db. Adding.")
|
||||||
self.set_id_if_needed(concept, True)
|
self.set_id_if_needed(concept, True)
|
||||||
@@ -158,7 +146,7 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
logging.basicConfig(format=log_format, level=log_level)
|
logging.basicConfig(format=log_format, level=log_level)
|
||||||
|
|
||||||
def eval(self, text):
|
def eval(self, text: str):
|
||||||
"""
|
"""
|
||||||
Note to KSI: If you try to add execution context to this function,
|
Note to KSI: If you try to add execution context to this function,
|
||||||
You may end in an infinite loop
|
You may end in an infinite loop
|
||||||
@@ -294,7 +282,19 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
return return_values
|
return return_values
|
||||||
|
|
||||||
def create_new_concept(self, context, concept):
|
def set_id_if_needed(self, obj: Concept, is_builtin: bool):
|
||||||
|
"""
|
||||||
|
Set the key for the concept if needed
|
||||||
|
:param obj:
|
||||||
|
:param is_builtin:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if obj.metadata.id is not None:
|
||||||
|
return
|
||||||
|
obj.metadata.id = self.sdp.get_next_key(self.BUILTIN_CONCEPTS_KEYS if is_builtin else self.USER_CONCEPTS_KEYS)
|
||||||
|
log.debug(f"Setting id '{obj.metadata.id}' to concept '{obj.metadata.name}'.")
|
||||||
|
|
||||||
|
def create_new_concept(self, context, concept: Concept):
|
||||||
"""
|
"""
|
||||||
Adds a new concept to the system
|
Adds a new concept to the system
|
||||||
:param context:
|
:param context:
|
||||||
@@ -325,7 +325,7 @@ class Sheerka(Concept):
|
|||||||
ret = self.ret(self.create_new_concept.__name__, True, self.new(BuiltinConcepts.NEW_CONCEPT, body=concept))
|
ret = self.ret(self.create_new_concept.__name__, True, self.new(BuiltinConcepts.NEW_CONCEPT, body=concept))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def add_codes_to_concept(self, context, concept):
|
def initialize_concept_asts(self, context, concept: Concept):
|
||||||
"""
|
"""
|
||||||
Updates the codes of the newly created concept
|
Updates the codes of the newly created concept
|
||||||
Basically, it runs the parsers on all parts
|
Basically, it runs the parsers on all parts
|
||||||
@@ -334,16 +334,16 @@ class Sheerka(Concept):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
for part_key in ConceptParts:
|
for part_key in ConceptParts:
|
||||||
source = getattr(concept, part_key.value)
|
source = getattr(concept.metadata, part_key.value)
|
||||||
if source is None or not isinstance(source, str) or source == "":
|
if source is None or not isinstance(source, str) or source == "":
|
||||||
# the only sources that I am sure to parse are strings
|
# the only sources that I am sure to parse are strings
|
||||||
# I refuse empty strings for performance, I don't want to handle useless NOPConcepts
|
# I refuse empty strings for performance, I don't want to handle useless NOPConcepts
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
concept.codes[part_key] = self.parse(context, source)
|
concept.cached_asts[part_key] = self.parse(context, source)
|
||||||
|
|
||||||
for prop in concept.props:
|
for prop in concept.props:
|
||||||
concept.codes[prop] = self.parse(context, concept.props[prop].value)
|
concept.cached_asts[prop] = self.parse(context, concept.props[prop].value)
|
||||||
|
|
||||||
# updates the code of the reference when possible
|
# updates the code of the reference when possible
|
||||||
if concept.key in self.concepts_cache:
|
if concept.key in self.concepts_cache:
|
||||||
@@ -352,11 +352,20 @@ class Sheerka(Concept):
|
|||||||
# TODO : manage when there are multiple entries
|
# TODO : manage when there are multiple entries
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.concepts_cache[concept.key].codes = concept.codes
|
self.concepts_cache[concept.key].cached_asts = concept.cached_asts
|
||||||
|
|
||||||
def eval_concept(self, context, concept, properties_to_eval=None):
|
def eval_concept(self, context, concept: Concept, properties_to_eval=None):
|
||||||
if len(concept.codes) == 0:
|
"""
|
||||||
self.add_codes_to_concept(context, concept)
|
Evaluation a concept
|
||||||
|
It means that if the where clause is True, will evaluate the body
|
||||||
|
Also chc
|
||||||
|
:param context:
|
||||||
|
:param concept:
|
||||||
|
:param properties_to_eval:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if len(concept.cached_asts) == 0:
|
||||||
|
self.initialize_concept_asts(context, concept)
|
||||||
|
|
||||||
if properties_to_eval is None:
|
if properties_to_eval is None:
|
||||||
properties_to_eval = ["where", "pre", "post", "body", "props"]
|
properties_to_eval = ["where", "pre", "post", "body", "props"]
|
||||||
@@ -366,13 +375,13 @@ class Sheerka(Concept):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
part_key = ConceptParts(prop)
|
part_key = ConceptParts(prop)
|
||||||
if concept.codes[part_key] is None:
|
if concept.cached_asts[part_key] is None:
|
||||||
continue
|
continue
|
||||||
res = self.chain_process(context, concept.codes[part_key], concept_evaluation_steps)
|
res = self.chain_process(context, concept.cached_asts[part_key], concept_evaluation_steps)
|
||||||
res = core.builtin_helpers.expect_one(context, res)
|
res = core.builtin_helpers.expect_one(context, res)
|
||||||
setattr(concept, prop, res.value)
|
setattr(concept.metadata, prop, res.value)
|
||||||
|
|
||||||
def add_in_cache(self, concept):
|
def add_in_cache(self, concept: Concept):
|
||||||
"""
|
"""
|
||||||
Adds a concept template in cache.
|
Adds a concept template in cache.
|
||||||
The cache is used as a proxy before looking at sdp
|
The cache is used as a proxy before looking at sdp
|
||||||
@@ -416,7 +425,7 @@ class Sheerka(Concept):
|
|||||||
unknown_concept = Concept()
|
unknown_concept = Concept()
|
||||||
template = self.concepts_cache[str(BuiltinConcepts.UNKNOWN_CONCEPT)]
|
template = self.concepts_cache[str(BuiltinConcepts.UNKNOWN_CONCEPT)]
|
||||||
unknown_concept.update_from(template)
|
unknown_concept.update_from(template)
|
||||||
unknown_concept.body = concept_key
|
unknown_concept.metadata.body = concept_key
|
||||||
return unknown_concept
|
return unknown_concept
|
||||||
|
|
||||||
def new(self, concept_key, **kwargs):
|
def new(self, concept_key, **kwargs):
|
||||||
@@ -431,7 +440,7 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
def new_from_template(t, k, **kwargs_):
|
def new_from_template(t, k, **kwargs_):
|
||||||
# manage singleton
|
# manage singleton
|
||||||
if t.is_unique:
|
if t.metadata.is_unique:
|
||||||
return t
|
return t
|
||||||
|
|
||||||
# otherwise, create another instance
|
# otherwise, create another instance
|
||||||
@@ -442,6 +451,8 @@ class Sheerka(Concept):
|
|||||||
for k, v in kwargs_.items():
|
for k, v in kwargs_.items():
|
||||||
if k in concept.props:
|
if k in concept.props:
|
||||||
concept.set_prop(k, v)
|
concept.set_prop(k, v)
|
||||||
|
elif k in PROPERTIES_FOR_DIGEST:
|
||||||
|
setattr(concept.metadata, k, v)
|
||||||
elif hasattr(concept, k):
|
elif hasattr(concept, k):
|
||||||
setattr(concept, k, v)
|
setattr(concept, k, v)
|
||||||
else:
|
else:
|
||||||
@@ -462,7 +473,7 @@ class Sheerka(Concept):
|
|||||||
concepts = [new_from_template(t, concept_key, **kwargs) for t in template]
|
concepts = [new_from_template(t, concept_key, **kwargs) for t in template]
|
||||||
return self.new(BuiltinConcepts.ENUMERATION, body=concepts)
|
return self.new(BuiltinConcepts.ENUMERATION, body=concepts)
|
||||||
|
|
||||||
def ret(self, who, status, value, message=None, parents=None):
|
def ret(self, who: str, status: bool, value, message=None, parents=None):
|
||||||
"""
|
"""
|
||||||
Creates and returns a ReturnValue concept
|
Creates and returns a ReturnValue concept
|
||||||
:param who:
|
:param who:
|
||||||
@@ -569,32 +580,18 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
return sorted(res, key=lambda i: int(i.id))
|
return sorted(res, key=lambda i: int(i.id))
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
return f"I have access to Sheerka !"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_builtins_classes_as_dict():
|
def get_builtins_classes_as_dict():
|
||||||
res = {}
|
res = {}
|
||||||
for c in core.utils.get_classes("core.builtin_concepts"):
|
for c in core.utils.get_classes("core.builtin_concepts"):
|
||||||
if issubclass(c, Concept) and c != Concept:
|
if issubclass(c, Concept) and c != Concept:
|
||||||
res[c().key] = c
|
res[c().metadata.key] = c
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_builtin_parsers():
|
|
||||||
res = []
|
|
||||||
# modules = core.utils.get_module("parsers")
|
|
||||||
# for m in modules:
|
|
||||||
base_class = core.utils.get_class("parsers.BaseParser.BaseParser")
|
|
||||||
|
|
||||||
for c in core.utils.get_classes_recursive("parsers"):
|
|
||||||
# if issubclass(c, base_class) and c != base_class:
|
|
||||||
res.append(c)
|
|
||||||
|
|
||||||
return res
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def test():
|
|
||||||
return "I have access to Sheerka !"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ExecutionContext:
|
class ExecutionContext:
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class AddConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
|
|
||||||
# update the parts
|
# update the parts
|
||||||
source = self.get_source(part_ret_val)
|
source = self.get_source(part_ret_val)
|
||||||
setattr(concept, prop, source)
|
setattr(concept.metadata, prop, source)
|
||||||
|
|
||||||
# try to find what can be a property
|
# try to find what can be a property
|
||||||
for p in self.get_props(part_ret_val):
|
for p in self.get_props(part_ret_val):
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
# pre condition should already be validated by the parser.
|
# pre condition should already be validated by the parser.
|
||||||
# It's a mandatory condition for the concept before it can be recognized
|
# It's a mandatory condition for the concept before it can be recognized
|
||||||
|
|
||||||
if len(concept.codes) == 0:
|
if len(concept.cached_asts) == 0:
|
||||||
sheerka.add_codes_to_concept(context, concept)
|
sheerka.initialize_concept_asts(context, concept)
|
||||||
|
|
||||||
# TODO; check pre
|
# TODO; check pre
|
||||||
# if pre is not true, return Concept with a false value
|
# if pre is not true, return Concept with a false value
|
||||||
@@ -38,7 +38,7 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
# Evaluate the properties
|
# Evaluate the properties
|
||||||
for prop in concept.props:
|
for prop in concept.props:
|
||||||
sub_context = context.push(self.name, f"Evaluating property '{prop}'", concept)
|
sub_context = context.push(self.name, f"Evaluating property '{prop}'", concept)
|
||||||
res = self.evaluate_parsing(sheerka, sub_context, concept.codes[prop])
|
res = self.evaluate_parsing(sheerka, sub_context, concept.cached_asts[prop])
|
||||||
if res.status:
|
if res.status:
|
||||||
concept.set_prop(prop, res.value)
|
concept.set_prop(prop, res.value)
|
||||||
else:
|
else:
|
||||||
@@ -49,11 +49,11 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
parents=[return_value])
|
parents=[return_value])
|
||||||
|
|
||||||
# Returns the concept when no body
|
# Returns the concept when no body
|
||||||
if ConceptParts.BODY not in concept.codes:
|
if ConceptParts.BODY not in concept.cached_asts:
|
||||||
return sheerka.ret(self.name, True, concept, parents=[return_value])
|
return sheerka.ret(self.name, True, concept, parents=[return_value])
|
||||||
|
|
||||||
# Evaluate the body otherwise
|
# Evaluate the body otherwise
|
||||||
body = concept.codes[ConceptParts.BODY]
|
body = concept.cached_asts[ConceptParts.BODY]
|
||||||
if body is None:
|
if body is None:
|
||||||
raise NotImplementedError("Seems weird !")
|
raise NotImplementedError("Seems weird !")
|
||||||
|
|
||||||
|
|||||||
@@ -40,5 +40,5 @@ class DuplicateConceptEvaluator(AllReturnValuesEvaluator):
|
|||||||
return sheerka.ret(
|
return sheerka.ret(
|
||||||
self.name,
|
self.name,
|
||||||
False,
|
False,
|
||||||
sheerka.new(BuiltinConcepts.CONCEPT_ALREADY_DEFINED, obj=self.already_defined),
|
sheerka.new(BuiltinConcepts.CONCEPT_ALREADY_DEFINED, body=self.already_defined),
|
||||||
parents=return_values)
|
parents=return_values)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class TooManySuccessEvaluator(AllReturnValuesEvaluator):
|
|||||||
def eval(self, context, return_values):
|
def eval(self, context, return_values):
|
||||||
sheerka = context.sheerka
|
sheerka = context.sheerka
|
||||||
if not core.builtin_helpers.is_same_success(sheerka, self.success):
|
if not core.builtin_helpers.is_same_success(sheerka, self.success):
|
||||||
too_many_success = sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS, obj=self.success)
|
too_many_success = sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS, body=self.success)
|
||||||
return sheerka.ret(self.name, False, too_many_success, parents=return_values)
|
return sheerka.ret(self.name, False, too_many_success, parents=return_values)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||||
from parsers.BaseParser import BaseParser
|
from parsers.BaseParser import BaseParser
|
||||||
from core.tokenizer import Tokenizer, Keywords, TokenKind
|
from core.tokenizer import Tokenizer, Keywords, TokenKind
|
||||||
from core.concept import Concept
|
from core.concept import Concept, VARIABLE_PREFIX
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@@ -28,7 +28,7 @@ class ExactConceptParser(BaseParser):
|
|||||||
sheerka = context.sheerka
|
sheerka = context.sheerka
|
||||||
words = self.get_words(text)
|
words = self.get_words(text)
|
||||||
if len(words) > self.MAX_WORDS_SIZE:
|
if len(words) > self.MAX_WORDS_SIZE:
|
||||||
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, obj=text))
|
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, body=text))
|
||||||
|
|
||||||
recognized = False
|
recognized = False
|
||||||
for combination in self.combinations(words):
|
for combination in self.combinations(words):
|
||||||
@@ -44,8 +44,8 @@ class ExactConceptParser(BaseParser):
|
|||||||
for concept in concepts:
|
for concept in concepts:
|
||||||
# update the properties if needed
|
# update the properties if needed
|
||||||
for i, token in enumerate(combination):
|
for i, token in enumerate(combination):
|
||||||
if token.startswith(Concept.PROPERTY_PREFIX):
|
if token.startswith(VARIABLE_PREFIX):
|
||||||
index = int(token[len(Concept.PROPERTY_PREFIX):])
|
index = int(token[len(VARIABLE_PREFIX):])
|
||||||
concept.set_prop_by_index(index, words[i])
|
concept.set_prop_by_index(index, words[i])
|
||||||
res.append(ReturnValueConcept(self.name, True, concept))
|
res.append(ReturnValueConcept(self.name, True, concept))
|
||||||
log.debug(f"Recognized '{text}' as '{concept}'")
|
log.debug(f"Recognized '{text}' as '{concept}'")
|
||||||
@@ -55,7 +55,7 @@ class ExactConceptParser(BaseParser):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
log.debug(f"Failed to recognize {words}")
|
log.debug(f"Failed to recognize {words}")
|
||||||
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, obj=text))
|
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body=text))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_words(text):
|
def get_words(text):
|
||||||
@@ -111,7 +111,7 @@ class ExactConceptParser(BaseParser):
|
|||||||
for i in indices:
|
for i in indices:
|
||||||
value = pool[i]
|
value = pool[i]
|
||||||
if value not in vars:
|
if value not in vars:
|
||||||
vars[pool[i]] = f"{Concept.PROPERTY_PREFIX}{k}"
|
vars[pool[i]] = f"{VARIABLE_PREFIX}{k}"
|
||||||
k += 1
|
k += 1
|
||||||
|
|
||||||
# create tuple
|
# create tuple
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ def test_i_can_manage_unknown_concept():
|
|||||||
|
|
||||||
assert not res.status
|
assert not res.status
|
||||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||||
assert res.value.obj == "def concept hello world"
|
assert res.value.body == "def concept hello world"
|
||||||
|
|
||||||
|
|
||||||
def test_i_can_detect_concepts_too_long():
|
def test_i_can_detect_concepts_too_long():
|
||||||
@@ -108,7 +108,7 @@ def test_i_can_detect_concepts_too_long():
|
|||||||
|
|
||||||
assert not res.status
|
assert not res.status
|
||||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_TOO_LONG)
|
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_TOO_LONG)
|
||||||
assert res.value.obj == "a very very long concept that cannot be an unique one"
|
assert res.value.body == "a very very long concept that cannot be an unique one"
|
||||||
|
|
||||||
|
|
||||||
def test_i_can_detect_concept_from_tokens():
|
def test_i_can_detect_concept_from_tokens():
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ def test_i_can_use_expect_one_when_too_many_success():
|
|||||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||||
assert not res.status
|
assert not res.status
|
||||||
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_SUCCESS)
|
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||||
assert res.value.obj == items
|
assert res.value.body == items
|
||||||
assert res.parents == items
|
assert res.parents == items
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ def test_i_can_use_expect_when_only_errors_1():
|
|||||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||||
assert not res.status
|
assert not res.status
|
||||||
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_ERRORS)
|
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||||
assert res.value.obj == items
|
assert res.value.body == items
|
||||||
assert res.parents == items
|
assert res.parents == items
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ def test_i_can_use_expect_when_only_errors_2():
|
|||||||
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
res = core.builtin_helpers.expect_one(get_context(sheerka), items)
|
||||||
assert not res.status
|
assert not res.status
|
||||||
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_ERRORS)
|
assert sheerka.isinstance(res.value, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||||
assert res.value.obj == items
|
assert res.value.body == items
|
||||||
assert res.parents == items
|
assert res.parents == items
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def test_i_can_get_concept_key(name, variables, expected):
|
|||||||
concept.set_prop(v, None)
|
concept.set_prop(v, None)
|
||||||
|
|
||||||
concept.init_key()
|
concept.init_key()
|
||||||
assert concept.key == expected
|
assert concept.metadata.key == expected
|
||||||
|
|
||||||
|
|
||||||
def test_i_can_serialize():
|
def test_i_can_serialize():
|
||||||
|
|||||||
+18
-18
@@ -6,7 +6,7 @@ from os import path
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
|
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
|
||||||
from core.concept import Concept
|
from core.concept import Concept, PROPERTIES_TO_SERIALIZE
|
||||||
from core.sheerka import Sheerka, ExecutionContext
|
from core.sheerka import Sheerka, ExecutionContext
|
||||||
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
|
from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator
|
||||||
from sdp.sheerkaDataProvider import SheerkaDataProvider
|
from sdp.sheerkaDataProvider import SheerkaDataProvider
|
||||||
@@ -63,13 +63,13 @@ def test_builtin_concepts_are_initialized():
|
|||||||
def test_builtin_concepts_can_be_updated():
|
def test_builtin_concepts_can_be_updated():
|
||||||
sheerka = get_sheerka(root_folder, skip_builtins_in_db=False)
|
sheerka = get_sheerka(root_folder, skip_builtins_in_db=False)
|
||||||
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
||||||
loaded_sheerka.desc = "I have a description"
|
loaded_sheerka.metadata.desc = "I have a description"
|
||||||
sheerka.sdp.modify("Test", sheerka.CONCEPTS_ENTRY, loaded_sheerka.key, loaded_sheerka)
|
sheerka.sdp.modify("Test", sheerka.CONCEPTS_ENTRY, loaded_sheerka.key, loaded_sheerka)
|
||||||
|
|
||||||
sheerka = get_sheerka(root_folder)
|
sheerka = get_sheerka(root_folder)
|
||||||
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
||||||
|
|
||||||
assert loaded_sheerka.desc == "I have a description"
|
assert loaded_sheerka.metadata.desc == "I have a description"
|
||||||
|
|
||||||
|
|
||||||
def test_i_can_add_a_concept():
|
def test_i_can_add_a_concept():
|
||||||
@@ -82,8 +82,8 @@ def test_i_can_add_a_concept():
|
|||||||
assert sheerka.isinstance(res.value, BuiltinConcepts.NEW_CONCEPT)
|
assert sheerka.isinstance(res.value, BuiltinConcepts.NEW_CONCEPT)
|
||||||
|
|
||||||
concept_found = res.value.body
|
concept_found = res.value.body
|
||||||
for prop in Concept.props_to_serialize:
|
for prop in PROPERTIES_TO_SERIALIZE:
|
||||||
assert getattr(concept_found, prop) == getattr(concept, prop)
|
assert getattr(concept_found.metadata, prop) == getattr(concept.metadata, prop)
|
||||||
|
|
||||||
assert concept_found.key == "__var__0 + __var__1"
|
assert concept_found.key == "__var__0 + __var__1"
|
||||||
assert concept_found.id == "1001"
|
assert concept_found.id == "1001"
|
||||||
@@ -166,7 +166,7 @@ def test_i_can_get_list_of_concept_when_same_key_when_no_cache():
|
|||||||
sheerka = get_sheerka()
|
sheerka = get_sheerka()
|
||||||
concept1 = get_default_concept()
|
concept1 = get_default_concept()
|
||||||
concept2 = get_default_concept()
|
concept2 = get_default_concept()
|
||||||
concept2.body = "a+b"
|
concept2.metadata.body = "a+b"
|
||||||
|
|
||||||
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
||||||
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
||||||
@@ -185,7 +185,7 @@ def test_i_can_get_list_of_concept_when_same_key_when_cache():
|
|||||||
sheerka = get_sheerka()
|
sheerka = get_sheerka()
|
||||||
concept1 = get_default_concept()
|
concept1 = get_default_concept()
|
||||||
concept2 = get_default_concept()
|
concept2 = get_default_concept()
|
||||||
concept2.body = "a+b"
|
concept2.metadata.body = "a+b"
|
||||||
|
|
||||||
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
res1 = sheerka.create_new_concept(get_context(sheerka), concept1)
|
||||||
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
res2 = sheerka.create_new_concept(get_context(sheerka), concept2)
|
||||||
@@ -239,8 +239,8 @@ def test_i_can_instantiate_a_concept():
|
|||||||
new = sheerka.new(concept.key, a=10, b="value")
|
new = sheerka.new(concept.key, a=10, b="value")
|
||||||
|
|
||||||
assert sheerka.isinstance(new, concept)
|
assert sheerka.isinstance(new, concept)
|
||||||
for prop in Concept.props_to_serialize:
|
for prop in PROPERTIES_TO_SERIALIZE:
|
||||||
assert getattr(new, prop) == getattr(concept, prop)
|
assert getattr(new.metadata, prop) == getattr(concept.metadata, prop)
|
||||||
|
|
||||||
assert new.props["a"].value == 10
|
assert new.props["a"].value == 10
|
||||||
assert new.props["b"].value == "value"
|
assert new.props["b"].value == "value"
|
||||||
@@ -398,8 +398,8 @@ as:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
expected = get_default_concept()
|
expected = get_default_concept()
|
||||||
expected.id = "1001"
|
expected.metadata.id = "1001"
|
||||||
expected.desc = None
|
expected.metadata.desc = None
|
||||||
expected.init_key()
|
expected.init_key()
|
||||||
|
|
||||||
sheerka = get_sheerka()
|
sheerka = get_sheerka()
|
||||||
@@ -411,8 +411,8 @@ as:
|
|||||||
|
|
||||||
concept_saved = res[0].value.body
|
concept_saved = res[0].value.body
|
||||||
|
|
||||||
for prop in Concept.props_to_serialize:
|
for prop in PROPERTIES_TO_SERIALIZE:
|
||||||
assert getattr(concept_saved, prop) == getattr(expected, prop)
|
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||||
|
|
||||||
assert concept_saved.key in sheerka.concepts_cache
|
assert concept_saved.key in sheerka.concepts_cache
|
||||||
assert sheerka.sdp.io.exists(
|
assert sheerka.sdp.io.exists(
|
||||||
@@ -433,7 +433,7 @@ def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept()
|
|||||||
|
|
||||||
res = sheerka.eval("def concept a xx b as a plus b")
|
res = sheerka.eval("def concept a xx b as a plus b")
|
||||||
expected = Concept(name="a xx b", body="a plus b").set_prop("a").set_prop("b").init_key()
|
expected = Concept(name="a xx b", body="a plus b").set_prop("a").set_prop("b").init_key()
|
||||||
expected.id = "1001"
|
expected.metadata.id = "1001"
|
||||||
|
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
@@ -441,8 +441,8 @@ def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept()
|
|||||||
|
|
||||||
concept_saved = res[0].value.body
|
concept_saved = res[0].value.body
|
||||||
|
|
||||||
for prop in Concept.props_to_serialize:
|
for prop in PROPERTIES_TO_SERIALIZE:
|
||||||
assert getattr(concept_saved, prop) == getattr(expected, prop)
|
assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop)
|
||||||
|
|
||||||
assert concept_saved.key in sheerka.concepts_cache
|
assert concept_saved.key in sheerka.concepts_cache
|
||||||
assert sheerka.sdp.io.exists(
|
assert sheerka.sdp.io.exists(
|
||||||
@@ -537,7 +537,7 @@ def test_i_cannot_manage_duplicate_concepts_when_the_values_are_different():
|
|||||||
assert not res[0].status
|
assert not res[0].status
|
||||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.TOO_MANY_SUCCESS)
|
assert sheerka.isinstance(res[0].value, BuiltinConcepts.TOO_MANY_SUCCESS)
|
||||||
|
|
||||||
concepts = res[0].value.obj
|
concepts = res[0].value.body
|
||||||
assert len(concepts) == 2
|
assert len(concepts) == 2
|
||||||
sorted_values = sorted(concepts, key=lambda x: x.value)
|
sorted_values = sorted(concepts, key=lambda x: x.value)
|
||||||
assert sorted_values[0].value == "hello another value"
|
assert sorted_values[0].value == "hello another value"
|
||||||
@@ -554,7 +554,7 @@ def test_i_can_manage_concepts_with_the_same_key_when_values_are_the_same():
|
|||||||
res = sheerka.eval("hello 'foo'")
|
res = sheerka.eval("hello 'foo'")
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
assert res[0].value == "hello foo"
|
assert res[0].value == "hello foo"
|
||||||
assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME)
|
assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user