From ef31a4807d036f2a3bb5373aa2d29c7195a2aac2 Mon Sep 17 00:00:00 2001 From: Kodjo Sossouvi Date: Thu, 27 Feb 2020 10:48:45 +0100 Subject: [PATCH] Concepts bodies are now evaluated on demand --- _concepts.txt | 9 +- src/core/builtin_concepts.py | 1 + src/core/builtin_helpers.py | 44 +++- src/core/sheerka/ExecutionContext.py | 5 +- .../Services/SheerkaEvaluateConcept.py | 86 ++++++-- src/core/sheerka/Services/SheerkaExecute.py | 5 + .../sheerka/Services/SheerkaSetsManager.py | 6 +- src/core/sheerka/Sheerka.py | 27 +-- src/core/sheerka_logger.py | 3 +- src/evaluators/ConceptEvaluator.py | 17 +- src/evaluators/EvalEvaluator.py | 4 +- src/evaluators/MutipleSameSuccessEvaluator.py | 2 +- src/evaluators/PrepareEvalEvaluator.py | 2 +- src/evaluators/PythonEvaluator.py | 2 +- src/evaluators/TooManySuccessEvaluator.py | 2 +- tests/core/test_ExecutionContext.py | 2 + tests/core/test_SheerkaEvaluateConcept.py | 84 ++++---- tests/core/test_SheerkaSetsManager.py | 5 +- tests/core/test_sheerka_call_evaluators.py | 69 ++++++ .../test_AddConceptInSetEvaluator.py | 25 +++ tests/evaluators/test_ConceptEvaluator.py | 7 + tests/evaluators/test_EvalEvaluator.py | 24 +-- tests/evaluators/test_PrepareEvalEvaluator.py | 2 +- tests/non_reg/test_sheerka_non_reg.py | 201 ++++++++++++------ .../test_ConceptsWithConceptsParser.py | 6 +- 25 files changed, 468 insertions(+), 172 deletions(-) diff --git a/_concepts.txt b/_concepts.txt index a60879f..420d0df 100644 --- a/_concepts.txt +++ b/_concepts.txt @@ -40,6 +40,13 @@ eighteen isa number nineteen isa number twenty isa number def concept twenties from bnf twenty number where number < 10 as twenty + number +twenties isa number def concept thirty as 30 +def concept thirties from bnf thirty number where number < 10 as thirty + number +thirties isa number def concept forty as 40 - +def concept forties from bnf forty number where number < 10 as forty + number +forties isa number +def concept fifty as 50 +def concept fifties from bnf fifty number where number < 10 as fifty + number +fifties isa number \ No newline at end of file diff --git a/src/core/builtin_concepts.py b/src/core/builtin_concepts.py index 9415559..d400ec5 100644 --- a/src/core/builtin_concepts.py +++ b/src/core/builtin_concepts.py @@ -53,6 +53,7 @@ class BuiltinConcepts(Enum): WHERE_CLAUSE_FAILED = "where clause failed" # failed to validate where clause during evaluation CHICKEN_AND_EGG = "chicken and egg" # infinite recursion when declaring concept ISA = "is a" # builtin concept to express that a concept is an instance of another one + CONCEPT_VALUE_REQUESTED = "concept value requested" # returns the body of the concept instead of the concept itself NODE = "node" GENERIC_NODE = "generic node" diff --git a/src/core/builtin_helpers.py b/src/core/builtin_helpers.py index 8054720..ab2dadd 100644 --- a/src/core/builtin_helpers.py +++ b/src/core/builtin_helpers.py @@ -5,12 +5,13 @@ import core.ast.nodes from core.ast.nodes import CallNodeConcept, GenericNodeConcept from core.ast.visitors import UnreferencedNamesVisitor from core.builtin_concepts import BuiltinConcepts +from core.concept import Concept -def is_same_success(sheerka, return_values): +def is_same_success(context, return_values): """ Returns True if all returns values are successful and have the same value - :param sheerka: + :param context: :param return_values: :return: """ @@ -19,13 +20,27 @@ def is_same_success(sheerka, return_values): if not return_values[0].status: return False - reference = sheerka.value(return_values[0].value) + if isinstance(return_values[0].body, Concept): + evaluated = context.sheerka.evaluate_concept(context, return_values[0].body, True) + if evaluated.key != return_values[0].body.key: + return False + reference = context.sheerka.value(evaluated) + else: + reference = context.sheerka.value(return_values[0]) for return_value in return_values[1:]: if not return_value.status: return False - actual = sheerka.value(return_value.value) + if isinstance(return_value.body, Concept): + evaluated = context.sheerka.evaluate_concept(context, return_value.body, True) + if evaluated.key != return_value.body.key: + return False + + actual = context.sheerka.value(evaluated) + else: + actual = context.sheerka.value(return_value) + if actual != reference: return False @@ -67,7 +82,7 @@ def expect_one(context, return_values): # too many winners, which one to choose ? if number_of_successful > 1: - if is_same_success(sheerka, successful_results): + if is_same_success(context, successful_results): return sheerka.ret( context.who, True, @@ -218,3 +233,22 @@ def _extract_predicates(sheerka, node, variables_to_include, variables_to_exclud predicates.append(res) return predicates + + +def add_to_ret_val(sheerka, context, return_values, concept_key): + concept = sheerka.new(concept_key) + ret_val = sheerka.ret(context.who, True, concept) + return_values.append(ret_val) + return return_values + + +def remove_from_ret_val(sheerka, return_values, concept_key): + to_remove = [] + for ret_val in return_values: + if ret_val.status and sheerka.isinstance(ret_val.body, concept_key): + to_remove.append(ret_val) + + for item in to_remove: + return_values.remove(item) + + return return_values diff --git a/src/core/sheerka/ExecutionContext.py b/src/core/sheerka/ExecutionContext.py index c83d145..f8aeb29 100644 --- a/src/core/sheerka/ExecutionContext.py +++ b/src/core/sheerka/ExecutionContext.py @@ -60,6 +60,7 @@ class ExecutionContext: self.children = [] self.preprocess = None self.logger = logger + self.extra_info = [] self.inputs = {} # what was the parameters of the execution context self.values = {} # what was produced by the execution context @@ -210,11 +211,11 @@ class ExecutionContext: self.sheerka, desc, logger, - **_kwargs, - ) + **_kwargs) new._parent = self new._tab = self._tab + " " * DEBUG_TAB_SIZE new.preprocess = self.preprocess + new.extra_info.extend(self.extra_info) self.children.append(new) return new diff --git a/src/core/sheerka/Services/SheerkaEvaluateConcept.py b/src/core/sheerka/Services/SheerkaEvaluateConcept.py index bf59a55..b023224 100644 --- a/src/core/sheerka/Services/SheerkaEvaluateConcept.py +++ b/src/core/sheerka/Services/SheerkaEvaluateConcept.py @@ -1,6 +1,6 @@ from core.builtin_concepts import BuiltinConcepts from core.concept import Concept, DoNotResolve, ConceptParts, InfiniteRecursionResolved -import core.builtin_helpers +from core.builtin_helpers import add_to_ret_val, remove_from_ret_val, expect_one CONCEPT_EVALUATION_STEPS = [ BuiltinConcepts.BEFORE_EVALUATION, @@ -118,7 +118,7 @@ class SheerkaEvaluateConcept: else: self.sheerka.cache_by_key[concept.key].compiled = concept.compiled - def resolve(self, context, to_resolve, current_prop, current_concept): + def resolve(self, context, to_resolve, current_prop, current_concept, evaluate_body): if isinstance(to_resolve, DoNotResolve): return to_resolve.value @@ -137,7 +137,7 @@ class SheerkaEvaluateConcept: # 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) + evaluated = self.evaluate_concept(sub_context, to_resolve, evaluate_body) sub_context.add_values(return_values=evaluated) if evaluated.key == to_resolve.key: return evaluated @@ -147,8 +147,11 @@ class SheerkaEvaluateConcept: # otherwise, execute all return values to find out what is the value else: use_copy = [r for r in to_resolve] if hasattr(to_resolve, "__iter__") else to_resolve + if evaluate_body: + sub_context.extra_info.append(BuiltinConcepts.CONCEPT_EVAL_REQUESTED) r = self.sheerka.execute(sub_context, use_copy, CONCEPT_EVALUATION_STEPS) - one_r = core.builtin_helpers.expect_one(context, r) + + one_r = expect_one(context, r) sub_context.add_values(return_values=one_r) if one_r.status: return one_r.value @@ -161,7 +164,7 @@ class SheerkaEvaluateConcept: concept=current_concept, property_name=current_prop) - def resolve_list(self, context, list_to_resolve, current_prop, current_concept): + def resolve_list(self, context, list_to_resolve, current_prop, current_concept, evaluate_body): """When dealing with a list, there are two possibilities""" # It may be a list of ReturnValueConcept to execute (always the case for metadata) # or a list of single values (may be the case for properties) @@ -170,7 +173,7 @@ class SheerkaEvaluateConcept: return [] if self.sheerka.isinstance(list_to_resolve[0], BuiltinConcepts.RETURN_VALUE): - return self.resolve(context, list_to_resolve, current_prop, current_concept) + return self.resolve(context, list_to_resolve, current_prop, current_concept, evaluate_body) res = [] for to_resolve in list_to_resolve: @@ -181,35 +184,31 @@ class SheerkaEvaluateConcept: concept=current_concept, property_name=current_prop) - r = self.resolve(context, to_resolve, current_prop, current_concept) + r = self.resolve(context, to_resolve, current_prop, current_concept, evaluate_body) if self.sheerka.isinstance(r, BuiltinConcepts.CONCEPT_EVAL_ERROR): return r res.append(r) return res - def evaluate_concept(self, context, concept: Concept): + def evaluate_concept(self, context, concept: Concept, evaluate_body=False): """ Evaluation a concept It means that if the where clause is True, will evaluate the body :param context: :param concept: - :param logger: + :param evaluate_body: If false, only evaluate body when necessary :return: value of the evaluation or error """ if concept.metadata.is_evaluated: return concept - # - # TODO : Validate the PRE condition - # - self.initialize_concept_asts(context, concept) # to make sure of the order, it don't use ConceptParts.get_parts() # props must be evaluated first, body must be evaluated before where - all_metadata_to_eval = ["pre", "post", "props", "body", "where"] + all_metadata_to_eval = self.choose_metadata_to_eval(concept, evaluate_body) for metadata_to_eval in all_metadata_to_eval: if metadata_to_eval == "props": @@ -218,10 +217,10 @@ class SheerkaEvaluateConcept: if isinstance(prop_ast, list): # Do not send the current concept for the properties - resolved = self.resolve_list(context, prop_ast, prop_name, None) + resolved = self.resolve_list(context, prop_ast, prop_name, None, True) else: # Do not send the current concept for the properties - resolved = self.resolve(context, prop_ast, prop_name, None) + resolved = self.resolve(context, prop_ast, prop_name, None, True) if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved): resolved.set_prop("concept", concept) # since current concept was not sent return resolved @@ -237,12 +236,16 @@ class SheerkaEvaluateConcept: if part_key in concept.compiled and concept.compiled[part_key] is not None: metadata_ast = concept.compiled[part_key] - resolved = self.resolve(context, metadata_ast, part_key, concept) + resolved = self.resolve(context, metadata_ast, part_key, concept, evaluate_body) if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved): return resolved else: concept.values[part_key] = self.get_infinite_recursion_resolution(resolved) or resolved + # + # TODO : Validate the PRE condition + # + # validate where clause if ConceptParts.WHERE in concept.values: where_value = concept.values[ConceptParts.WHERE] @@ -254,5 +257,52 @@ class SheerkaEvaluateConcept: # concept.init_key() # only does it if needed - concept.metadata.is_evaluated = True + concept.metadata.is_evaluated = "body" in all_metadata_to_eval return concept + + def choose_metadata_to_eval(self, concept, evaluate_body): + if evaluate_body: + return ["pre", "post", "props", "body", "where"] + + metadata = ["pre", "post"] + self.needed_metadata(concept) + ["where"] + return metadata + + def needed_metadata(self, concept): + """ + Tries to find out if the evaluation of the body is necessary + It's a very basic approach that will need to be improved + :param concept: + :return: + """ + + needed = [] + + for metadata in (ConceptParts.PRE, ConceptParts.POST, ConceptParts.WHERE): + if metadata not in concept.compiled: + continue + + return_values = concept.compiled[metadata] + if not isinstance(return_values, list): + continue + + for return_value in return_values: + if not self.sheerka.isinstance(return_value, BuiltinConcepts.RETURN_VALUE): + continue + + if not return_value.status: + continue + + if not self.sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT): + continue + + if not isinstance(return_value.body.source, str): + continue + + for prop_name in (p[0] for p in concept.metadata.props): + if prop_name in return_value.body.source: + needed.append("props") + break + + if "self" in return_value.body.source: + needed.append("body") + return needed diff --git a/src/core/sheerka/Services/SheerkaExecute.py b/src/core/sheerka/Services/SheerkaExecute.py index 1d2edcb..71b9a27 100644 --- a/src/core/sheerka/Services/SheerkaExecute.py +++ b/src/core/sheerka/Services/SheerkaExecute.py @@ -150,6 +150,11 @@ class SheerkaExecute: debug_result = [] for item in original_items: if evaluator.matches(sub_context, item): + + # init the evaluator is possible + if hasattr(evaluator, "init_evaluator") and not evaluator.is_initialized: + evaluator.init_evaluator(sub_context, original_items) + result = evaluator.eval(sub_context, item) if result is None: debug_result.append({"input": item, "return_value": None}) diff --git a/src/core/sheerka/Services/SheerkaSetsManager.py b/src/core/sheerka/Services/SheerkaSetsManager.py index 948c638..bb03fa6 100644 --- a/src/core/sheerka/Services/SheerkaSetsManager.py +++ b/src/core/sheerka/Services/SheerkaSetsManager.py @@ -108,7 +108,7 @@ class SheerkaSetsManager: # it may be a concept that references a set if not sub_concept.metadata.is_evaluated: with context.push(desc=f"Evaluating concept {sub_concept}") as sub_context: - evaluated = self.sheerka.evaluate_concept(sub_context, sub_concept) + evaluated = self.sheerka.evaluate_concept(sub_context, sub_concept, True) if evaluated.key != concept.key: return False return _get_set_elements(context, concept, sub_concept.body) @@ -167,7 +167,7 @@ class SheerkaSetsManager: # it may be a concept that references a set if not concept.metadata.is_evaluated: with context.push(desc=f"Evaluating concept {concept}") as sub_context: - evaluated = self.sheerka.evaluate_concept(sub_context, concept) + evaluated = self.sheerka.evaluate_concept(sub_context, concept, True) if evaluated.key != concept.key: return False @@ -218,7 +218,7 @@ for x in xx__concepts__xx: with context.push(desc=f"Evaluating concepts of a set") as sub_context: for element_id in ids: concept = self.sheerka.get_by_id(element_id) - evaluated = self.sheerka.evaluate_concept(context, concept) + evaluated = self.sheerka.evaluate_concept(sub_context, concept, True) result.append(evaluated) return result diff --git a/src/core/sheerka/Sheerka.py b/src/core/sheerka/Sheerka.py index cd5204a..c344bbb 100644 --- a/src/core/sheerka/Sheerka.py +++ b/src/core/sheerka/Sheerka.py @@ -269,7 +269,6 @@ class Sheerka(Concept): :param execution_context: :param return_values: :param execution_steps: - :param logger: logger to use (if not directly called by sheerka) :return: """ return self.execute_handler.execute(execution_context, return_values, execution_steps) @@ -294,7 +293,6 @@ class Sheerka(Concept): Adds a new concept to the system :param context: :param concept: DefConceptNode - :param logger :return: digest of the new concept """ @@ -309,7 +307,6 @@ class Sheerka(Concept): :param context: :param concept: :param concept_set: - :param logger: :return: """ return self.sets_handler.add_concept_to_set(context, concept, concept_set) @@ -320,7 +317,6 @@ class Sheerka(Concept): :param context: :param concept: :param concept_set: - :param logger: :return: """ return self.sets_handler.set_isa(context, concept, concept_set) @@ -336,16 +332,17 @@ class Sheerka(Concept): return self.sets_handler.get_set_elements(context, concept) - def evaluate_concept(self, context, concept: Concept): + def evaluate_concept(self, context, concept: Concept, evaluate_body=False): """ Evaluation a concept It means that if the where clause is True, will evaluate the body + :param evaluate_body: :param context: :param concept: - :param logger: + :param evaluate_body: :return: value of the evaluation or error """ - return self.evaluate_concept_handler.evaluate_concept(context, concept) + return self.evaluate_concept_handler.evaluate_concept(context, concept, evaluate_body) def add_in_cache(self, concept: Concept): """ @@ -393,11 +390,13 @@ class Sheerka(Concept): if result is None: metadata = [("key", concept_key), ("id", concept_id)] if concept_id else ("key", concept_key) result = self._get_unknown(metadata) - - self.cache_by_key[concept_key] = result - for r in (result if isinstance(result, list) else [result]): - if r.id: - self.cache_by_id[r.id] = r + # Do not put in cache_by_key or cache_by_id unknown concept + # TODO: implement an MRU cache for them + else: + self.cache_by_key[concept_key] = result + for r in (result if isinstance(result, list) else [result]): + if r.id: + self.cache_by_id[r.id] = r if not (isinstance(result, list) and concept_id): return result @@ -640,7 +639,9 @@ class Sheerka(Concept): if line == "" or line.startswith("#"): continue self.log.info(line) - self.evaluate_user_input(line) + res = self.evaluate_user_input(line) + if len(res) > 1 or not res[0].status: + self.log.error("Error detected !") self.during_restore = False except IOError: pass diff --git a/src/core/sheerka_logger.py b/src/core/sheerka_logger.py index c05773c..f41522b 100644 --- a/src/core/sheerka_logger.py +++ b/src/core/sheerka_logger.py @@ -8,6 +8,7 @@ console_handler = logging.StreamHandler(sys.stdout) all_loggers = {} + def init_config(loggers): if loggers is None: return @@ -55,7 +56,7 @@ def get_logger(logger_name): logger.disabled = True for e in enabled: - if logger_name.startswith("verbose." + e): + if logger_name.startswith("verbose." + e) or logger_name == e: logger.disabled = False return logger diff --git a/src/evaluators/ConceptEvaluator.py b/src/evaluators/ConceptEvaluator.py index be0eccd..48154f0 100644 --- a/src/evaluators/ConceptEvaluator.py +++ b/src/evaluators/ConceptEvaluator.py @@ -5,7 +5,7 @@ from evaluators.BaseEvaluator import OneReturnValueEvaluator class ConceptEvaluator(OneReturnValueEvaluator): """ - The concept evaluatuor is the main class that know what to do with a concept + The concept evaluator is the main class that know what to do with a concept It verifies the PRE If ok, can execute or not the BODY Then checks the POST conditions @@ -15,6 +15,19 @@ class ConceptEvaluator(OneReturnValueEvaluator): def __init__(self, return_body=False): super().__init__(self.NAME, [BuiltinConcepts.EVALUATION], 50) self.return_body = return_body + self.evaluate_body = False + self.is_initialized = False + + def init_evaluator(self, context, return_values): + if BuiltinConcepts.CONCEPT_EVAL_REQUESTED in context.extra_info: + self.evaluate_body = True + + for r in return_values: + if r.status and context.sheerka.isinstance(r.body, BuiltinConcepts.CONCEPT_VALUE_REQUESTED): + self.evaluate_body = True + break + + self.is_initialized = True def matches(self, context, return_value): return return_value.status and \ @@ -36,7 +49,7 @@ class ConceptEvaluator(OneReturnValueEvaluator): return sheerka.ret(self.name, True, value, parents=[return_value]) - evaluated = sheerka.evaluate_concept(context, concept) + evaluated = sheerka.evaluate_concept(context, concept, self.evaluate_body) if evaluated.key != concept.key: # evaluated.key != concept.key means that we have transformed the concept diff --git a/src/evaluators/EvalEvaluator.py b/src/evaluators/EvalEvaluator.py index 06a92d1..6ab3041 100644 --- a/src/evaluators/EvalEvaluator.py +++ b/src/evaluators/EvalEvaluator.py @@ -17,7 +17,7 @@ class EvalEvaluator(AllReturnValuesEvaluator): def matches(self, context, return_values): sheerka = context.sheerka for ret in return_values: - if ret.status and sheerka.isinstance(ret.body, BuiltinConcepts.CONCEPT_EVAL_REQUESTED): + if ret.status and sheerka.isinstance(ret.body, BuiltinConcepts.CONCEPT_VALUE_REQUESTED): self.eval_requested = ret return True @@ -47,5 +47,5 @@ class EvalEvaluator(AllReturnValuesEvaluator): return sheerka.ret( self.name, False, - sheerka.new(BuiltinConcepts.CONCEPT_EVAL_REQUESTED), + sheerka.new(BuiltinConcepts.CONCEPT_VALUE_REQUESTED), parents=[self.eval_requested]) diff --git a/src/evaluators/MutipleSameSuccessEvaluator.py b/src/evaluators/MutipleSameSuccessEvaluator.py index ad1cc24..0afd0e5 100644 --- a/src/evaluators/MutipleSameSuccessEvaluator.py +++ b/src/evaluators/MutipleSameSuccessEvaluator.py @@ -49,7 +49,7 @@ class MultipleSameSuccessEvaluator(AllReturnValuesEvaluator): for s in self.success: context.log(f"{s}", who=self) - if not core.builtin_helpers.is_same_success(sheerka, self.success): + if not core.builtin_helpers.is_same_success(context, self.success): return None # ###################################### diff --git a/src/evaluators/PrepareEvalEvaluator.py b/src/evaluators/PrepareEvalEvaluator.py index a44d86a..4c5867f 100644 --- a/src/evaluators/PrepareEvalEvaluator.py +++ b/src/evaluators/PrepareEvalEvaluator.py @@ -35,6 +35,6 @@ class PrepareEvalEvaluator(OneReturnValueEvaluator): evaluation_requested = sheerka.ret( self.name, - True, sheerka.new(BuiltinConcepts.CONCEPT_EVAL_REQUESTED)) + True, sheerka.new(BuiltinConcepts.CONCEPT_VALUE_REQUESTED)) return [new_text_to_parse, evaluation_requested] diff --git a/src/evaluators/PythonEvaluator.py b/src/evaluators/PythonEvaluator.py index 72f2b11..6a456de 100644 --- a/src/evaluators/PythonEvaluator.py +++ b/src/evaluators/PythonEvaluator.py @@ -112,7 +112,7 @@ class PythonEvaluator(OneReturnValueEvaluator): context.log(f"Evaluating '{concept}'", self.name) with context.push(self.name, desc=f"Evaluating '{concept}'", obj=concept) as sub_context: - evaluated = context.sheerka.evaluate_concept(sub_context, concept) + evaluated = context.sheerka.evaluate_concept(sub_context, concept, True) sub_context.add_values(return_values=evaluated) if evaluated.key == concept.key: diff --git a/src/evaluators/TooManySuccessEvaluator.py b/src/evaluators/TooManySuccessEvaluator.py index b4c235a..5cd4414 100644 --- a/src/evaluators/TooManySuccessEvaluator.py +++ b/src/evaluators/TooManySuccessEvaluator.py @@ -44,7 +44,7 @@ class TooManySuccessEvaluator(AllReturnValuesEvaluator): context.log(s, self.name) context.log(f"value={sheerka.value(s.value)}", self.name) - if not core.builtin_helpers.is_same_success(sheerka, self.success): + if not core.builtin_helpers.is_same_success(context, self.success): context.log(f"Values are different. Raising {BuiltinConcepts.TOO_MANY_SUCCESS}.", self.name) too_many_success = sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS, body=self.success) return sheerka.ret(self.name, False, too_many_success, parents=self.eaten) diff --git a/tests/core/test_ExecutionContext.py b/tests/core/test_ExecutionContext.py index c4d09ab..40c7845 100644 --- a/tests/core/test_ExecutionContext.py +++ b/tests/core/test_ExecutionContext.py @@ -34,6 +34,7 @@ def test_i_can_push(): concepts={"bar": Concept("bar")}) a.preprocess = set() a.preprocess.add("preprocess") + a.extra_info.append(BuiltinConcepts.CONCEPT_EVAL_REQUESTED) b = a.push() @@ -49,6 +50,7 @@ def test_i_can_push(): assert b.id == a.id + 1 assert b._tab == a._tab + " " assert b.preprocess == a.preprocess + assert b.extra_info == [BuiltinConcepts.CONCEPT_EVAL_REQUESTED] def test_children_i_created_when_i_push(): diff --git a/tests/core/test_SheerkaEvaluateConcept.py b/tests/core/test_SheerkaEvaluateConcept.py index 9d1b54b..4df84cb 100644 --- a/tests/core/test_SheerkaEvaluateConcept.py +++ b/tests/core/test_SheerkaEvaluateConcept.py @@ -21,8 +21,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): def test_i_can_evaluate_a_concept_with_simple_body(self, body, expected): sheerka = self.get_sheerka() - concept = Concept("foo", body=body) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + concept = Concept("foo", body=body).init_key() + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == expected @@ -53,7 +53,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka = self.get_sheerka() - concept = Concept("foo", pre=expr) + concept = Concept("foo", pre=expr).init_key() evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key @@ -63,7 +63,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): assert evaluated.metadata.where is None assert evaluated.get_metadata_value(ConceptParts.PRE) == expected assert evaluated.props == {} - assert evaluated.metadata.is_evaluated + assert not evaluated.metadata.is_evaluated assert len(evaluated.values) == 0 if expr is None else 1 @pytest.mark.parametrize("expr, expected", [ @@ -80,7 +80,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka = self.get_sheerka() concept = Concept("foo").def_prop("a", expr) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.metadata.pre is None @@ -95,7 +95,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept = Concept("foo") concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.body == "do not resolve" assert evaluated.metadata.is_evaluated @@ -105,7 +105,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept = Concept("foo").def_prop("a") concept.compiled["a"] = DoNotResolve("do not resolve") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.get_prop("a") == "do not resolve" assert evaluated.metadata.is_evaluated @@ -116,7 +116,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept.compiled["a"] = DoNotResolve("do not resolve") concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.body == "do not resolve" assert evaluated.get_prop("a") == "do not resolve" @@ -126,7 +126,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka = self.get_sheerka() concept = Concept("foo", body="a+1").def_prop("a", "10").init_key() - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == 11 @@ -137,7 +137,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(concept_a) concept = Concept("foo", body="a").init_key() - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated == simplec("foo", simplec("a", None)) assert id(evaluated.body) != id(concept_a) @@ -150,7 +150,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(concept_a) concept = Concept("foo", body="a") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == simplec("a", 1) @@ -164,7 +164,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(Concept(name="c", body="b")) concept_d = sheerka.add_in_cache(Concept(name="d", body="c")) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d, True) assert evaluated.key == concept_d.key expected = simplec("c", simplec("b", simplec("a", "a"))) @@ -179,7 +179,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(Concept(name="c", body="b")) concept_d = sheerka.add_in_cache(Concept(name="d", body="c")) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept_d, True) assert evaluated.key == concept_d.key expected = simplec("c", simplec("b", simplec("a", None))) @@ -192,7 +192,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept_a = sheerka.add_in_cache(Concept(name="a").init_key()) concept = Concept("foo", body="a").def_prop("a", "a").init_key() - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) # first prop a is evaluated to concept_a # then body is evaluated to prop a -> concept_a @@ -209,7 +209,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept_a = sheerka.add_in_cache(Concept(name="a")) concept = Concept("foo", body="concept_a").def_prop("concept_a", "a") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == concept_a @@ -220,7 +220,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(Concept(name="b", body="2")) concept = Concept("foo", body="propA + propB").def_prop("propA", "a").def_prop("propB", "b") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == 3 @@ -231,7 +231,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept = Concept("foo").def_prop("a") concept.compiled["a"] = concept_a - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.get_prop("a") == simplec("a", "a") @@ -242,7 +242,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept = Concept("to_eval").def_prop("prop") concept.compiled["prop"] = [foo, DoNotResolve("1")] - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) props = evaluated.get_prop("prop") assert len(props) == 2 @@ -257,20 +257,20 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept = Concept("to_eval").def_prop("prop") concept.compiled["prop"] = [ReturnValueConcept("who", True, parser_result)] - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.get_prop("prop") == 2 # also works when only one return value concept = Concept("to_eval").def_prop("prop") concept.compiled["prop"] = ReturnValueConcept("who", True, parser_result) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.get_prop("prop") == 2 def test_i_can_reference_sheerka(self): sheerka = self.get_sheerka() concept = Concept("foo", body="sheerka.test()").init_key() - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == sheerka.test() @@ -281,19 +281,19 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(Concept(name="b", body="'concept_b'")) concept = Concept("foo", body="a") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == simplec("a", "concept_a") # this test was already done # so check this one. concept = Concept("foo", body="a").def_prop("a", "'property_a'") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == 'property_a' # or this one. concept = Concept("foo", body="a").def_prop("a", "b") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == simplec(name="b", body="concept_b") @@ -303,7 +303,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(Concept(name="b", body="'concept_b'")) concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'").init_key() - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == 'prop_aconcept_b' @@ -312,21 +312,21 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(Concept(name="concept_a").def_prop("subProp", "'sub_a'")) concept = Concept("foo", body="a.props['subProp'].value").def_prop("a", "concept_a") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated == simplec(concept.key, "sub_a") def test_i_cannot_evaluate_concept_if_property_is_in_error(self): sheerka = self.get_sheerka() concept = Concept(name="concept_a").def_prop("subProp", "undef_concept") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR) def test_key_is_initialized_by_evaluation(self): sheerka = self.get_sheerka() concept = Concept("foo") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.init_key().key @@ -345,7 +345,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): concept = Concept("foo", body="10", where=where_clause).def_prop("a", "20") sheerka.add_in_cache(concept) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) if expected: assert evaluated.key == concept.key @@ -362,11 +362,11 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(foo_true) concept = Concept("foo", where="foo_true").init_key() - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key concept = Concept("foo", where="foo_false") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert sheerka.isinstance(evaluated, BuiltinConcepts.WHERE_CLAUSE_FAILED) assert evaluated.body == concept @@ -379,11 +379,11 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(one_str) sheerka.add_in_cache(one_digit) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), one_digit) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), one_digit, True) assert evaluated.key == one_digit.key assert evaluated.body == InfiniteRecursionResolved(1) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), one_str) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), one_str, True) assert evaluated.key == one_str.key assert evaluated.body == InfiniteRecursionResolved(1) @@ -396,11 +396,11 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(true_str) sheerka.add_in_cache(true_bool) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), true_str) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), true_str, True) assert evaluated.key == true_str.key assert evaluated.body == InfiniteRecursionResolved(True) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), true_bool) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), true_bool, True) assert evaluated.key == true_bool.key assert evaluated.body == InfiniteRecursionResolved(True) @@ -413,7 +413,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): c4 = sheerka.add_in_cache(Concept("3", body="one")) for concept in (c1, c2, c3, c4): - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept, True) assert evaluated.key == concept.key assert evaluated.body == InfiniteRecursionResolved(3) @@ -425,19 +425,19 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): baz = sheerka.add_in_cache(Concept("baz", body="qux")) qux = sheerka.add_in_cache(Concept("qux", body="foo")) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), foo) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), foo, True) assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG) assert evaluated.body == {foo, bar, baz, qux} - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), bar) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), bar, True) assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG) assert evaluated.body == {foo, bar, baz, qux} - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), baz) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), baz, True) assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG) assert evaluated.body == {foo, bar, baz, qux} - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), qux) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), qux, True) assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG) assert evaluated.body == {foo, bar, baz, qux} @@ -446,7 +446,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): foo = sheerka.add_in_cache(Concept("foo", body="foo")) - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), foo) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), foo, True) assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG) assert evaluated.body == {foo} @@ -454,7 +454,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka = self.get_sheerka() one = Concept("1", body="1") - evaluated = sheerka.evaluate_concept(self.get_context(sheerka), one) + evaluated = sheerka.evaluate_concept(self.get_context(sheerka), one, True) assert evaluated.key == one.key assert evaluated.body == 1 diff --git a/tests/core/test_SheerkaSetsManager.py b/tests/core/test_SheerkaSetsManager.py index ca23356..a660987 100644 --- a/tests/core/test_SheerkaSetsManager.py +++ b/tests/core/test_SheerkaSetsManager.py @@ -107,7 +107,7 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka): def test_i_can_define_a_group_from_another_group(self): sheerka, context, foo, bar, group1, group2 = self.init_concepts( - Concept("foo"), Concept("bar"), Concept("group1"), Concept("group2", body="group1")) + "foo", "bar", "group1", Concept("group2", body="group1")) sheerka.sets_handler.add_concepts_to_set(context, [foo, bar], group1) @@ -122,7 +122,8 @@ class TestSheerkaSetsManager(TestUsingFileBasedSheerka): Concept("four", body="4"), Concept("five", body="5"), Concept("number"), - Concept("sub_number", body="number", where="number < 4") + Concept("sub_number", body="number", where="number < 4"), + create_new=True ) sheerka.sets_handler.add_concepts_to_set(context, [one, two, three, four, five], number) diff --git a/tests/core/test_sheerka_call_evaluators.py b/tests/core/test_sheerka_call_evaluators.py index fa04e65..3d27ba5 100644 --- a/tests/core/test_sheerka_call_evaluators.py +++ b/tests/core/test_sheerka_call_evaluators.py @@ -124,6 +124,26 @@ class EvaluatorOnePreEvaluation(OneReturnValueEvaluatorForTestingPurpose): super().__init__("preEval", [BuiltinConcepts.BEFORE_EVALUATION], 10) +class EvaluatorOneInitializationOnce(OneReturnValueEvaluatorForTestingPurpose): + def __init__(self): + super().__init__("init_once", [BuiltinConcepts.EVALUATION], 10) + self.is_initialized = False + + def init_evaluator(self, context, return_values): + self.out_all("init_evaluator", self.name, context, return_values) + self.is_initialized = True + + +class EvaluatorOneInitializationMultiple(OneReturnValueEvaluatorForTestingPurpose): + def __init__(self): + super().__init__("init_multiple", [BuiltinConcepts.EVALUATION], 10) + self.is_initialized = False + + def init_evaluator(self, context, return_values): + self.out_all("init_evaluator", self.name, context, return_values) + # self.is_initialized = True + + class EvaluatorOneMultiSteps(OneReturnValueEvaluatorForTestingPurpose): def __init__(self): super().__init__("multiStep", [BuiltinConcepts.EVALUATION, BuiltinConcepts.BEFORE_EVALUATION], 10) @@ -373,3 +393,52 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka): '__EVALUATION [1] modifyFoo - matches - target=bar', '__EVALUATION [1] modifyFoo - matches - target=__EVALUATION' ] + + def test_i_can_initialize_evaluator_if_initialize_evaluator_is_defined(self): + sheerka, context, foo, bar, baz = self.init_concepts("foo", "bar", "baz") + sheerka.evaluators = [EvaluatorOneInitializationOnce] + + entries = [ + self.tretval(sheerka, foo), + self.tretval(sheerka, bar), + self.tretval(sheerka, baz) + ] + Out.debug_out = [] + sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION]) + assert Out.debug_out == [ + '__EVALUATION [0] init_once - matches - target=foo', + "__EVALUATION [0] init_once - init_evaluator - target=['foo', 'bar', 'baz', '__EVALUATION']", + '__EVALUATION [0] init_once - eval - target=foo', + '__EVALUATION [0] init_once - matches - target=bar', + '__EVALUATION [0] init_once - eval - target=bar', + '__EVALUATION [0] init_once - matches - target=baz', + '__EVALUATION [0] init_once - eval - target=baz', + '__EVALUATION [0] init_once - matches - target=__EVALUATION', + '__EVALUATION [0] init_once - eval - target=__EVALUATION' + ] + + def test_i_can_initialize_evaluators_multiple_times(self): + sheerka, context, foo, bar, baz = self.init_concepts("foo", "bar", "baz") + sheerka.evaluators = [EvaluatorOneInitializationMultiple] + + entries = [ + self.tretval(sheerka, foo), + self.tretval(sheerka, bar), + self.tretval(sheerka, baz) + ] + Out.debug_out = [] + sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION]) + assert Out.debug_out == [ + '__EVALUATION [0] init_multiple - matches - target=foo', + "__EVALUATION [0] init_multiple - init_evaluator - target=['foo', 'bar', 'baz', '__EVALUATION']", + '__EVALUATION [0] init_multiple - eval - target=foo', + '__EVALUATION [0] init_multiple - matches - target=bar', + "__EVALUATION [0] init_multiple - init_evaluator - target=['foo', 'bar', 'baz', '__EVALUATION']", + '__EVALUATION [0] init_multiple - eval - target=bar', + '__EVALUATION [0] init_multiple - matches - target=baz', + "__EVALUATION [0] init_multiple - init_evaluator - target=['foo', 'bar', 'baz', '__EVALUATION']", + '__EVALUATION [0] init_multiple - eval - target=baz', + '__EVALUATION [0] init_multiple - matches - target=__EVALUATION', + "__EVALUATION [0] init_multiple - init_evaluator - target=['foo', 'bar', 'baz', '__EVALUATION']", + '__EVALUATION [0] init_multiple - eval - target=__EVALUATION' + ] diff --git a/tests/evaluators/test_AddConceptInSetEvaluator.py b/tests/evaluators/test_AddConceptInSetEvaluator.py index 1f9b810..a193a6f 100644 --- a/tests/evaluators/test_AddConceptInSetEvaluator.py +++ b/tests/evaluators/test_AddConceptInSetEvaluator.py @@ -66,6 +66,31 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka): foo_from_sheerka = context.sheerka.get("foo") assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == [bar] + def test_i_can_add_bnf_concept_to_a_set_of_concept(self): + """ + This test is the reason why I have started the whole eval on demand stuff + Sheerka tries to evaluate the body but it can (as a and b are not defined) + So 'foo' cannot be put is set + :return: + """ + sheerka, context, foo, bar = self.init_concepts( + Concept("foo", definition="a plus b", body="a + b").def_prop("a").def_prop("b"), + "bar", + create_new=True) + + ret_val = get_ret_val("foo", "bar") + res = AddConceptInSetEvaluator().eval(context, ret_val) + foo = sheerka.new("foo") # reload it + + assert res.status + assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS) + assert context.sheerka.isaset(context, bar) + assert context.sheerka.isinset(foo, bar) + assert context.sheerka.isa(foo, bar) + + foo_from_sheerka = context.sheerka.get("foo") + assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == [bar] + def test_i_can_add_concept_with_a_body_to_a_set_of_concept(self): context = self.get_context() foo = Concept("foo", body="1") diff --git a/tests/evaluators/test_ConceptEvaluator.py b/tests/evaluators/test_ConceptEvaluator.py index 64408b2..f762828 100644 --- a/tests/evaluators/test_ConceptEvaluator.py +++ b/tests/evaluators/test_ConceptEvaluator.py @@ -20,6 +20,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka): def test_i_can_evaluate_concept(self): context = self.get_context() + context.extra_info.append(BuiltinConcepts.CONCEPT_EVAL_REQUESTED) concept = Concept(name="foo", where="True", pre="2", @@ -27,6 +28,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka): evaluator = ConceptEvaluator() item = self.pretval(concept) + evaluator.init_evaluator(context, [item]) result = evaluator.eval(context, item) assert result.who == evaluator.name @@ -42,6 +44,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka): def test_body_is_returned_when_defined_and_requested(self): context = self.get_context() + context.extra_info.append(BuiltinConcepts.CONCEPT_EVAL_REQUESTED) concept = Concept(name="foo", body="'I have a value'", where="True", @@ -50,6 +53,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka): evaluator = ConceptEvaluator(return_body=True) item = self.pretval(concept) + evaluator.init_evaluator(context, [item]) result = evaluator.eval(context, item) assert result.who == evaluator.name @@ -67,6 +71,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka): evaluator = ConceptEvaluator(return_body=False) # which is the default behaviour item = self.pretval(concept) + evaluator.init_evaluator(context, [item]) result = evaluator.eval(context, item) assert result.who == evaluator.name @@ -90,6 +95,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka): def test_i_cannot_recognize_a_concept_if_one_of_the_prop_is_unknown(self): context = self.get_context() + context.extra_info.append(BuiltinConcepts.CONCEPT_EVAL_REQUESTED) context.sheerka.add_in_cache(Concept(name="one").init_key()) concept_plus = context.sheerka.add_in_cache(Concept(name="a plus b") .def_prop("a", "one") @@ -97,6 +103,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka): evaluator = ConceptEvaluator() item = self.pretval(concept_plus) + evaluator.init_evaluator(context, [item]) result = evaluator.eval(context, item) assert not result.status diff --git a/tests/evaluators/test_EvalEvaluator.py b/tests/evaluators/test_EvalEvaluator.py index 365350e..dbcbb71 100644 --- a/tests/evaluators/test_EvalEvaluator.py +++ b/tests/evaluators/test_EvalEvaluator.py @@ -5,7 +5,7 @@ from core.concept import Concept from evaluators.EvalEvaluator import EvalEvaluator from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka -eval_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.CONCEPT_EVAL_REQUESTED)) +value_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.CONCEPT_VALUE_REQUESTED)) def retval(obj, who="who", status=True): @@ -26,7 +26,7 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka): ReturnValueConcept("some_name", False, Concept(name="1", body="'not to eval'")), to_eval1, to_eval2, - eval_requested + value_requested ] evaluator = EvalEvaluator() @@ -35,16 +35,16 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka): evaluated = evaluator.eval(context, return_values) assert len(evaluated) == 2 assert evaluated[0].value == to_eval1.body.body - assert evaluated[0].parents == [to_eval1, eval_requested] + assert evaluated[0].parents == [to_eval1, value_requested] assert evaluated[1].value == to_eval2.body.body - assert evaluated[1].parents == [to_eval2, eval_requested] + assert evaluated[1].parents == [to_eval2, value_requested] @pytest.mark.parametrize("return_values, expected", [ - ([retval(Concept("foo", body="bar")), eval_requested], True), - ([retval(Concept("status is false", body="bar"), status=False), eval_requested], True), - ([retval("string_value"), eval_requested], True), - ([retval(Concept("no body")), eval_requested], True), + ([retval(Concept("foo", body="bar")), value_requested], True), + ([retval(Concept("status is false", body="bar"), status=False), value_requested], True), + ([retval("string_value"), value_requested], True), + ([retval(Concept("no body")), value_requested], True), ([retval(Concept("eval requested missing", body="bar"))], False), ]) def test_i_cannot_match_if_eval_request_is_not_present(self, return_values, expected): @@ -58,7 +58,7 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka): ReturnValueConcept("some_name", True, "not to eval"), ReturnValueConcept("some_name", True, Concept(name="not to eval")), ReturnValueConcept("some_name", False, Concept(name="1", body="not to eval")), - eval_requested + value_requested ] evaluator = EvalEvaluator() @@ -68,8 +68,8 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka): assert evaluated == ReturnValueConcept( "evaluators.Eval", False, - context.sheerka.new(BuiltinConcepts.CONCEPT_EVAL_REQUESTED)) - assert evaluated.parents == [eval_requested] + context.sheerka.new(BuiltinConcepts.CONCEPT_VALUE_REQUESTED)) + assert evaluated.parents == [value_requested] def test_i_can_evaluate_sets(self): sheerka, context, foo, bar, baz, number = self.init_concepts( @@ -79,7 +79,7 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka): Concept("number")) sheerka.sets_handler.add_concepts_to_set(context, [foo, bar, baz], number) - return_values = [retval(number), eval_requested] + return_values = [retval(number), value_requested] evaluator = EvalEvaluator() evaluator.matches(context, return_values) diff --git a/tests/evaluators/test_PrepareEvalEvaluator.py b/tests/evaluators/test_PrepareEvalEvaluator.py index d0abee1..b72db4b 100644 --- a/tests/evaluators/test_PrepareEvalEvaluator.py +++ b/tests/evaluators/test_PrepareEvalEvaluator.py @@ -46,4 +46,4 @@ class TestPrepareEvalEvaluator(TestUsingMemoryBasedSheerka): assert res[0].body.body == expected assert res[1].status - assert sheerka.isinstance(res[1].body, BuiltinConcepts.CONCEPT_EVAL_REQUESTED) + assert sheerka.isinstance(res[1].body, BuiltinConcepts.CONCEPT_VALUE_REQUESTED) diff --git a/tests/non_reg/test_sheerka_non_reg.py b/tests/non_reg/test_sheerka_non_reg.py index a834ad2..304ce18 100644 --- a/tests/non_reg/test_sheerka_non_reg.py +++ b/tests/non_reg/test_sheerka_non_reg.py @@ -15,7 +15,7 @@ class TestSheerkaNonReg(TestUsingFileBasedSheerka): ("1 + 1", 2), ("sheerka.test()", 'I have access to Sheerka !') ]) - def test_i_can_eval_python_expressions_with_no_variable(self, text, expected): + def test_i_can_evaluate_python_expressions_with_no_variable(self, text, expected): sheerka = self.get_sheerka() res = sheerka.evaluate_user_input(text) @@ -24,7 +24,7 @@ class TestSheerkaNonReg(TestUsingFileBasedSheerka): assert res[0].status assert res[0].value == expected - def test_i_can_eval_concept_with_python_body(self): + def test_i_can_recognize_concept_with_python_body(self): sheerka = self.get_sheerka() concept = Concept(name="one", body="1") sheerka.add_in_cache(concept) @@ -33,9 +33,13 @@ class TestSheerkaNonReg(TestUsingFileBasedSheerka): res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert res[0].status - assert res[0].value == simplec("one", 1) # by default, the concept is returned + assert res[0].value == concept - def test_i_can_eval_concept_with_concept_body(self): + # sanity check + evaluated = sheerka.evaluate_concept(self.get_context(), res[0].value, True) + assert evaluated == simplec("one", 1) + + def test_i_can_recognize_concept_with_concept_body(self): sheerka = self.get_sheerka() concept_one = Concept(name="one") concept_un = Concept(name="un", body="one") @@ -46,9 +50,13 @@ class TestSheerkaNonReg(TestUsingFileBasedSheerka): return_value = res[0].value assert len(res) == 1 assert res[0].status - assert return_value == simplec("un", simplec("one", None)) + assert return_value == concept_un - def test_i_can_eval_concept_with_no_body(self): + # sanity check + evaluated = sheerka.evaluate_concept(self.get_context(), return_value, True) + assert evaluated == simplec("un", simplec("one", None)) + + def test_i_can_recognize_concept_with_no_body(self): sheerka = self.get_sheerka() concept = Concept(name="one") sheerka.add_in_cache(concept) @@ -72,7 +80,7 @@ class TestSheerkaNonReg(TestUsingFileBasedSheerka): assert res[0].value == concept assert id(res[0].value) == id(concept) - def test_i_can_eval_def_concept_request(self): + def test_i_can_evaluate_def_concept_request(self): text = """ def concept a + b where isinstance(a, int) and isinstance(b, int) @@ -107,7 +115,7 @@ as: assert sheerka.sdp.io.exists( sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_origin())) - def test_i_can_eval_def_concept_part_when_one_part_is_a_ref_of_another_concept(self): + def test_i_can_evaluate_def_concept_part_when_one_part_is_a_ref_of_another_concept(self): """ In this test, we test that the properties of 'concept a xx b' (which are 'a' and 'b') are correctly detected, thanks to the source code 'a plus b' in its body @@ -137,7 +145,7 @@ as: assert sheerka.sdp.io.exists( sheerka.sdp.io.get_obj_path(SheerkaDataProvider.ObjectsFolder, concept_saved.get_origin())) - def test_i_cannot_eval_the_same_def_concept_twice(self): + def test_i_cannot_evaluate_the_same_def_concept_twice(self): text = """ def concept a + b where isinstance(a, int) and isinstance(b, int) @@ -162,7 +170,7 @@ as: " ", "\n", ]) - def test_i_can_eval_a_empty_input(self, text): + def test_i_can_recognize_a_empty_input(self, text): sheerka = self.get_sheerka() res = sheerka.evaluate_user_input(text) @@ -171,7 +179,7 @@ as: assert res[0].status assert sheerka.isinstance(res[0].value, BuiltinConcepts.NOP) - def test_i_can_eval_concept_with_variable(self): + def test_i_can_recognize_concept_with_variable(self): sheerka = self.get_sheerka() concept_hello = Concept(name="hello a").def_prop("a") concept_foo = Concept(name="foo") @@ -183,9 +191,13 @@ as: assert len(res) == 1 assert res[0].status assert sheerka.isinstance(return_value, concept_hello) - assert return_value.props["a"].value == concept_foo + assert return_value.metadata.props[0] == ('a', "foo") - def test_i_can_eval_concept_with_variable_and_python_as_body(self): + # sanity check + evaluated = sheerka.evaluate_concept(self.get_context(), return_value, True) + assert evaluated.props["a"].value == concept_foo + + def test_i_can_recognize_concept_with_variable_and_python_as_body(self): sheerka = self.get_sheerka() hello_a = sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a")) sheerka.add_in_cache(Concept(name="foo", body="'foo'")) @@ -194,12 +206,15 @@ as: assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, hello_a) - assert res[0].value.body == "hello foo" - assert res[0].value.metadata.is_evaluated - assert res[0].value.props["a"].value == simplec("foo", "foo") - assert res[0].value.props["a"].value.metadata.is_evaluated - def test_i_can_eval_duplicate_concepts_with_same_value(self): + # sanity check + evaluated = sheerka.evaluate_concept(self.get_context(), res[0].value, True) + assert evaluated.body == "hello foo" + assert evaluated.metadata.is_evaluated + assert evaluated.props["a"].value == simplec("foo", "foo") + assert evaluated.props["a"].value.metadata.is_evaluated + + def test_i_can_recognize_duplicate_concepts_with_same_value(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_prop("a")) @@ -248,11 +263,11 @@ as: context = self.get_context(sheerka) sheerka.create_new_concept(context, Concept(name="concepts", body="sheerka.concepts()")) - res = sheerka.evaluate_user_input("concepts") + res = sheerka.evaluate_user_input("eval concepts") assert len(res) == 1 assert res[0].status - assert isinstance(res[0].value.body, list) + assert isinstance(res[0].value, list) def test_i_can_create_concept_with_bnf_definition(self): sheerka = self.get_sheerka(use_dict=False, skip_builtins_in_db=False) @@ -284,7 +299,7 @@ as: assert "a" in new_concept.props assert "plus" in new_concept.props - def test_i_can_eval_bnf_definitions(self): + def test_i_can_recognize_bnf_definitions(self): sheerka = self.get_sheerka() concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body @@ -294,7 +309,7 @@ as: assert res[0].status assert sheerka.isinstance(res[0].value, concept_a) - def test_i_can_eval_bnf_definitions_with_variables(self): + def test_i_can_recognize_bnf_definitions_with_variables(self): sheerka = self.get_sheerka() concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body @@ -306,13 +321,15 @@ as: return_value = res[0].value assert sheerka.isinstance(return_value, concept_b) - assert return_value.body == "one three" - assert return_value.metadata.is_evaluated - assert return_value.props["a"] == Property("a", sheerka.new(concept_a.key, body="one").init_key()) - assert return_value.props["a"].value.metadata.is_evaluated + # sanity check + evaluated = sheerka.evaluate_concept(self.get_context(), return_value, True) + assert evaluated.body == "one three" + assert evaluated.metadata.is_evaluated + assert evaluated.props["a"] == Property("a", sheerka.new(concept_a.key, body="one").init_key()) + assert evaluated.props["a"].value.metadata.is_evaluated - def test_i_can_eval_bnf_definitions_from_separate_instances(self): + def test_i_can_recognize_bnf_definitions_from_separate_instances(self): """ Same test then before, but make sure that the BNF are correctly persisted and loaded @@ -337,8 +354,10 @@ as: assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, concept_b) - assert res[0].value.body == "one two three" - assert res[0].value.props["a"] == Property("a", sheerka.new(concept_a.key, body="one two").init_key()) + + evaluated = sheerka.evaluate_concept(self.get_context(), res[0].value, True) + assert evaluated.body == "one two three" + assert evaluated.props["a"] == Property("a", sheerka.new(concept_a.key, body="one two").init_key()) @pytest.mark.parametrize("desc, definitions", [ ("Simple form", [ @@ -387,7 +406,7 @@ as: assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, "twenties") - assert res[0].body.body == 21 + assert sheerka.evaluate_concept(self.get_context(), res[0].body, True).body == 21 res = sheerka.evaluate_user_input("twenty one + 1") assert len(res) == 1 @@ -430,7 +449,8 @@ as: res = sheerka.evaluate_user_input("twenty one") assert len(res) == 1 assert res[0].status - assert res[0].body == simplec("twenties", 21) + assert sheerka.isinstance(res[0].body, "twenties") + assert sheerka.evaluate_concept(self.get_context(), res[0].value, True).body == 21 res = sheerka.evaluate_user_input("twenty one + 1") assert len(res) == 1 @@ -472,10 +492,10 @@ as: for exp in init: sheerka.evaluate_user_input(exp) - res = sheerka.evaluate_user_input("twenty one") + res = sheerka.evaluate_user_input("eval twenty one") assert len(res) == 1 assert res[0].status - assert res[0].body == simplec("twenties", 21) + assert res[0].body == 21 def test_i_can_mix_concept_of_concept(self): sheerka = self.get_sheerka() @@ -490,55 +510,55 @@ as: for definition in definitions: sheerka.evaluate_user_input(definition) - res = sheerka.evaluate_user_input("1 plus 2") + res = sheerka.evaluate_user_input("eval 1 plus 2") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 3 + assert res[0].body == 3 - res = sheerka.evaluate_user_input("1 plus one") + res = sheerka.evaluate_user_input("eval 1 plus one") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 2 + assert res[0].body == 2 - res = sheerka.evaluate_user_input("1 + 1 plus 1") + res = sheerka.evaluate_user_input("eval 1 + 1 plus 1") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 3 + assert res[0].body == 3 - res = sheerka.evaluate_user_input("1 plus twenty one") + res = sheerka.evaluate_user_input("eval 1 plus twenty one") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 22 + assert res[0].body == 22 - res = sheerka.evaluate_user_input("one plus 1") + res = sheerka.evaluate_user_input("eval one plus 1") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 2 + assert res[0].body == 2 - res = sheerka.evaluate_user_input("one plus two") + res = sheerka.evaluate_user_input("eval one plus two") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 3 + assert res[0].body == 3 - res = sheerka.evaluate_user_input("one plus twenty one") + res = sheerka.evaluate_user_input("eval one plus twenty one") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 22 + assert res[0].body == 22 - res = sheerka.evaluate_user_input("twenty one plus 1") + res = sheerka.evaluate_user_input("eval twenty one plus 1") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 22 + assert res[0].body == 22 - res = sheerka.evaluate_user_input("twenty one plus one") + res = sheerka.evaluate_user_input("eval twenty one plus one") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 22 + assert res[0].body == 22 - res = sheerka.evaluate_user_input("twenty one plus twenty two") + res = sheerka.evaluate_user_input("eval twenty one plus twenty two") assert len(res) == 1 assert res[0].status - assert res[0].body.body == 43 + assert res[0].body == 43 @pytest.mark.xfail def test_i_can_evaluate_concept_of_concept_when_multiple_choices(self): @@ -663,23 +683,29 @@ as: for exp in init: sheerka.evaluate_user_input(exp) + res = sheerka.evaluate_user_input("twenty one") + assert len(res) == 1 and res[0].status and sheerka.isinstance(res[0].body, "twenties") + res = sheerka.evaluate_user_input("eval twenty one") assert len(res) == 1 and res[0].status and res[0].body == 21 + res = sheerka.evaluate_user_input("twenty two") + assert len(res) == 1 and res[0].status and sheerka.isinstance(res[0].body, "twenties") + res = sheerka.evaluate_user_input("eval twenty two") assert len(res) == 1 and res[0].status and res[0].body == 22 res = sheerka.evaluate_user_input("eval twenty three") assert len(res) > 1 - def test_i_can_detect_when_only_one_evaluator_is_in_error(self): - sheerka = self.get_sheerka() - - sheerka.evaluate_user_input("def concept 1 as one") - res = sheerka.evaluate_user_input("1") - assert len(res) == 1 - assert not res[0].status - assert sheerka.isinstance(res[0].body, BuiltinConcepts.CONCEPT_EVAL_ERROR) + # def test_i_can_detect_when_only_one_evaluator_is_in_error(self): + # sheerka = self.get_sheerka() + # + # sheerka.evaluate_user_input("def concept 1 as one") + # res = sheerka.evaluate_user_input("eval 1") + # assert len(res) == 1 + # assert not res[0].status + # assert sheerka.isinstance(res[0].body, BuiltinConcepts.CONCEPT_EVAL_ERROR) def test_i_can_manage_some_type_of_infinite_recursion(self): sheerka = self.get_sheerka() @@ -696,3 +722,56 @@ as: assert res[0].status assert res[0].body == 2 + @pytest.mark.xfail + def test_i_can_evaluate_bnf_concept_with_where_clause(self): + + + sheerka = self.get_sheerka() + + sheerka.evaluate_user_input("def concept a from bnf 'bar' | 'baz'") + sheerka.evaluate_user_input("def concept b as 'hello world'") + sheerka.evaluate_user_input("def concept foobar from bnf 'foo' a where a=='bar' as b") + + res = sheerka.evaluate_user_input("foo bar") + assert len(res) == 1 + assert res[0].status + assert sheerka.isinstance(res[0].body, "foobar") + assert res[0].body.body is None + + res = sheerka.evaluate_user_input("eval foo bar") + assert len(res) == 1 + assert res[0].status + assert res[0].body.body == "hello world" + + res = sheerka.evaluate_user_input("foo baz") + assert len(res) == 1 + assert not res[0].status + assert sheerka.isinstance(res[0].body, BuiltinConcepts.WHERE_CLAUSE_FAILED) + + res = sheerka.evaluate_user_input("eval foo baz") + assert len(res) > 1 + + # The following test fails + # the Where clause is evaluated while it should not + res = sheerka.evaluate_user_input("foobar") + assert len(res) == 1 + assert res[0].status + + res = sheerka.evaluate_user_input("eval foobar") + assert len(res) > 1 # error + assert res[0].status + + def test_i_can_say_than_bnf_concept_isa_another_concept(self): + sheerka = self.get_sheerka() + sheerka.evaluate_user_input("def concept number") + sheerka.evaluate_user_input("def concept one as 1") + sheerka.evaluate_user_input("def concept two as 2") + sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit") + + res = sheerka.evaluate_user_input("twenties isa number") + assert len(res) == 1 + assert res[0].status + + twenties = sheerka.get("twenties") + number = sheerka.get("number") + assert sheerka.isa(twenties, number) diff --git a/tests/parsers/test_ConceptsWithConceptsParser.py b/tests/parsers/test_ConceptsWithConceptsParser.py index 8bfd1b3..a5cfd44 100644 --- a/tests/parsers/test_ConceptsWithConceptsParser.py +++ b/tests/parsers/test_ConceptsWithConceptsParser.py @@ -93,7 +93,7 @@ class TestConceptsWithConceptsParser(TestUsingMemoryBasedSheerka): assert return_value.compiled["b"] == bar # sanity check, I can evaluate the result - evaluated = context.sheerka.evaluate_concept(context, return_value) + evaluated = context.sheerka.evaluate_concept(context, return_value, True) assert evaluated.key == return_value.key assert evaluated.get_prop("a") == foo.init_key() assert evaluated.get_prop("b") == bar.init_key() @@ -116,7 +116,7 @@ class TestConceptsWithConceptsParser(TestUsingMemoryBasedSheerka): assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, right_parser_result)] # sanity check, I can evaluate the result - evaluated = context.sheerka.evaluate_concept(context, return_value) + evaluated = context.sheerka.evaluate_concept(context, return_value, True) assert evaluated.key == return_value.key assert evaluated.get_prop("a") == 2 assert evaluated.get_prop("b") == 4 @@ -139,7 +139,7 @@ class TestConceptsWithConceptsParser(TestUsingMemoryBasedSheerka): assert return_value.compiled["b"] == [ReturnValueConcept(parser.name, True, code_parser_result)] # sanity check, I can evaluate the result - evaluated = context.sheerka.evaluate_concept(context, return_value) + evaluated = context.sheerka.evaluate_concept(context, return_value, True) assert evaluated.key == return_value.key assert evaluated.get_prop("a") == foo.init_key() assert evaluated.get_prop("b") == 2