Files
Sheerka-Old/tests/evaluators/test_PythonEvaluator.py
T

205 lines
7.9 KiB
Python

import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import Concept, CB
from core.sheerka.services.SheerkaExecute import ParserInput
from evaluators.PythonEvaluator import PythonEvaluator, PythonEvalError
from parsers.PythonParser import PythonNode, PythonParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
def get_concept_name(concept):
return concept.name
class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("ret_val, expected", [
(ReturnValueConcept("some_name", True, ParserResultConcept(value=PythonNode("", None))), True),
(ReturnValueConcept("some_name", True, ParserResultConcept(value="other thing")), False),
(ReturnValueConcept("some_name", False, "not relevant"), False),
(ReturnValueConcept("some_name", True, Concept()), False)
])
def test_i_can_match(self, ret_val, expected):
context = self.get_context()
assert PythonEvaluator().matches(context, ret_val) == expected
@pytest.mark.parametrize("text, expected", [
("1 + 1", 2),
("test()", "I have access to Sheerka !"),
("sheerka.test()", "I have access to Sheerka !"),
("a=10\na", 10),
])
def test_i_can_eval(self, text, expected):
context = self.get_context()
parsed = PythonParser().parse(context, ParserInput(text))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value == expected
def test_i_can_eval_using_context(self):
context = self.get_context()
parsed = PythonParser().parse(context, ParserInput("test_using_context('value for param1', 10)"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value.startswith("I have access to Sheerka ! param1='value for param1', param2=10, event=")
def test_i_can_eval_using_context_when_self_is_not_sheerka(self):
sheerka, context = self.init_concepts()
parsed = PythonParser().parse(context, ParserInput("create_new_concept(Concept('foo'))"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert sheerka.has_key("foo")
@pytest.mark.parametrize("concept", [
Concept("foo"),
Concept("foo", body="2"),
Concept("foo").def_var("prop", "'a'"),
Concept("foo", body="bar")
])
def test_simple_concepts_are_not_for_me(self, concept):
context = self.get_context()
context.sheerka.add_in_cache(Concept("foo"))
parsed = PythonParser().parse(context, ParserInput("foo"))
evaluated = PythonEvaluator().eval(context, parsed)
assert not evaluated.status
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.NOT_FOR_ME)
def test_i_can_eval_ast_expression_that_references_concepts(self):
"""
I can test modules with variables
:return:
"""
context = self.get_context()
context.sheerka.add_in_cache(Concept("foo", body="1"))
parsed = PythonParser().parse(context, ParserInput("foo + 2"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value == 3
def test_i_can_eval_ast_module_that_references_concepts(self):
"""
I can test modules with variables
:return:
"""
context = self.get_context()
context.sheerka.add_in_cache(Concept("foo"))
parsed = PythonParser().parse(context, ParserInput("def a(b):\n return b\na(c:foo:)"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value == Concept("foo").init_key()
def test_i_can_eval_ast_module_that_references_concepts_with_body(self):
"""
I can test modules with variables
:return:
"""
sheerka, context, foo = self.init_concepts(Concept("foo", body="2"))
parsed = PythonParser().parse(context, ParserInput("def a(b):\n return b\na(foo)"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value == 2
def test_i_can_eval_concept_token(self):
context = self.get_context()
context.sheerka.add_in_cache(Concept("foo", body="2"))
parsed = PythonParser().parse(context, ParserInput("get_concept_name(c:foo:)"))
python_evaluator = PythonEvaluator()
python_evaluator.globals["get_concept_name"] = get_concept_name
evaluated = python_evaluator.eval(context, parsed)
assert evaluated.status
assert evaluated.value == "foo"
def test_i_can_call_function_with_complex_concepts(self):
sheerka, context, plus, mult = self.init_concepts(
self.from_def_concept("plus", "a plus b", ["a", "b"]),
self.from_def_concept("mult", "a mult b", ["a", "b"]),
)
parsed = PythonParser().parse(context, ParserInput("is_greater_than(BuiltinConcepts.PRECEDENCE, mult, plus)"))
python_evaluator = PythonEvaluator()
evaluated = python_evaluator.eval(context, parsed)
assert evaluated.status
assert sheerka.get_concepts_weights(BuiltinConcepts.PRECEDENCE) == {'1001': 1, '1002': 2}
def test_i_can_define_variables(self):
sheerka, context = self.init_concepts()
parsed = PythonParser().parse(context, ParserInput("a=10"))
python_evaluator = PythonEvaluator()
python_evaluator.eval(context, parsed)
parsed = PythonParser().parse(context, ParserInput("a"))
evaluated = python_evaluator.eval(context, parsed)
assert evaluated.status
assert evaluated.body == 10
def test_i_can_get_all_possibles_globals(self):
sheerka, context, foo = self.init_concepts(Concept("foo", body="foo").auto_init())
python_evaluator = PythonEvaluator()
my_globals = {
"a": "a string",
"b": self.test_i_can_get_all_possibles_globals,
"foo": foo
}
all_globals = python_evaluator.get_all_possible_globals(context, my_globals)
assert len(all_globals) == 2
assert all_globals[0]["foo"] == 'foo'
assert all_globals[1]["foo"] == CB(foo, "foo") # body is evaluated
def test_i_can_detect_one_error(self):
sheerka, context, foo = self.init_concepts("foo")
parsed = PythonParser().parse(context, ParserInput("foo + 1"))
evaluated = PythonEvaluator().eval(context, parsed)
assert not evaluated.status
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.ERROR)
error = evaluated.body.body
assert isinstance(error, PythonEvalError)
assert isinstance(error.error, TypeError)
assert error.error.args[0] == "unsupported operand type(s) for +: 'Concept' and 'int'"
assert error.concepts == {'foo': foo}
def test_i_can_detect_multiple_errors(self):
sheerka, context, foo = self.init_concepts(Concept("foo", body="'string'"))
parsed = PythonParser().parse(context, ParserInput("foo + 1"))
evaluated = PythonEvaluator().eval(context, parsed)
assert not evaluated.status
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.TOO_MANY_ERRORS)
error0 = evaluated.body.body[0]
assert isinstance(error0, PythonEvalError)
assert isinstance(error0.error, TypeError)
assert error0.error.args[0] == 'can only concatenate str (not "int") to str'
assert error0.concepts == {'foo': 'string'}
error1 = evaluated.body.body[1]
assert isinstance(error1, PythonEvalError)
assert isinstance(error1.error, TypeError)
assert error1.error.args[0] == "unsupported operand type(s) for +: 'Concept' and 'int'"
assert error1.concepts == {'foo': CB(foo, 'string')}