89e1f20975
Fixed #130 : ArithmeticOperatorParser Fixed #129 : python_wrapper : create_namespace Fixed #128 : ExpressionParser: Cannot parse func(x) infixed concept 'xxx'
217 lines
10 KiB
Python
217 lines
10 KiB
Python
import pytest
|
|
|
|
from core.builtin_concepts_ids import BuiltinConcepts
|
|
from core.builtin_helpers import ensure_asts
|
|
from core.concept import Concept
|
|
from core.global_symbols import SyaAssociativity
|
|
from core.sheerka.ExecutionContext import ExecutionContext
|
|
from core.sheerka.services.SheerkaAdmin import SheerkaAdmin
|
|
from sheerkapython.python_wrapper import Expando, MethodAccessError, Pipe, create_namespace, get_sheerka_method, \
|
|
get_variables_from_concept_asts, inject_context
|
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|
|
|
|
|
class TestPythonWrapper(TestUsingMemoryBasedSheerka):
|
|
|
|
@pytest.mark.parametrize("name, expected", [
|
|
("Concept", Concept),
|
|
("BuiltinConcepts", BuiltinConcepts),
|
|
("Expando", Expando),
|
|
("ExecutionContext", ExecutionContext),
|
|
("SyaAssociativity", SyaAssociativity),
|
|
])
|
|
def test_i_can_create_namespace_from_internal_references(self, name, expected):
|
|
context = self.get_context()
|
|
|
|
assert create_namespace(context, "TestPythonWrapper", [name], None, {}, False) == {name: expected}
|
|
|
|
def test_i_can_create_namespace_with_context_method(self):
|
|
context = self.get_context()
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["in_context", "isinstance"], None, {}, False)
|
|
assert res["in_context"] == context.in_context
|
|
assert res["isinstance"] == context.sheerka.services[SheerkaAdmin.NAME].extended_isinstance
|
|
|
|
def test_i_can_create_namespace_when_sheerka_expando_object(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["sheerka"], set(), {}, False)
|
|
assert res["sheerka"] == Expando("sheerka", {})
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["sheerka"], {"test", "set_debug"}, {}, False)
|
|
assert isinstance(res["sheerka"], Expando)
|
|
assert res["sheerka"].get_name() == "sheerka"
|
|
assert set(vars(res["sheerka"])) == {"_Expando__name", "test", "set_debug"}
|
|
|
|
def test_i_can_create_namespace_when_short_term_memory(self):
|
|
context = self.get_context()
|
|
context.add_to_short_term_memory("my_key", "my_value")
|
|
|
|
assert create_namespace(context, "TestPythonWrapper", ["my_key"], None, {}, False) == {"my_key": "my_value"}
|
|
|
|
def test_i_can_create_namespace_when_value_from_memory(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
|
|
sheerka.add_to_memory(context, "my_key", "my_value")
|
|
assert create_namespace(context, "TestPythonWrapper", ["my_key"], None, {}, False) == {"my_key": "my_value"}
|
|
|
|
def test_i_can_create_namespace_when_sheerka_methods(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
res = create_namespace(context, "TestPythonWrapper", ["test", "set_debug"], None, {}, False)
|
|
|
|
assert res["test"] == sheerka.test
|
|
assert isinstance(res["set_debug"], type(inject_context))
|
|
assert res["set_debug"].__name__ == "set_debug"
|
|
|
|
def test_i_can_create_namespace_when_value_from_context_obj(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
obj = Concept("foo").def_var("a", "value1").auto_init()
|
|
context.obj = obj
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["self", "a"], None, {}, False)
|
|
assert res == {"self": obj, "a": "value1"}
|
|
|
|
def test_i_can_create_namespace_when_value_from_local_objects(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
obj = Concept("foo")
|
|
objects = {"self": obj, "a": Concept("bar")}
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["self", "a"], None, objects, False)
|
|
assert res == {"self": obj, "a": objects["a"]}
|
|
|
|
def test_i_can_create_namespace_when_name_refers_to_a_concept(self):
|
|
sheerka, context, foo = self.init_concepts("foo")
|
|
|
|
assert create_namespace(context, "TestPythonWrapper", ["foo"], None, {}, False) == {"foo": foo}
|
|
|
|
def test_internal_references_and_context_method_take_over_short_term_memory(self):
|
|
context = self.get_context()
|
|
context.add_to_short_term_memory("Concept", "short_term_value")
|
|
context.add_to_short_term_memory("isinstance", "short_term_value")
|
|
context.add_to_short_term_memory("in_context", "short_term_value")
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["Concept", "isinstance", "in_context"], None, {}, False)
|
|
|
|
assert res == {
|
|
"Concept": Concept,
|
|
"isinstance": context.sheerka.services[SheerkaAdmin.NAME].extended_isinstance,
|
|
"in_context": context.in_context,
|
|
}
|
|
|
|
def test_short_term_memory_takes_precedence_over_long_term_memory(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
|
|
context.add_to_short_term_memory("my_key", "short_term")
|
|
sheerka.add_to_memory(context, "my_key", "long_term")
|
|
|
|
assert create_namespace(context, "TestPythonWrapper", ["my_key"], None, {}, False) == {"my_key": "short_term"}
|
|
|
|
def test_long_term_memory_takes_precedence_over_sheerka_methods(self):
|
|
# I am not really sure why
|
|
sheerka, context = self.init_test().unpack()
|
|
|
|
sheerka.add_to_memory(context, "test", "from memory")
|
|
assert create_namespace(context, "TestPythonWrapper", ["test"], None, {}, False) == {"test": "from memory"}
|
|
|
|
def test_sheerka_method_takes_precedence_over_context_obj(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
obj = Concept("foo").def_var("test", "value1").auto_init()
|
|
context.obj = obj
|
|
|
|
assert create_namespace(context, "TestPythonWrapper", ["test", ], None, {}, False) == {"test": sheerka.test}
|
|
|
|
def test_context_obj_takes_precedence_over_local_objects(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
obj = Concept("foo").def_var("a", "value1").auto_init()
|
|
context.obj = obj
|
|
objects = {"self": Concept("bar"), "a": Concept("bar")}
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["self", "a"], None, objects, False)
|
|
assert res == {"self": obj, "a": "value1"}
|
|
|
|
def test_local_objects_take_precedence_over_object_instantiation(self):
|
|
sheerka, context, foo = self.init_concepts("from instantiation")
|
|
objects = {"foo": Concept("from local")}
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["foo"], None, objects, False)
|
|
assert res == {"foo": objects["foo"]}
|
|
|
|
def test_external_value_takes_precedence_over_concept_parameter(self):
|
|
"""
|
|
To manage :
|
|
Concept("x is a y").def_var("x").def_var("y"),
|
|
"y is a number" -> "call_concept(__o_00__, x=y)"
|
|
If 'y' is not given, it will use the concept parameter 'y'
|
|
But if y is given (as a short term memory) it must be prioritized
|
|
:return:
|
|
"""
|
|
sheerka, context = self.init_test().unpack()
|
|
obj = Concept("x is a y").def_var("x").def_var("y", "concept value").auto_init()
|
|
context.obj = obj
|
|
objects = {"y": "object value"}
|
|
|
|
res = create_namespace(context, "TestPythonWrapper", ["y"], None, objects, False)
|
|
assert res == {'y': 'concept value'}
|
|
|
|
context.add_to_short_term_memory("y", "stm value")
|
|
res = create_namespace(context, "TestPythonWrapper", ["y"], None, objects, False)
|
|
assert res == {'y': 'stm value'}
|
|
|
|
def test_i_can_get_sheerka_method(self):
|
|
context = self.get_context()
|
|
|
|
# sheerka direct method
|
|
assert get_sheerka_method(context, "TestPythonWrapper", "test", True) == context.sheerka.test
|
|
|
|
# sheerka indirect method
|
|
assert get_sheerka_method(context, "TestPythonWrapper", "get_value", True) == context.sheerka.get_value
|
|
|
|
# method that need context are wrapped
|
|
res = get_sheerka_method(context, "TestPythonWrapper", "test_using_context", True)
|
|
assert res != context.sheerka.test_using_context
|
|
assert type(res) == type(inject_context)
|
|
assert res.__name__ == "test_using_context"
|
|
|
|
# return None when the method is not found
|
|
assert get_sheerka_method(context, "TestPythonWrapper", "xxx", True) is None
|
|
|
|
def test_i_cannot_get_method_that_modifies_the_state_when_expression_only(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
|
|
assert get_sheerka_method(context, "TestPythonWrapper", "set_debug", expression_only=False) is not None
|
|
|
|
with pytest.raises(MethodAccessError) as ex:
|
|
get_sheerka_method(context, "TestPythonWrapper", "set_debug", expression_only=True)
|
|
assert ex.value.method_name == "set_debug"
|
|
|
|
def test_i_can_get_method_when_pipe_function(self):
|
|
context = self.get_context()
|
|
|
|
res = get_sheerka_method(context, "TestPythonWrapper", "where", True)
|
|
assert isinstance(res, Pipe)
|
|
|
|
@pytest.mark.parametrize("concept, known_variables, expected", [
|
|
(Concept("foo").def_var("x", "True"), set(), {}),
|
|
(Concept("foo").def_var("x"), set(), {}),
|
|
(Concept("foo").def_var("x", "self"), set(), {"x": {"self"}}),
|
|
(Concept("foo").def_var("x", "self + a"), set(), {"x": {"self", "a"}}),
|
|
(Concept("foo").def_var("x", "self + a").def_var("y", "b"), set(), {'x': {'a', 'self'}, 'y': {'b'}}),
|
|
(Concept("foo", body="x").def_var("x"), set(), {}), # 'x' is a concept var, so it can be resolved
|
|
(Concept("foo", body="x").def_var("x", "x"), set(), {'x': {'x'}}),
|
|
(Concept("foo").def_var("x", "func(y)"), set(), {"x": {"y"}}),
|
|
(Concept("foo").def_var("x", "x"), set(), {'x': {'x'}}),
|
|
(Concept("foo").def_var("x", "y"), set(), {'x': {'y'}}),
|
|
(Concept("foo").def_var("x", "x"), {"x"}, {"x": {"x"}}),
|
|
(Concept("foo").def_var("x"), {"x"}, {}), # var x has no value, there no way to link the two 'x's
|
|
(Concept("foo", body="x").def_var("x"), {"x"}, {"#body#": {"x"}}),
|
|
(Concept("foo").def_var("x", "bar"), set(), {}),
|
|
(Concept("foo").def_var("x", "bar"), {"bar"}, {"x": {"bar"}}),
|
|
])
|
|
def test_get_variables_from_concept_asts(self, concept, known_variables, expected):
|
|
sheerka, context, foo, bar = self.init_concepts(concept, "bar")
|
|
|
|
ensure_asts(context, concept)
|
|
variables = get_variables_from_concept_asts(context, concept, known_variables, parameters_only=False)
|
|
|
|
assert variables == expected
|