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
+72 -31
View File
@@ -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: