Concept validation must be requested
This commit is contained in:
@@ -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, evaluate_body):
|
||||
def resolve(self, context, to_resolve, current_prop, current_concept, force_evaluation):
|
||||
if isinstance(to_resolve, DoNotResolve):
|
||||
return to_resolve.value
|
||||
|
||||
@@ -134,10 +134,13 @@ class SheerkaEvaluateConcept:
|
||||
context.log(desc, self.logger_name)
|
||||
with context.push(desc=desc, obj=current_concept) as sub_context:
|
||||
|
||||
if force_evaluation:
|
||||
sub_context.local_hints.add(BuiltinConcepts.EVAL_BODY_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, evaluate_body)
|
||||
evaluated = self.evaluate_concept(sub_context, to_resolve)
|
||||
sub_context.add_values(return_values=evaluated)
|
||||
if evaluated.key == to_resolve.key:
|
||||
return evaluated
|
||||
@@ -147,8 +150,6 @@ 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 = expect_one(context, r)
|
||||
@@ -164,7 +165,7 @@ class SheerkaEvaluateConcept:
|
||||
concept=current_concept,
|
||||
property_name=current_prop)
|
||||
|
||||
def resolve_list(self, context, list_to_resolve, current_prop, current_concept, evaluate_body):
|
||||
def resolve_list(self, context, list_to_resolve, current_prop, current_concept, force_evaluation):
|
||||
"""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)
|
||||
@@ -173,7 +174,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, evaluate_body)
|
||||
return self.resolve(context, list_to_resolve, current_prop, current_concept, force_evaluation)
|
||||
|
||||
res = []
|
||||
for to_resolve in list_to_resolve:
|
||||
@@ -184,14 +185,14 @@ class SheerkaEvaluateConcept:
|
||||
concept=current_concept,
|
||||
property_name=current_prop)
|
||||
|
||||
r = self.resolve(context, to_resolve, current_prop, current_concept, evaluate_body)
|
||||
r = self.resolve(context, to_resolve, current_prop, current_concept, force_evaluation)
|
||||
if self.sheerka.isinstance(r, BuiltinConcepts.CONCEPT_EVAL_ERROR):
|
||||
return r
|
||||
res.append(r)
|
||||
|
||||
return res
|
||||
|
||||
def evaluate_concept(self, context, concept: Concept, evaluate_body=False):
|
||||
def evaluate_concept(self, context, concept: Concept):
|
||||
"""
|
||||
Evaluation a concept
|
||||
It means that if the where clause is True, will evaluate the body
|
||||
@@ -208,7 +209,7 @@ class SheerkaEvaluateConcept:
|
||||
|
||||
# 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 = self.choose_metadata_to_eval(concept, evaluate_body)
|
||||
all_metadata_to_eval = self.choose_metadata_to_eval(context, concept)
|
||||
|
||||
for metadata_to_eval in all_metadata_to_eval:
|
||||
if metadata_to_eval == "props":
|
||||
@@ -221,6 +222,7 @@ class SheerkaEvaluateConcept:
|
||||
else:
|
||||
# Do not send the current concept for the properties
|
||||
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
|
||||
@@ -236,7 +238,10 @@ 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, evaluate_body)
|
||||
# if part_key is PRE, POST or WHERE, the concepts need to be evaluated
|
||||
# otherwise the predicates cannot be resolved
|
||||
force_concept_eval = False if part_key == ConceptParts.BODY else True
|
||||
resolved = self.resolve(context, metadata_ast, part_key, concept, force_concept_eval)
|
||||
if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved):
|
||||
return resolved
|
||||
else:
|
||||
@@ -260,49 +265,57 @@ class SheerkaEvaluateConcept:
|
||||
concept.metadata.is_evaluated = "body" in all_metadata_to_eval
|
||||
return concept
|
||||
|
||||
def choose_metadata_to_eval(self, concept, evaluate_body):
|
||||
if evaluate_body:
|
||||
def choose_metadata_to_eval(self, context, concept):
|
||||
if context.in_context(BuiltinConcepts.EVAL_BODY_REQUESTED):
|
||||
return ["pre", "post", "props", "body", "where"]
|
||||
|
||||
metadata = ["pre", "post"] + self.needed_metadata(concept) + ["where"]
|
||||
metadata = ["pre", "post"]
|
||||
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")
|
||||
|
||||
return metadata
|
||||
|
||||
def needed_metadata(self, concept):
|
||||
def needed_metadata(self, concept, metadata):
|
||||
"""
|
||||
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:
|
||||
:param metadata:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if metadata not in concept.compiled:
|
||||
return []
|
||||
|
||||
return_values = concept.compiled[metadata]
|
||||
if not isinstance(return_values, list):
|
||||
return []
|
||||
|
||||
needed = []
|
||||
|
||||
for metadata in (ConceptParts.PRE, ConceptParts.POST, ConceptParts.WHERE):
|
||||
if metadata not in concept.compiled:
|
||||
for return_value in return_values:
|
||||
if not self.sheerka.isinstance(return_value, BuiltinConcepts.RETURN_VALUE):
|
||||
continue
|
||||
|
||||
return_values = concept.compiled[metadata]
|
||||
if not isinstance(return_values, list):
|
||||
if not return_value.status:
|
||||
continue
|
||||
|
||||
for return_value in return_values:
|
||||
if not self.sheerka.isinstance(return_value, BuiltinConcepts.RETURN_VALUE):
|
||||
continue
|
||||
if not self.sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT):
|
||||
continue
|
||||
|
||||
if not return_value.status:
|
||||
continue
|
||||
if not isinstance(return_value.body.source, str):
|
||||
continue
|
||||
|
||||
if not self.sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT):
|
||||
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 not isinstance(return_value.body.source, str):
|
||||
continue
|
||||
if "self" in return_value.body.source:
|
||||
needed.append("body")
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user