Added first implementation of concepts ambiguity resolution + Jenkins file test

This commit is contained in:
2020-07-15 18:29:43 +02:00
parent b768eaa95d
commit e84b394da2
42 changed files with 1130 additions and 313 deletions
+45 -11
View File
@@ -1,5 +1,6 @@
import inspect
import logging
from dataclasses import dataclass
import core.builtin_helpers
import core.utils
@@ -22,6 +23,15 @@ BASE_NODE_PARSER_CLASS = "parsers.BaseNodeParser.BaseNodeParser"
EXIT_COMMANDS = ("quit", "exit", "bye")
@dataclass
class SheerkaMethod:
"""
Wrapper to sheerka method, to indicate if it's safe to call
"""
method: object
has_side_effect: bool
class Sheerka(Concept):
"""
Main controller for the project
@@ -55,6 +65,7 @@ class Sheerka(Concept):
self.log.debug("Starting Sheerka.")
self.bnp = None # reference to the BaseNodeParser class (to compute first keyword token)
self.return_value_concept_id = None
# a concept can be instantiated
# ex: File is a concept, but File('foo.txt') is an instance
@@ -84,10 +95,10 @@ class Sheerka(Concept):
self.save_execution_context = True
self.methods_with_context = {"test_using_context"}
self.methods_with_context = {"test_using_context"} # only the names, the method is defined in sheerka_methods
self.sheerka_methods = {
"test": self.test,
"test_using_context": self.test_using_context
"test": SheerkaMethod(self.test, False),
"test_using_context": SheerkaMethod(self.test_using_context, False)
}
self.sheerka_pipeables = {}
@@ -119,10 +130,11 @@ class Sheerka(Concept):
def chicken_and_eggs(self):
return self.cache_manager.caches[self.CONCEPTS_GRAMMARS_ENTRY].cache
def bind_service_method(self, bound_method, as_name=None):
def bind_service_method(self, bound_method, has_side_effect, as_name=None):
"""
Bind service method to sheerka instance for ease of use ?
:param bound_method:
:param has_side_effect: False if the method is safe
:param as_name:
:return:
"""
@@ -132,18 +144,19 @@ class Sheerka(Concept):
signature = inspect.signature(bound_method)
if len(signature.parameters) > 0 and list(signature.parameters.keys())[0] == "context":
self.methods_with_context.add(as_name)
self.sheerka_methods[as_name] = bound_method
self.sheerka_methods[as_name] = SheerkaMethod(bound_method, has_side_effect)
setattr(self, as_name, bound_method)
def add_pipeable(self, func_name, function):
def add_pipeable(self, func_name, function, has_side_effect):
"""
Adds a function that can bu used with pipe '|'
:param func_name:
:param function:
:param has_side_effect:
:return:
"""
self.sheerka_pipeables[func_name] = function
self.sheerka_pipeables[func_name] = SheerkaMethod(function, has_side_effect)
def initialize(self, root_folder: str = None, save_execution_context=True):
"""
@@ -292,6 +305,10 @@ class Sheerka(Concept):
self.init_log.debug(f"'{concept.name}' concept is not found in db. Adding.")
self.set_id_if_needed(concept, True)
self.cache_manager.add_concept(concept)
if key == BuiltinConcepts.RETURN_VALUE:
self.return_value_concept_id = concept.id
else:
self.init_log.debug(f"Found concept '{from_db}' in db. Updating.")
concept.update_from(from_db)
@@ -595,6 +612,8 @@ class Sheerka(Concept):
:param concept_id:
:return:
"""
if concept_id is None:
return False
return self.cache_manager.has(self.CONCEPTS_BY_ID_ENTRY, concept_id)
def has_key(self, concept_key):
@@ -652,6 +671,7 @@ class Sheerka(Concept):
return self.new_from_template(template, concept_key, **kwargs)
def new_from_template(self, template, key, **kwargs):
# core.utils.my_debug(f"Created {template}, {key=}, {kwargs=}")
# manage singleton
if template.metadata.is_unique:
return template
@@ -677,7 +697,7 @@ class Sheerka(Concept):
return self.new(BuiltinConcepts.UNKNOWN_PROPERTY, body=k, concept=concept)
# TODO : add the concept to the list of known concepts (self.instances)
concept.metadata.is_evaluated = True # because we have manually set the variables
concept.metadata.is_evaluated = True # because we have manually set the variables
return concept
def ret(self, who: str, status: bool, value, message=None, parents=None):
@@ -690,13 +710,23 @@ class Sheerka(Concept):
:param parents:
:return:
"""
return self.new(
BuiltinConcepts.RETURN_VALUE,
# 1 second saved every twenty seconds in unit tests
return ReturnValueConcept(
who=who,
status=status,
value=value,
message=message,
parents=parents)
parents=parents,
concept_id=self.return_value_concept_id
)
# return self.new(
# BuiltinConcepts.RETURN_VALUE,
# who=who,
# status=status,
# value=value,
# message=message,
# parents=parents)
def objvalue(self, obj, reduce_simple_list=False):
if obj is None:
@@ -812,6 +842,10 @@ class Sheerka(Concept):
if isinstance(obj, ReturnValueConcept):
return obj.status
# other cases ?
# ...
# manage internal errors
if isinstance(obj, Concept) and obj.metadata.is_builtin and obj.key in BuiltinErrors:
return False
+5 -5
View File
@@ -14,11 +14,11 @@ class SheerkaAdmin(BaseService):
super().__init__(sheerka)
def initialize(self):
self.sheerka.bind_service_method(self.caches_names)
self.sheerka.bind_service_method(self.cache)
self.sheerka.bind_service_method(self.restore)
self.sheerka.bind_service_method(self.concepts)
self.sheerka.bind_service_method(self.last_created_concept)
self.sheerka.bind_service_method(self.caches_names, False)
self.sheerka.bind_service_method(self.cache, False)
self.sheerka.bind_service_method(self.restore, True)
self.sheerka.bind_service_method(self.concepts, False)
self.sheerka.bind_service_method(self.last_created_concept, False)
def caches_names(self):
"""
@@ -90,10 +90,10 @@ class SheerkaComparisonManager(BaseService):
cache = Cache()
self.sheerka.cache_manager.register_cache(self.RESOLVED_COMPARISON_ENTRY, cache, persist=False)
self.sheerka.bind_service_method(self.set_is_greater_than)
self.sheerka.bind_service_method(self.set_is_less_than)
self.sheerka.bind_service_method(self.get_partition)
self.sheerka.bind_service_method(self.get_concepts_weights)
self.sheerka.bind_service_method(self.set_is_greater_than, True)
self.sheerka.bind_service_method(self.set_is_less_than, True)
self.sheerka.bind_service_method(self.get_partition, False)
self.sheerka.bind_service_method(self.get_concepts_weights, False)
def set_is_greater_than(self, context, prop_name, concept_a, concept_b, comparison_context="#"):
"""
@@ -20,7 +20,7 @@ class SheerkaCreateNewConcept(BaseService):
self.bnp = core.utils.get_class(BASE_NODE_PARSER_CLASS) # BaseNodeParser
def initialize(self):
self.sheerka.bind_service_method(self.create_new_concept)
self.sheerka.bind_service_method(self.create_new_concept, True)
def create_new_concept(self, context, concept: Concept):
"""
+3 -3
View File
@@ -21,8 +21,8 @@ class SheerkaDump(BaseService):
super().__init__(sheerka)
def initialize(self):
self.sheerka.bind_service_method(self.dump_desc, "desc")
self.sheerka.bind_service_method(self.dump_sdp, "dump_sdp")
self.sheerka.bind_service_method(self.dump_desc, True, "desc") # because concept is evaluated
self.sheerka.bind_service_method(self.dump_sdp, False, "dump_sdp")
def dump_desc(self, *concept_names, eval=False):
first = True
@@ -42,7 +42,7 @@ class SheerkaDump(BaseService):
for c in concepts:
if eval:
evaluated = self.sheerka.evaluate_concept(context, c)
evaluated = self.sheerka.evaluate_concept(context, c, eval_body=eval)
value = evaluated.body if evaluated.key == c.key else evaluated
if not first:
@@ -2,6 +2,7 @@ from core.builtin_concepts import BuiltinConcepts
from core.builtin_helpers import expect_one, only_successful
from core.concept import Concept, DoNotResolve, ConceptParts, InfiniteRecursionResolved
from core.sheerka.services.sheerka_service import BaseService
from core.tokenizer import Tokenizer
from core.utils import unstr_concept
CONCEPT_EVALUATION_STEPS = [
@@ -17,16 +18,23 @@ class SheerkaEvaluateConcept(BaseService):
super().__init__(sheerka)
def initialize(self):
self.sheerka.bind_service_method(self.evaluate_concept)
self.sheerka.bind_service_method(self.evaluate_concept, True)
@staticmethod
def infinite_recursion_detected(context, concept):
"""
Browse the parents, looking for another evaluation of the same concept
:param context:
:param concept:
:return:
"""
if concept is None:
return False
parent = context.get_parent()
while parent is not None:
if parent.who == context.who and parent.obj == concept and parent.obj.compiled == concept.compiled:
if parent.who == context.who and parent.action == BuiltinConcepts.EVALUATING_CONCEPT and \
parent.obj == concept and parent.obj.compiled == concept.compiled:
return True
parent = parent.get_parent()
@@ -64,7 +72,7 @@ class SheerkaEvaluateConcept(BaseService):
parent = context
concepts_found = set()
while parent and parent.obj:
if parent.who == context.who and parent.desc == context.desc:
if parent.who == context.who and parent.action == BuiltinConcepts.EVALUATING_CONCEPT:
body = parent.obj.metadata.body
try:
return self.sheerka.ret(self.NAME, True, InfiniteRecursionResolved(eval(body)))
@@ -180,8 +188,7 @@ class SheerkaEvaluateConcept(BaseService):
path = get_path(context, current_prop)
desc = f"Evaluating {path} (concept={current_concept})"
context.log(desc, self.NAME)
with context.push(BuiltinConcepts.EVALUATING_CONCEPT,
with context.push(BuiltinConcepts.EVALUATING_ATTRIBUTE,
current_prop,
desc=desc,
obj=current_concept,
@@ -191,14 +198,14 @@ class SheerkaEvaluateConcept(BaseService):
sub_context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
if expect_success:
sub_context.local_hints.add(BuiltinConcepts.EVAL_SUCCESS_REQUESTED)
sub_context.local_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
# when it's a concept, evaluate it
if isinstance(to_resolve, Concept) and \
not context.sheerka.isinstance(to_resolve, BuiltinConcepts.RETURN_VALUE):
evaluated = self.evaluate_concept(sub_context, to_resolve)
sub_context.add_values(return_values=evaluated)
if evaluated.key == to_resolve.key:
if evaluated.key == to_resolve.key: # quicker (and dirtier) than sheerka.is_success()
return self.apply_ret(evaluated)
else:
error = evaluated
@@ -253,51 +260,78 @@ class SheerkaEvaluateConcept(BaseService):
return res
def evaluate_concept(self, context, concept: Concept):
def evaluate_concept(self, context, concept: Concept, eval_body=False, metadata=None):
"""
Evaluation a concept
It means that if the where clause is True, will evaluate the body
:param context:
:param concept:
:param eval_body:
:param metadata: list of metadata to evaluate ('pre', 'post'...)
:return: value of the evaluation or error
"""
if concept.metadata.is_evaluated:
return concept
self.initialize_concept_asts(context, concept)
# I cannot use cache because of concept like 'number'.
# They don't have variables, but their values change every time they are instanciated
# TODO: Need to find a way to cache despite of them
# need_body = eval_body or context.in_context(BuiltinConcepts.EVAL_BODY_REQUESTED)
# if need_body and len(concept.metadata.variables) == 0 and context.sheerka.has_id(concept.id):
# from_cache = context.sheerka.get_by_id(concept.id)
# if from_cache.metadata.is_evaluated:
# concept.set_value(ConceptParts.BODY, from_cache.body)
# concept.metadata.is_evaluated = True
# return concept
# to make sure of the order, it don't use ConceptParts.get_parts()
# variables must be evaluated first, body must be evaluated before where
all_metadata_to_eval = self.choose_metadata_to_eval(context, concept)
desc = f"Evaluating concept {concept}"
with context.push(BuiltinConcepts.EVALUATING_CONCEPT, concept, desc=desc, eval_body=eval_body) as sub_context:
for metadata_to_eval in all_metadata_to_eval:
if metadata_to_eval == "variables":
for var_name in (v for v in concept.variables() if v in concept.compiled):
prop_ast = concept.compiled[var_name]
if eval_body:
# ask for body evaluation
sub_context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
if isinstance(prop_ast, list):
# Do not send the current concept for the properties
resolved = self.resolve_list(context, prop_ast, var_name, None, True, False)
else:
# Do not send the current concept for the properties
resolved = self.resolve(context, prop_ast, var_name, None, True, False)
# auto evaluate commands
if context.sheerka.isa(concept, context.sheerka.new(BuiltinConcepts.COMMAND)):
sub_context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved):
resolved.set_value("concept", concept) # since current concept was not sent
return resolved
else:
concept.set_value(var_name, resolved)
else:
part_key = ConceptParts(metadata_to_eval)
self.initialize_concept_asts(sub_context, concept)
# do not evaluate where when the body is a set
# Indeed, the way that the where clause is expressed is not a valid python or concept code
if part_key == ConceptParts.WHERE and self.sheerka.isaset(context, concept.body):
continue
# to make sure of the order, it don't use ConceptParts.get_parts()
# variables must be evaluated first, body must be evaluated before where
all_metadata_to_eval = metadata or self.compute_metadata_to_eval(sub_context, concept)
for metadata_to_eval in all_metadata_to_eval:
if metadata_to_eval == "variables":
for var_name in (v for v in concept.variables() if v in concept.compiled):
prop_ast = concept.compiled[var_name]
if isinstance(prop_ast, list):
# Do not send the current concept for the properties
resolved = self.resolve_list(sub_context, prop_ast, var_name, None, True, False)
else:
# Do not send the current concept for the properties
resolved = self.resolve(sub_context, prop_ast, var_name, None, True, False)
if isinstance(resolved, Concept) and not sub_context.sheerka.is_success(resolved):
resolved.set_value("concept", concept) # since current concept was not sent
return resolved
else:
concept.set_value(var_name, resolved)
else:
part_key = ConceptParts(metadata_to_eval)
# do not evaluate where when the body is a set
# Indeed, the way that the where clause is expressed is not a valid python or concept code
if part_key == ConceptParts.WHERE and self.sheerka.isaset(sub_context, concept.body):
continue
if part_key not in concept.compiled or concept.compiled[part_key] is None:
continue
if part_key in concept.compiled and concept.compiled[part_key] is not None:
metadata_ast = concept.compiled[part_key]
# if part_key is PRE, POST or WHERE, the concept need to be evaluated
# if we want the predicates to be resolved => so force_eval = True
# otherwise no need to force
@@ -306,91 +340,111 @@ class SheerkaEvaluateConcept(BaseService):
# when resolving predicate (where or pre), we need to make sure that PythonEvaluator
# will try every possibilities before returning False
expect_success = part_key in (ConceptParts.WHERE, ConceptParts.PRE)
resolved = self.resolve(context,
# resolve
resolved = self.resolve(sub_context,
metadata_ast,
part_key,
concept,
force_concept_eval,
expect_success)
if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved):
# 'FATAL' error is detected, let's stop
if isinstance(resolved, Concept) and not sub_context.sheerka.is_success(resolved):
return resolved
else:
concept.set_value(part_key, self.get_infinite_recursion_resolution(resolved) or resolved)
#
# TODO : Validate the PRE condition
#
concept.set_value(part_key, self.get_infinite_recursion_resolution(resolved) or resolved)
# validate where clause
if ConceptParts.WHERE in concept.values:
where_value = concept.get_value(ConceptParts.WHERE)
if not (where_value is None or self.sheerka.objvalue(where_value)):
return self.sheerka.new(BuiltinConcepts.WHERE_CLAUSE_FAILED, body=concept)
# validate PRE and WHERE condition
if part_key in (ConceptParts.PRE, ConceptParts.WHERE) and not self.sheerka.objvalue(resolved):
return self.sheerka.new(BuiltinConcepts.CONDITION_FAILED,
body=getattr(concept.metadata, metadata_to_eval),
concept=concept,
prop=part_key)
#
# TODO : Validate the POST condition
#
#
# TODO : Validate the POST condition
#
concept.init_key() # only does it if needed
concept.metadata.is_evaluated = "body" in all_metadata_to_eval
concept.init_key() # Necessary for old unit tests. To remove someday
# update the cache for concepts with no variable
if len(concept.metadata.variables) == 0:
self.sheerka.cache_manager.put(self.sheerka.CONCEPTS_BY_ID_ENTRY, concept.id, concept)
if "body" in all_metadata_to_eval:
concept.metadata.is_evaluated = True
return concept
# # update the cache for concepts with no variables
# Cannot use cache. See the comment at the beginning of this method
# if len(concept.metadata.variables) == 0:
# self.sheerka.cache_manager.put(self.sheerka.CONCEPTS_BY_ID_ENTRY, concept.id, concept)
def choose_metadata_to_eval(self, context, concept):
if context.in_context(BuiltinConcepts.EVAL_BODY_REQUESTED):
return ["pre", "post", "variables", "body", "where", "ret"]
return concept
def compute_metadata_to_eval(self, context, concept):
to_eval = []
needed, variables, body = self.get_needed_metadata(concept, ConceptParts.PRE, True, True)
to_eval.extend(needed)
metadata = ["pre", "post", "ret"]
if context.in_context(BuiltinConcepts.EVAL_WHERE_REQUESTED) or concept.metadata.need_validation:
needed = self.needed_metadata(concept, ConceptParts.WHERE)
for e in needed:
if e not in metadata:
metadata.append(e)
if "where" not in metadata:
metadata.append("where")
# What are the cases where we do not need a validation ?
# see test_sheerka_non_reg::test_i_can_evaluate_bnf_concept_with_where_clause()
# res = sheerka.evaluate_user_input("foobar")
needed, v, b = self.get_needed_metadata(concept, ConceptParts.WHERE, not variables, not body)
variables |= v
body |= b
to_eval.extend(needed)
return metadata
needed, v, b = self.get_needed_metadata(concept, ConceptParts.RET, not variables, not body)
variables |= v
body |= b
to_eval.extend(needed)
def needed_metadata(self, concept, metadata):
needed, v, b = self.get_needed_metadata(concept, ConceptParts.POST, not variables, not body)
variables |= v
body |= b
to_eval.extend(needed)
if context.in_context(BuiltinConcepts.EVAL_BODY_REQUESTED):
if not variables:
to_eval.append('variables')
if not body:
to_eval.append("body")
return to_eval
@staticmethod
def get_needed_metadata(concept, concept_part, check_vars, check_body):
"""
Tries to find out if the evaluation of the body is necessary
It's a very basic approach that will need to be improved
Check if the concept_part has to be evaluated
It also checks if the variables and the body need to be evaluated prior to it
:param concept:
:param metadata:
:param concept_part:
:param check_vars:
:param check_body:
:return:
"""
ret = []
vars_needed = False
body_needed = False
if metadata not in concept.compiled:
return []
if concept_part in concept.compiled and concept.compiled[concept_part] is not None:
concept_part_source = getattr(concept.metadata, concept_part.value)
return_values = concept.compiled[metadata]
if not isinstance(return_values, list):
return []
assert concept_part_source is not None
needed = []
for return_value in return_values:
if not self.sheerka.isinstance(return_value, BuiltinConcepts.RETURN_VALUE):
continue
tokens = [t.str_value for t in Tokenizer(concept_part_source)]
if not return_value.status:
continue
if check_vars:
for var_name in (v[0] for v in concept.metadata.variables):
if var_name in tokens:
vars_needed = True
ret.append("variables")
break
if not self.sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT):
continue
if check_body and "self" in tokens:
body_needed = True
ret.append("body")
if not isinstance(return_value.body.source, str):
continue
ret.append(concept_part.value)
for var_name in (p[0] for p in concept.metadata.variables):
if var_name in return_value.body.source:
needed.append("variables")
break
if "self" in return_value.body.source:
needed.append("body")
return needed
return ret, vars_needed, body_needed
+3 -2
View File
@@ -144,7 +144,7 @@ class SheerkaExecute(BaseService):
self.pi_cache = Cache(default=lambda key: ParserInput(key), max_size=20)
def initialize(self):
self.sheerka.bind_service_method(self.execute)
self.sheerka.bind_service_method(self.execute, True)
self.sheerka.cache_manager.register_cache(self.PARSERS_INPUTS_ENTRY, self.pi_cache, False)
@@ -362,7 +362,8 @@ class SheerkaExecute(BaseService):
if not isinstance(results, list):
results = [results]
for result in results:
evaluated_items.append(result)
if result.body:
evaluated_items.append(result)
to_delete.extend(result.parents)
sub_context.add_values(return_values=results)
else:
+2 -2
View File
@@ -96,9 +96,9 @@ class SheerkaFilter(BaseService):
for k, v in SheerkaFilter.__dict__.items():
if k.startswith("pipe_"):
if isinstance(v, staticmethod):
self.sheerka.add_pipeable(k[5:], v.__func__)
self.sheerka.add_pipeable(k[5:], v.__func__, True)
else:
self.sheerka.add_pipeable(k[5:], v.__get__(self, self.__class__))
self.sheerka.add_pipeable(k[5:], v.__get__(self, self.__class__), True)
self.sheerka.cache_manager.register_cache(self.PREDICATES_ENTRY, self.cache, False, False)
@@ -57,7 +57,7 @@ class SheerkaHistoryManager(BaseService):
super().__init__(sheerka)
def initialize(self):
self.sheerka.bind_service_method(self.history)
self.sheerka.bind_service_method(self.history, False)
def history(self, depth=10, start=0):
"""
@@ -10,7 +10,7 @@ class SheerkaModifyConcept(BaseService):
super().__init__(sheerka)
def initialize(self):
self.sheerka.bind_service_method(self.modify_concept)
self.sheerka.bind_service_method(self.modify_concept, True)
def modify_concept(self, context, concept):
old_version = self.sheerka.get_by_id(concept.id)
@@ -10,10 +10,10 @@ class SheerkaResultConcept(BaseService):
self.page_size = page_size
def initialize(self):
self.sheerka.bind_service_method(self.get_results_by_digest)
self.sheerka.bind_service_method(self.get_results_by_command)
self.sheerka.bind_service_method(self.get_last_results)
self.sheerka.bind_service_method(self.get_results)
self.sheerka.bind_service_method(self.get_results_by_digest, True) # digest is recorded
self.sheerka.bind_service_method(self.get_results_by_command, True) # digest is recorded
self.sheerka.bind_service_method(self.get_last_results, True) # digest is recorded
self.sheerka.bind_service_method(self.get_results, False)
def get_results_by_digest(self, context, digest, record_digest=True):
"""
@@ -13,7 +13,7 @@ GROUP_PREFIX = 'All_'
class SheerkaSetsManager(BaseService):
NAME = "SetsManager"
CONCEPTS_GROUPS_ENTRY = "SetsManager:Concepts_Groups"
CONCEPTS_IN_GROUPS_ENTRY = "SetsManager:Concepts_In_Groups" # cache for get_set_elements()
CONCEPTS_IN_GROUPS_ENTRY = "SetsManager:Concepts_In_Groups" # cache for get_set_elements()
def __init__(self, sheerka):
super().__init__(sheerka)
@@ -21,12 +21,12 @@ class SheerkaSetsManager(BaseService):
self.concepts_in_set = Cache()
def initialize(self):
self.sheerka.bind_service_method(self.set_isa)
self.sheerka.bind_service_method(self.get_set_elements)
self.sheerka.bind_service_method(self.add_concept_to_set)
self.sheerka.bind_service_method(self.isinset)
self.sheerka.bind_service_method(self.isa)
self.sheerka.bind_service_method(self.isaset)
self.sheerka.bind_service_method(self.set_isa, True)
self.sheerka.bind_service_method(self.get_set_elements, True) # concepts are evaluated
self.sheerka.bind_service_method(self.add_concept_to_set, True)
self.sheerka.bind_service_method(self.isinset, False)
self.sheerka.bind_service_method(self.isa, False)
self.sheerka.bind_service_method(self.isaset, True) # concept is evaluated, need to change the code
self.sheerka.cache_manager.register_cache(self.CONCEPTS_GROUPS_ENTRY, self.sets)
self.sheerka.cache_manager.register_cache(self.CONCEPTS_IN_GROUPS_ENTRY, self.concepts_in_set, persist=False)
@@ -49,6 +49,8 @@ class SheerkaSetsManager(BaseService):
False,
self.sheerka.new(BuiltinConcepts.CONCEPT_ALREADY_IN_SET, body=concept, concept_set=concept_set))
# KSI 20200709 add the concept, not its 'id' or 'key'
# It will allow conditions handling if concept set has its WHERE or PRE set to something
concept.add_prop(BuiltinConcepts.ISA, concept_set)
res = self.sheerka.modify_concept(context, concept)
@@ -141,7 +143,7 @@ class SheerkaSetsManager(BaseService):
if sub_concept.metadata.where:
new_condition = self._validate_where_clause(sub_concept)
if not new_condition:
return self.sheerka.new(BuiltinConcepts.WHERE_CLAUSE_FAILED, body=sub_concept)
return self.sheerka.new(BuiltinConcepts.CONDITION_FAILED, body=sub_concept)
# This methods sucks, but I don't have enough tools (like proper AST manipulation functions)
# to do it properly now. It will be enhanced later
@@ -206,7 +208,7 @@ class SheerkaSetsManager(BaseService):
if not (isinstance(concept, Concept) and concept.id):
return False
# KSI 29062020
# KSI 20200629
# To resolve infinite recursion between group concepts and BNF concepts
if concept.metadata.definition_type == DEFINITION_TYPE_BNF:
return False
@@ -27,11 +27,11 @@ class SheerkaVariableManager(BaseService):
super().__init__(sheerka)
def initialize(self):
self.sheerka.bind_service_method(self.record)
self.sheerka.bind_service_method(self.load)
self.sheerka.bind_service_method(self.delete)
self.sheerka.bind_service_method(self.set)
self.sheerka.bind_service_method(self.get)
self.sheerka.bind_service_method(self.record, True)
self.sheerka.bind_service_method(self.load, False)
self.sheerka.bind_service_method(self.delete, True)
self.sheerka.bind_service_method(self.set, True)
self.sheerka.bind_service_method(self.get, False)
cache = Cache(default=lambda k: self.sheerka.sdp.get(self.VARIABLES_ENTRY, k))
self.sheerka.cache_manager.register_cache(self.VARIABLES_ENTRY, cache, True, True)