Added first implementation of concepts ambiguity resolution + Jenkins file test
This commit is contained in:
@@ -7,7 +7,7 @@ import core.ast.nodes
|
||||
import core.utils
|
||||
from core.ast.visitors import UnreferencedNamesVisitor
|
||||
from core.builtin_concepts import BuiltinConcepts, ParserResultConcept
|
||||
from core.concept import ConceptParts, Concept
|
||||
from core.concept import ConceptParts, Concept, NotInit
|
||||
from core.sheerka.services.SheerkaFilter import Pipe
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||
from parsers.PythonParser import PythonNode
|
||||
@@ -73,15 +73,29 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
not_for_me = context.sheerka.new(BuiltinConcepts.NOT_FOR_ME, body=node)
|
||||
return sheerka.ret(self.name, False, not_for_me, parents=[return_value])
|
||||
|
||||
attr_under_eval = context.get_parents(lambda ec: ec.action == BuiltinConcepts.EVALUATING_ATTRIBUTE)
|
||||
if attr_under_eval:
|
||||
attr_under_eval = attr_under_eval[0]
|
||||
expression_only = attr_under_eval.action_context != ConceptParts.BODY
|
||||
|
||||
if expression_only and isinstance(node.ast_, ast.Module):
|
||||
# Module execution is forbidden in where, pre, post and ret concept parts
|
||||
security_error = sheerka.new(BuiltinConcepts.PYTHON_SECURITY_ERROR,
|
||||
prop=attr_under_eval.action_context,
|
||||
body=node.source)
|
||||
return sheerka.ret(self.name, False, security_error, parents=[return_value])
|
||||
else:
|
||||
expression_only = False
|
||||
|
||||
# get globals
|
||||
my_globals = self.get_globals(context, node)
|
||||
my_globals = self.get_globals(context, node, expression_only)
|
||||
context.log(f"globals={my_globals}", self.name)
|
||||
|
||||
all_possible_globals = self.get_all_possible_globals(context, my_globals)
|
||||
concepts_entries = None
|
||||
evaluated = BuiltinConcepts.NOT_INITIALIZED
|
||||
errors = []
|
||||
expect_success = BuiltinConcepts.EVAL_SUCCESS_REQUESTED in context.local_hints
|
||||
expect_success = BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED in context.local_hints
|
||||
for globals_ in all_possible_globals:
|
||||
try:
|
||||
# eval
|
||||
@@ -117,14 +131,27 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
context.log(f"{evaluated=}", self.name)
|
||||
return sheerka.ret(self.name, True, evaluated, parents=[return_value])
|
||||
|
||||
def get_globals(self, context, node):
|
||||
def get_globals(self, context, node, expression_only):
|
||||
"""
|
||||
Creates the global variables for python source code evaluation
|
||||
:param context:
|
||||
:param node:
|
||||
:param expression_only: most of the commands are refused
|
||||
:return:
|
||||
"""
|
||||
my_globals = {
|
||||
"Concept": core.concept.Concept,
|
||||
"BuiltinConcepts": core.builtin_concepts.BuiltinConcepts,
|
||||
"in_context": context.in_context
|
||||
}
|
||||
|
||||
if expression_only:
|
||||
# disable builtin
|
||||
my_globals["__builtins__"] = None
|
||||
|
||||
# has to be the first, to allow override
|
||||
method_from_sheerka = self.update_globals_with_sheerka_methods(my_globals, context)
|
||||
method_from_sheerka = self.update_globals_with_sheerka_methods(my_globals, context, expression_only)
|
||||
|
||||
self.update_globals_with_context(my_globals, context)
|
||||
already_know = set(my_globals.keys())
|
||||
self.update_globals_with_node(my_globals, context, node, already_know)
|
||||
@@ -136,32 +163,54 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
return my_globals
|
||||
|
||||
@staticmethod
|
||||
def update_globals_with_sheerka_methods(my_locals, context):
|
||||
def update_globals_with_sheerka_methods(my_locals, context, expression_only):
|
||||
# methods_from_sheerka = {}
|
||||
#
|
||||
# # Make sure that methods that need the concept are correctly wrapped
|
||||
# for method_name, method in context.sheerka.sheerka_methods.items():
|
||||
# if expression_only and method.has_side_effect:
|
||||
# continue
|
||||
#
|
||||
# if method_name in context.sheerka.methods_with_context:
|
||||
# methods_from_sheerka[method_name] = inject_context(context)(method.method)
|
||||
# else:
|
||||
# methods_from_sheerka[method_name] = method.method
|
||||
methods_from_sheerka = {}
|
||||
|
||||
# Make sure that methods that need the concept are correctly wrapped
|
||||
for method_name, method in context.sheerka.sheerka_methods.items():
|
||||
if method_name in context.sheerka.methods_with_context:
|
||||
methods_from_sheerka[method_name] = inject_context(context)(method)
|
||||
else:
|
||||
methods_from_sheerka[method_name] = method
|
||||
|
||||
# Add all the methods as a direct access
|
||||
for method_name, method in methods_from_sheerka.items():
|
||||
my_locals[method_name] = method
|
||||
for method_name, method in context.sheerka.sheerka_methods.items():
|
||||
if expression_only and method.has_side_effect:
|
||||
continue
|
||||
|
||||
if method_name in context.sheerka.methods_with_context:
|
||||
my_locals[method_name] = inject_context(context)(method.method)
|
||||
else:
|
||||
my_locals[method_name] = method.method
|
||||
methods_from_sheerka[method_name] = my_locals[method_name]
|
||||
|
||||
# Add pipeable functions
|
||||
for func_name, function in context.sheerka.sheerka_pipeables.items():
|
||||
my_locals[func_name] = Pipe(function, context)
|
||||
if expression_only and function.has_side_effect:
|
||||
continue
|
||||
|
||||
my_locals[func_name] = Pipe(function.method, context)
|
||||
|
||||
return methods_from_sheerka # to allow access using prefix "sheerka."
|
||||
|
||||
def update_globals_with_context(self, my_globals, context):
|
||||
"""
|
||||
Update globals with the current object being evaluated (and its variables)
|
||||
:param my_globals:
|
||||
:param context:
|
||||
:return:
|
||||
"""
|
||||
if context.obj:
|
||||
context.log(f"Concept '{context.obj}' is in context. Adding it and its properties to locals.", self.name)
|
||||
|
||||
for prop_name in context.obj.variables():
|
||||
my_globals[prop_name] = context.obj.get_value(prop_name)
|
||||
value = context.obj.get_value(prop_name)
|
||||
if value != NotInit:
|
||||
my_globals[prop_name] = value
|
||||
my_globals["self"] = context.obj
|
||||
|
||||
def update_globals_with_node(self, my_globals, context, node, already_known):
|
||||
@@ -202,19 +251,11 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
context.log(f"Concept {name} is already evaluated.", self.name)
|
||||
else:
|
||||
context.log(f"Evaluating '{concept}'", self.name)
|
||||
with context.push(BuiltinConcepts.EVALUATE_CONCEPT,
|
||||
concept,
|
||||
who=self.name,
|
||||
desc=f"Evaluating '{concept}'",
|
||||
obj=concept) as sub_context:
|
||||
sub_context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
evaluated = context.sheerka.evaluate_concept(sub_context, concept)
|
||||
sub_context.add_values(return_values=evaluated)
|
||||
|
||||
if evaluated.key != concept.key:
|
||||
context.log(f"Error while evaluating '{name}'. Skipping.", self.name)
|
||||
continue
|
||||
concept = evaluated
|
||||
evaluated = context.sheerka.evaluate_concept(context, concept, eval_body=True)
|
||||
if evaluated.key != concept.key:
|
||||
context.log(f"Error while evaluating '{name}'. Skipping.", self.name)
|
||||
continue
|
||||
concept = evaluated
|
||||
|
||||
my_globals[name] = concept
|
||||
|
||||
@@ -293,7 +334,7 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
last_ast = copy.deepcopy(code_ast)
|
||||
last_ast.body = code_ast.body[-1:]
|
||||
|
||||
exec(compile(init_ast, "<ast>", "exec"), {}, my_locals)
|
||||
exec(compile(init_ast, "<ast>", "exec"), my_globals, my_locals)
|
||||
if type(last_ast.body[0]) == ast.Expr:
|
||||
return eval(compile(self.expr_to_expression(last_ast.body[0]), "<ast>", "eval"), my_globals, my_locals)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user