87cab44fb8
Fixed #135: Change services service priorities Fixed #136: ErrorManager: Implement recognize_error Fixed #137: BNFNodeParser : Error when parsing regex with sub parsers Fixed #138: get_last_errors(): real errors sources are lost Fixed #139: OneError return value removes the origin of the error Fixed #140: Concept variables are not correctly handled when parsing sub expression Fixed #143: Implement has_unknown_concepts()
242 lines
10 KiB
Python
242 lines
10 KiB
Python
from dataclasses import dataclass
|
|
|
|
import pytest
|
|
|
|
from core.builtin_concepts import NotFoundConcept
|
|
from core.builtin_concepts_ids import BuiltinConcepts
|
|
from core.concept import Concept
|
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|
|
|
|
|
@dataclass
|
|
class A:
|
|
prop1: object
|
|
prop2: object
|
|
|
|
def __eq__(self, other):
|
|
if not isinstance(other, A):
|
|
return False
|
|
|
|
return self.prop1 == other.prop1 and self.prop2 == other.prop2
|
|
|
|
def __hash__(self):
|
|
hash_res = []
|
|
for p in [self.prop1, self.prop2]:
|
|
hash_res.append(0 if isinstance(p, (list, dict, set)) else p)
|
|
|
|
return hash(tuple(hash_res))
|
|
|
|
|
|
@dataclass
|
|
class B(A):
|
|
|
|
def as_bag(self):
|
|
return {
|
|
"fake_prop1": self.prop1,
|
|
"fake_prop2": self.prop2
|
|
}
|
|
|
|
def __hash__(self):
|
|
return hash((self.prop1, self.prop2))
|
|
|
|
|
|
class TestSheerkaQueryManager(TestUsingMemoryBasedSheerka):
|
|
def test_i_can_filter_objects_using_kwargs(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
|
|
|
|
assert sheerka.filter_objects(context, lst, prop1="a21") == [lst[1]]
|
|
assert sheerka.filter_objects(context, lst, prop2=10) == [lst[0]]
|
|
assert sheerka.filter_objects(context, lst, prop2=3.14) == [lst[1]]
|
|
assert sheerka.filter_objects(context, lst, prop2=0xab) == [lst[2]]
|
|
assert sheerka.filter_objects(context, lst, prop1=[0, 1]) == [lst[3]]
|
|
assert sheerka.filter_objects(context, lst, prop2={"key": "value"}) == [lst[3]]
|
|
# assert sheerka.filter_objects(context, lst, prop1={1, "v"}) == [lst[2]] set are not supported
|
|
|
|
# complex properties
|
|
assert sheerka.filter_objects(context, lst, prop1_contains="a") == [lst[0], lst[1]]
|
|
assert sheerka.filter_objects(context, lst, prop1_contains=1) == [lst[2], lst[3]]
|
|
|
|
def test_i_can_filter_by_object_type(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", "a12"), Concept("foo", body="a").auto_init(), Concept("foo", body="b").auto_init()]
|
|
|
|
assert sheerka.filter_objects(context, lst, __type="foo") == [lst[1], lst[2]]
|
|
|
|
def test_i_can_filter_on_as_bag_property(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [B("a11", "a12"), B("a21", "a22"), B("a31", "a32")]
|
|
|
|
assert sheerka.filter_objects(context, lst, fake_prop1="a21") == [lst[1]]
|
|
|
|
def test_i_can_filter_container(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
|
|
container = sheerka.new(BuiltinConcepts.EXPLANATION, body=lst, digest="xxx", command="text")
|
|
|
|
res = sheerka.filter_objects(context, container, prop1="a21")
|
|
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
|
assert res.digest == "xxx"
|
|
assert res.command == "text"
|
|
assert res.body == [lst[1]]
|
|
|
|
def test_i_can_filter_when_property_does_not_exist(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", "a12"), B("a21", "a22"), B("a31", "a32")]
|
|
|
|
assert sheerka.filter_objects(context, lst, prop1="a11") == [lst[0]]
|
|
|
|
def test_i_can_filter_objets_using_predicate(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10),
|
|
A("a21", 3.14),
|
|
A({1, "v"}, 0xab),
|
|
A([0, 1], {"key": "value"}),
|
|
Concept("foo", body="a").auto_init(),
|
|
B("a21", "a22"),
|
|
Concept("foo", body="b").auto_init(),
|
|
B("a31", "a32")]
|
|
|
|
assert sheerka.filter_objects(context, lst, predicate="self.prop1 == 'a21'") == [lst[1]]
|
|
assert sheerka.filter_objects(context, lst, predicate="self.prop2 >= 1") == [lst[0], lst[1], lst[2]]
|
|
assert sheerka.filter_objects(context, lst, predicate="get_type(self) == 'foo' ") == [lst[4], lst[6]]
|
|
assert sheerka.filter_objects(context, lst, predicate="self.fake_prop1 == 'a21' ") == [lst[5]]
|
|
assert sheerka.filter_objects(context, lst, predicate="hasattr(self, 'fake_prop1')") == [lst[5], lst[7]]
|
|
|
|
def test_i_can_filter_object_using_predicate_and_sheerka_objects(self):
|
|
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
|
|
lst = [foo, bar, A("a21", 3.14)]
|
|
|
|
assert sheerka.filter_objects(context, lst, predicate="self == bar") == [lst[1]]
|
|
|
|
def test_i_can_filter_objects_using_concept(self):
|
|
sheerka, context, foo, bar, isa = self.init_concepts(
|
|
"foo",
|
|
"bar",
|
|
Concept("x is a concept", body="isinstance(x, Concept)", pre="is_question()").def_var("x"),
|
|
create_new=True)
|
|
|
|
lst = [foo, A("a21", 3.14), bar, B("a21", 3.14)]
|
|
assert sheerka.filter_objects(context, lst, predicate="self is a concept") == [foo, bar]
|
|
|
|
def test_i_can_filter_objects_when_no_kwargs_and_no_predicate(self):
|
|
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
|
|
lst = [foo, bar, A("a21", 3.14)]
|
|
|
|
assert sheerka.filter_objects(context, lst) == lst
|
|
|
|
def test_i_can_filter_objects_after_applying_a_mapping(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10),
|
|
A("a21", 3.14)]
|
|
|
|
res = sheerka.filter_objects(context, lst, mapping=lambda o: o.prop1, predicate="self[1] == '1'")
|
|
assert res == [A("a11", 10)]
|
|
|
|
def test_i_can_filter_objects_using_concept_after_applying_a_mapping(self):
|
|
sheerka, context, foo, bar, isa = self.init_concepts(
|
|
"foo",
|
|
"bar",
|
|
Concept("x is a concept", body="isinstance(x, Concept)", pre="is_question()").def_var("x"),
|
|
create_new=True)
|
|
|
|
lst = [foo, A(foo, 3.14), bar, A(bar, 3.14)]
|
|
res = sheerka.filter_objects(context, lst, mapping=lambda o: o.prop1, predicate="self is a concept")
|
|
assert res == [lst[1], lst[3]]
|
|
|
|
def test_i_can_filter_objects_by_type(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", "a12"), Concept("foo"), NotImplementedError(), NotFoundConcept()]
|
|
|
|
assert sheerka.filter_objects(context, lst, __type="A") == [lst[0]]
|
|
assert sheerka.filter_objects(context, lst, __type="foo") == [lst[1]]
|
|
|
|
assert sheerka.filter_objects(context, lst, __type="NotImplementedError") == [lst[2]]
|
|
assert sheerka.filter_objects(context, lst, __type=NotImplementedError) == [lst[2]]
|
|
|
|
assert sheerka.filter_objects(context, lst, __type=BuiltinConcepts.NOT_FOUND) == [lst[3]]
|
|
assert sheerka.filter_objects(context, lst, __type=NotFoundConcept) == [lst[3]]
|
|
assert sheerka.filter_objects(context, lst, __type="NotFoundConcept") == [lst[3]]
|
|
|
|
def test_empty_list_is_returned_when_nothing_is_found(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", "a12")]
|
|
|
|
assert sheerka.filter_objects(context, lst, __type="foo") == []
|
|
assert sheerka.filter_objects(context, [], __type="foo") == []
|
|
assert sheerka.filter_objects(context, lst, predicate="self.name == 'bar'") == []
|
|
|
|
def test_i_must_select_object_property_using_string(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
|
|
with pytest.raises(SyntaxError):
|
|
sheerka.select_objects(context, [], 00)
|
|
|
|
def test_i_can_select_objects_with_args(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
|
|
|
|
assert sheerka.select_objects(context, lst, "prop1", "prop2") == (
|
|
('a11', 10),
|
|
('a21', 3.14),
|
|
({1, 'v'}, 171),
|
|
([0, 1], {'key': 'value'}))
|
|
|
|
def test_i_can_select_objects_when_container(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
|
|
container = sheerka.new(BuiltinConcepts.EXPLANATION, body=lst, digest="xxx", command="text")
|
|
|
|
res = sheerka.select_objects(context, container, "prop1", "prop2")
|
|
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
|
assert res.digest == "xxx"
|
|
assert res.command == "text"
|
|
assert res.body == (('a11', 10),
|
|
('a21', 3.14),
|
|
({1, 'v'}, 171),
|
|
([0, 1], {'key': 'value'}))
|
|
|
|
def test_i_can_select_objects_with_complicated_request(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab)]
|
|
|
|
assert sheerka.select_objects(context, lst, "self.prop2 + 5") == (15, 8.14, 0xab + 5)
|
|
assert sheerka.select_objects(context, lst, "isinstance(self.prop1, str)") == (True, True, False)
|
|
|
|
def test_error_when_collecting_returns_are_managed(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10), A("a21", {"key": "value"})]
|
|
res = sheerka.select_objects(context, lst, "self.prop2 + 5")
|
|
|
|
assert len(res) == 2
|
|
assert res[0] == 15
|
|
assert isinstance(res[1], TypeError)
|
|
|
|
def test_i_can_select_objects_using_kwargs(self):
|
|
sheerka, context = self.init_test().unpack()
|
|
lst = [A("a11", 10), A("a21", 3.14), A({1, "v"}, 0xab), A([0, 1], {"key": "value"})]
|
|
|
|
assert sheerka.select_objects(context, lst, p1="prop1", p2="prop2") == (
|
|
{"p1": "a11", "p2": 10},
|
|
{"p1": "a21", "p2": 3.14},
|
|
{"p1": {1, "v"}, "p2": 0xab},
|
|
{"p1": [0, 1], "p2": {"key": "value"}},
|
|
)
|
|
|
|
def test_i_can_collect_attributes(self):
|
|
sheerka = self.get_sheerka()
|
|
lst = [A("", ""),
|
|
B("", ""),
|
|
Concept("foo").def_var("a").auto_init(),
|
|
Concept("bar").def_var("y").def_var("x").auto_init()]
|
|
|
|
res = sheerka.collect_attributes(lst)
|
|
|
|
assert sheerka.isinstance(res, BuiltinConcepts.TO_DICT)
|
|
assert res.body == {
|
|
"A": ["prop1", "prop2"],
|
|
"B": ["fake_prop1", "fake_prop2"],
|
|
"foo": ["a", 'body', 'id', 'key', 'name'],
|
|
"bar": ['body', 'id', 'key', 'name', "x", "y"] # attributes are sorted
|
|
}
|