Reimplemented explain feature
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.sheerka.services.SheerkaFilter import Pipe, SheerkaFilter
|
||||
from printer.FormatInstructions import FormatInstructions, FormatDetailDesc, FormatDetailType
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
@dataclass
|
||||
class Obj:
|
||||
prop1: str
|
||||
prop2: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class ObjWithAsBag:
|
||||
prop1: str
|
||||
prop2: str
|
||||
|
||||
def as_bag(self):
|
||||
return {
|
||||
"first_prop": self.prop1,
|
||||
"second_prop": self.prop2,
|
||||
}
|
||||
|
||||
|
||||
class TestSheerkaFilter(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_pipe_using_decorator(self):
|
||||
@Pipe
|
||||
def is_ok_with_decorator(iterable):
|
||||
for item in iterable:
|
||||
yield item + " ok"
|
||||
|
||||
def exclamation(iterable):
|
||||
for item in iterable:
|
||||
yield item + "!"
|
||||
|
||||
res = ["one", "two", "three"] | is_ok_with_decorator | Pipe(exclamation)
|
||||
assert list(res) == ["one ok!", "two ok!", "three ok!"]
|
||||
|
||||
def test_i_can_pipe_function_with_context_as_first_parameter(self):
|
||||
def func_with_context(context, iterable, var_name):
|
||||
for item in iterable:
|
||||
yield f"{context.desc}: {var_name}={item}"
|
||||
|
||||
sheerka, context = self.init_concepts()
|
||||
context.desc = "desc"
|
||||
pipeable = Pipe(func_with_context, context)
|
||||
|
||||
assert pipeable.need_context
|
||||
assert list(["one", "two", "three"] | pipeable("var")) == ['desc: var=one', 'desc: var=two', 'desc: var=three']
|
||||
|
||||
def test_i_can_pipe_function_with_context_as_only_parameter(self):
|
||||
# This time, func_with_context does not have other parameter than context and iterable
|
||||
def func_with_context(context, iterable):
|
||||
for item in iterable:
|
||||
yield f"{context.desc}: var={item}"
|
||||
|
||||
sheerka, context = self.init_concepts()
|
||||
context.desc = "desc"
|
||||
pipeable = Pipe(func_with_context, context)
|
||||
|
||||
assert pipeable.need_context
|
||||
assert list(["one", "two", "three"] | pipeable) == ['desc: var=one', 'desc: var=two', 'desc: var=three']
|
||||
|
||||
def test_i_can_pipe_explanation_concept(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
execution_contexts = [context.push(desc=f"desc_{i}") for i in range(4)]
|
||||
explanation_node = sheerka.new(BuiltinConcepts.EXPLANATION, body=execution_contexts)
|
||||
|
||||
@Pipe
|
||||
def get_desc(iterable):
|
||||
for item in iterable:
|
||||
yield item.desc
|
||||
|
||||
res = explanation_node | get_desc
|
||||
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert list(res.body) == ["desc_0", "desc_1", "desc_2", "desc_3"] # body is modified
|
||||
|
||||
@pytest.mark.parametrize("predicate, expected", [
|
||||
("True", ["one", "two", "three"]),
|
||||
("self == 'two'", ["two"])
|
||||
])
|
||||
def test_i_can_filter(self, predicate, expected):
|
||||
filter_service = SheerkaFilter(None)
|
||||
|
||||
res = ["one", "two", "three"] | Pipe(filter_service.pipe_filter)(predicate)
|
||||
|
||||
assert list(res) == expected
|
||||
|
||||
def test_i_can_filter_obj(self):
|
||||
filter_service = SheerkaFilter(None)
|
||||
|
||||
lst = [Obj("a", "b"), Obj("c", "d")]
|
||||
predicate = "prop2 == 'd'"
|
||||
res = lst | Pipe(filter_service.pipe_filter)(predicate)
|
||||
|
||||
assert list(res) == [Obj("c", "d")]
|
||||
|
||||
def test_i_can_filter_obj_implementing_as_bag(self):
|
||||
filter_service = SheerkaFilter(None)
|
||||
|
||||
lst = [ObjWithAsBag("a", "b"), ObjWithAsBag("c", "d")]
|
||||
predicate = "second_prop == 'd'"
|
||||
res = lst | Pipe(filter_service.pipe_filter)(predicate)
|
||||
|
||||
assert list(res) == [ObjWithAsBag("c", "d")]
|
||||
|
||||
def test_i_can_manage_name_error(self):
|
||||
filter_service = SheerkaFilter(None)
|
||||
|
||||
lst = [Obj("a", "b"), Obj("c", "d"), ObjWithAsBag("a", "b"), ObjWithAsBag("c", "d")]
|
||||
predicate = "second_prop == 'd'" # 'second_prop' does not exist in Obj
|
||||
res = lst | Pipe(filter_service.pipe_filter)(predicate)
|
||||
|
||||
assert list(res) == [ObjWithAsBag("c", "d")]
|
||||
|
||||
def test_i_cannot_filter_if_the_predicate_is_incorrect(self):
|
||||
filter_service = SheerkaFilter(None)
|
||||
|
||||
lst = [Obj("a", "b"), Obj("c", "d")]
|
||||
predicate = "prop2 =="
|
||||
|
||||
with pytest.raises(SyntaxError):
|
||||
res = lst | Pipe(filter_service.pipe_filter)(predicate)
|
||||
list(res)
|
||||
|
||||
def test_i_can_format_l(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
|
||||
lst = [foo, bar]
|
||||
|
||||
res = lst | Pipe(SheerkaFilter.pipe_format_l)("my_format")
|
||||
res = list(res)
|
||||
|
||||
assert len(res) == 2
|
||||
format_instructions = res[0].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.format_l[f"c:{foo.id}:"] == "my_format"
|
||||
|
||||
format_instructions = res[1].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.format_l[f"c:{bar.id}:"] == "my_format"
|
||||
|
||||
def test_i_can_format_d(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
|
||||
lst = [foo, bar]
|
||||
|
||||
res = lst | Pipe(SheerkaFilter.pipe_format_d)("id", "name", "body", id="%red%{id}%reset%")
|
||||
res = list(res)
|
||||
|
||||
expected_props = {
|
||||
"id": "%red%{id}%reset%",
|
||||
"name": "{name}",
|
||||
"body": "{body}"
|
||||
}
|
||||
|
||||
assert len(res) == 2
|
||||
format_instructions = res[0].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.format_d[f"c:{foo.id}:"] == FormatDetailDesc(FormatDetailType.Props_In_Line, expected_props)
|
||||
|
||||
format_instructions = res[1].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.format_d[f"c:{bar.id}:"] == FormatDetailDesc(FormatDetailType.Props_In_Line, expected_props)
|
||||
|
||||
def test_i_can_format_d_all_properties(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
|
||||
lst = [foo, bar]
|
||||
|
||||
res = lst | Pipe(SheerkaFilter.pipe_format_d)()
|
||||
res = list(res)
|
||||
|
||||
expected_props = {
|
||||
'id': '{id}',
|
||||
'name': '{name}',
|
||||
'key': '{key}',
|
||||
'body': '{body}',
|
||||
'self': '{self}'
|
||||
}
|
||||
|
||||
assert len(res) == 2
|
||||
format_instructions = res[0].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.format_d[f"c:{foo.id}:"] == FormatDetailDesc(FormatDetailType.Props_In_Line, expected_props)
|
||||
|
||||
def test_i_can_set_recurse(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", "bar")
|
||||
lst = [foo, bar]
|
||||
|
||||
res = lst | Pipe(SheerkaFilter.pipe_recurse)(10)
|
||||
res = list(res)
|
||||
|
||||
assert len(res) == 2
|
||||
format_instructions = res[0].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.recursive_props["children"] == 10
|
||||
|
||||
format_instructions = res[1].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.recursive_props["children"] == 10
|
||||
|
||||
res = lst | Pipe(SheerkaFilter.pipe_recurse)(15, "other_prop")
|
||||
res = list(res)
|
||||
|
||||
assert len(res) == 2
|
||||
format_instructions = res[0].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.recursive_props["children"] == 10
|
||||
assert format_instructions.recursive_props["other_prop"] == 15
|
||||
@@ -0,0 +1,147 @@
|
||||
import types
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.sheerka.services.SheerkaResultManager import SheerkaResultConcept
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
sheerka = cls().get_sheerka()
|
||||
sheerka.save_execution_context = True
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
sheerka = cls().get_sheerka()
|
||||
sheerka.save_execution_context = False
|
||||
|
||||
def test_i_can_get_the_result_by_digest(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
digest = sheerka.get_last_execution().event.get_digest()
|
||||
|
||||
res = sheerka.get_results_by_digest(context, digest)
|
||||
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
assert sheerka.load(SheerkaResultConcept.NAME, "digest") == digest
|
||||
|
||||
previous_results = list(res.body)
|
||||
|
||||
# Second test,
|
||||
# I can get the result from the recorded digest
|
||||
res = sheerka.get_results(context)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
assert list(res.body) == previous_results
|
||||
|
||||
def test_i_cannot_get_result_by_digest_if_the_digest_does_not_exist(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
res = sheerka.get_results_by_digest(context, "fake digest")
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||
assert res.body == {'digest': 'fake digest'}
|
||||
|
||||
def test_i_cannot_get_results_if_no_previous_digest(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
assert sheerka.get_results(context) is None
|
||||
|
||||
def test_i_can_get_the_result_by_command_name(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
digest = sheerka.get_last_execution().event.get_digest()
|
||||
|
||||
sheerka.evaluate_user_input("one") # another command
|
||||
|
||||
res = sheerka.get_results_by_command(context, "def concept")
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
def test_i_can_get_the_result_by_command_when_not_in_the_same_page_size(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
|
||||
service = SheerkaResultConcept(sheerka, 2)
|
||||
res = service.get_results_by_command(context, "def concept")
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
|
||||
def test_i_cannot_get_results_from_command_if_the_command_does_not_exist(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
res = sheerka.get_results_by_command(context, "def concept")
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||
assert res.body == {'command': 'def concept'}
|
||||
|
||||
def test_i_cannot_get_result_from_command_if_the_command_does_not_exists_multiple_pages(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
|
||||
service = SheerkaResultConcept(sheerka, 2)
|
||||
res = service.get_results_by_command(context, "fake command")
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||
assert res.body == {'command': 'fake command'}
|
||||
|
||||
def test_i_can_get_last_results(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one")
|
||||
|
||||
res = sheerka.get_last_results(context)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "one"
|
||||
|
||||
def test_i_can_get_last_results_when_event_with_no_result(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
sheerka.sdp.save_event(Event("event 1"))
|
||||
sheerka.sdp.save_event(Event("event 2"))
|
||||
sheerka.sdp.save_event(Event("event 3"))
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
|
||||
res = sheerka.get_last_results(context)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
|
||||
def test_i_cannot_get_last_results_when_no_result(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
res = sheerka.get_last_results(context)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||
assert res.body == {'query': 'last'}
|
||||
|
||||
def test_i_cannot_get_last_results_when_only_events(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
sheerka.sdp.save_event(Event("event 1"))
|
||||
sheerka.sdp.save_event(Event("event 2"))
|
||||
sheerka.sdp.save_event(Event("event 3"))
|
||||
|
||||
res = sheerka.get_last_results(context)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||
assert res.body == {'query': 'last'}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ from dataclasses import dataclass
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts
|
||||
from parsers.ExpressionParser import TrueNode, LambdaNode
|
||||
from core.sheerka.services.SheerkaFilter import Pipe, SheerkaFilter
|
||||
from printer.Formatter import Formatter, BraceToken
|
||||
from printer.SheerkaPrinter import FormatInstructions
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
@@ -149,7 +150,43 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
|
||||
(None)level33
|
||||
"""
|
||||
|
||||
def test_i_can_format_concept(self, capsys):
|
||||
def test_i_can_format_l_concepts_using_default_format_l_definition(self, capsys):
|
||||
# default format_l definition
|
||||
# for all obj of a given type
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Concept("foo a b").def_var("a").def_var("b").init_key()
|
||||
foo.set_value("a", "value a").set_value("b", "value b")
|
||||
foo.set_value(ConceptParts.BODY, "body")
|
||||
sheerka.set_id_if_needed(foo, False)
|
||||
|
||||
sheerka.printer_handler.register_format_l(foo, "DEFAULT:{id}-{name}-{key}-{body}-{a}-{b}")
|
||||
|
||||
sheerka.print(foo)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "DEFAULT:1001-foo a b-foo __var__0 __var__1-body-value a-value b\n"
|
||||
|
||||
def test_i_can_format_l_concepts_using_context_format_l_definition(self, capsys):
|
||||
# context format_l definition
|
||||
# for all obj of a given type in the current print call
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Concept("foo a b").def_var("a").def_var("b").init_key()
|
||||
foo.set_value("a", "value a").set_value("b", "value b")
|
||||
foo.set_value(ConceptParts.BODY, "body")
|
||||
sheerka.set_id_if_needed(foo, False)
|
||||
|
||||
sheerka.printer_handler.register_format_l(foo, "DEFAULT:{id}-{name}-{key}-{body}-{a}-{b}")
|
||||
context_instructions = FormatInstructions().set_format_l(foo, "CONTEXT:{id}-{name}-{key}-{body}-{a}-{b}")
|
||||
|
||||
sheerka.print(foo, context_instructions)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "CONTEXT:1001-foo a b-foo __var__0 __var__1-body-value a-value b\n"
|
||||
|
||||
def test_i_can_format_l_concepts_using_item_format_l_definition(self, capsys):
|
||||
# item format_l definition
|
||||
# for the item only
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Concept("foo a b").def_var("a").def_var("b").init_key()
|
||||
foo.set_value("a", "value a").set_value("b", "value b")
|
||||
@@ -157,12 +194,16 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
|
||||
sheerka.set_id_if_needed(foo, False)
|
||||
|
||||
sheerka.printer_handler.register_format_l(foo, "{id}-{name}-{key}-{body}-{a}-{b}")
|
||||
context_instructions = FormatInstructions().set_format_l(foo, "CONTEXT:{id}-{name}-{key}-{body}-{a}-{b}")
|
||||
item_instructions = FormatInstructions().set_format_l(foo, "ITEM:{id}-{name}-{key}-{body}-{a}-{b}")
|
||||
|
||||
sheerka.print(foo)
|
||||
foo.set_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS, item_instructions)
|
||||
|
||||
sheerka.print(foo, context_instructions)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "1001-foo a b-foo __var__0 __var__1-body-value a-value b\n"
|
||||
assert captured.out == "ITEM:1001-foo a b-foo __var__0 __var__1-body-value a-value b\n"
|
||||
|
||||
def test_i_can_format_object(self, capsys):
|
||||
def test_i_can_format_l_objects(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Obj("value a", "value b")
|
||||
|
||||
@@ -172,6 +213,21 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "value a-value b\n"
|
||||
|
||||
def test_i_can_format_l_execution_context(self, capsys):
|
||||
# In this test, no format_l definition is provided
|
||||
# The system knows how to format ExecutionContext
|
||||
sheerka = self.get_sheerka()
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
execution_context = context.push("test_sheerka_printer", "Testing Execution Context Printing")
|
||||
ret_val = sheerka.ret("test_sheerka_printer", True, sheerka.new(BuiltinConcepts.SUCCESS))
|
||||
execution_context.add_values(return_value=ret_val)
|
||||
ec = execution_context.as_bag()
|
||||
|
||||
sheerka.print(execution_context)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == f"[{ec['id']:3}] {ec['desc']} ({ec['status']})\n"
|
||||
|
||||
def test_i_can_register_a_custom_format_by_its_name(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Obj("value a", "value b")
|
||||
@@ -182,80 +238,196 @@ class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "value a-value b\n"
|
||||
|
||||
def test_i_can_define_format_in_print_instruction(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Obj("value a", "value b")
|
||||
def test_i_can_format_d_concepts_using_default_definition(self, capsys):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo a b").def_var("a").def_var("b"))
|
||||
foo_1 = sheerka.new(foo.key, a="value a", b="value b")
|
||||
foo_2 = sheerka.new(foo.key, a="value c", b="value d")
|
||||
lst = [foo_1, foo_2]
|
||||
|
||||
instructions = FormatInstructions().set_format_l("tests.core.test_sheerka_printer.Obj", "{a}-{b}")
|
||||
|
||||
sheerka.print(foo, instructions)
|
||||
sheerka.printer_handler.register_format_d(foo, {"a": "DEFAULT:{a}", "b": "DEFAULT:{b}"})
|
||||
sheerka.print(lst)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "value a-value b\n"
|
||||
assert captured.out == """(1001)foo a b
|
||||
a: DEFAULT:'value a'
|
||||
b: DEFAULT:'value b'
|
||||
(1001)foo a b
|
||||
a: DEFAULT:'value c'
|
||||
b: DEFAULT:'value d'
|
||||
"""
|
||||
|
||||
def test_format_print_instruction_override_register_format(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Obj("value a", "value b")
|
||||
def test_i_can_format_d_concepts_using_context_definition(self, capsys):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo a b").def_var("a").def_var("b"))
|
||||
foo_1 = sheerka.new(foo.key, a="value a", b="value b")
|
||||
foo_2 = sheerka.new(foo.key, a="value c", b="value d")
|
||||
lst = [foo_1, foo_2]
|
||||
|
||||
sheerka.printer_handler.register_format_l("tests.core.test_sheerka_printer.Obj", "{a}-{b}")
|
||||
instructions = FormatInstructions().set_format_l("tests.core.test_sheerka_printer.Obj", "a={a} <> b={b}")
|
||||
|
||||
sheerka.print(foo, instructions)
|
||||
sheerka.printer_handler.register_format_d(foo, {"a": "DEFAULT:{a}", "b": "DEFAULT:{b}"})
|
||||
context_instructions = FormatInstructions().set_format_d(foo, {"a": "CONTEXT:{a}", "b": "CONTEXT:{b}"})
|
||||
sheerka.print(lst, context_instructions)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "a=value a <> b=value b\n"
|
||||
assert captured.out == """(1001)foo a b
|
||||
a: CONTEXT:'value a'
|
||||
b: CONTEXT:'value b'
|
||||
(1001)foo a b
|
||||
a: CONTEXT:'value c'
|
||||
b: CONTEXT:'value d'
|
||||
"""
|
||||
|
||||
def test_i_can_format_d(self, capsys):
|
||||
def test_i_can_format_d_concepts_using_item_definition(self, capsys):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo a b").def_var("a").def_var("b"))
|
||||
item_instructions = FormatInstructions().set_format_d(foo, {"a": "ITEM:{a}", "b": "ITEM:{b}"})
|
||||
foo.set_format_instructions(item_instructions)
|
||||
foo_1 = sheerka.new(foo.key, a="value a", b="value b")
|
||||
foo_2 = sheerka.new(foo.key, a="value c", b="value d")
|
||||
lst = [foo_1, foo_2]
|
||||
|
||||
sheerka.printer_handler.register_format_d(foo, {"a": "DEFAULT:{a}", "b": "DEFAULT:{b}"})
|
||||
context_instructions = FormatInstructions().set_format_d(foo, {"a": "CONTEXT:{a}", "b": "CONTEXT:{b}"})
|
||||
# Note that this time, foo has a format instruction defined
|
||||
|
||||
sheerka.print(lst, context_instructions)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """(1001)foo a b
|
||||
a: ITEM:'value a'
|
||||
b: ITEM:'value b'
|
||||
(1001)foo a b
|
||||
a: ITEM:'value c'
|
||||
b: ITEM:'value d'
|
||||
"""
|
||||
|
||||
def test_i_can_format_d_objects(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = [Obj("value a", "value b"), Obj("value c", "value d")]
|
||||
|
||||
sheerka.printer_handler.register_format_d(TrueNode(), ["a", "b"])
|
||||
sheerka.printer_handler.register_format_d(Obj, {"a": "CUSTOM:{a}", "b": "CUSTOM:{b}"})
|
||||
sheerka.print(foo)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """Obj(a='value a', b='value b')
|
||||
a: value a
|
||||
b: value b
|
||||
a: CUSTOM:'value a'
|
||||
b: CUSTOM:'value b'
|
||||
Obj(a='value c', b='value d')
|
||||
a: value c
|
||||
b: value d
|
||||
a: CUSTOM:'value c'
|
||||
b: CUSTOM:'value d'
|
||||
"""
|
||||
|
||||
def test_i_can_format_d_with_only_a_list_of_properties(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = [Obj("value a", "value b"), Obj("value c", "value d")]
|
||||
|
||||
sheerka.printer_handler.register_format_d(Obj, ["a", "b"])
|
||||
sheerka.print(foo)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """Obj(a='value a', b='value b')
|
||||
a: 'value a'
|
||||
b: 'value b'
|
||||
Obj(a='value c', b='value d')
|
||||
a: 'value c'
|
||||
b: 'value d'
|
||||
"""
|
||||
|
||||
def test_i_can_format_d_and_align_properties(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = [ObjLongProp("value a", "value b"), ObjLongProp("value c", "value d")]
|
||||
|
||||
sheerka.printer_handler.register_format_d(TrueNode(), ["first_property_name", "second"])
|
||||
sheerka.printer_handler.register_format_d(ObjLongProp, ["first_property_name", "second"])
|
||||
sheerka.print(foo)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """ObjLongProp(first_property_name='value a', second='value b')
|
||||
first_property_name: value a
|
||||
second : value b
|
||||
first_property_name: 'value a'
|
||||
second : 'value b'
|
||||
ObjLongProp(first_property_name='value c', second='value d')
|
||||
first_property_name: value c
|
||||
second : value d
|
||||
first_property_name: 'value c'
|
||||
second : 'value d'
|
||||
"""
|
||||
|
||||
def test_i_can_format_d_all_properties_of_a_concept(self, capsys):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo a b").def_var("a").def_var("b"))
|
||||
foo_1 = sheerka.new(foo.key, a="value a", b="value b")
|
||||
foo_2 = sheerka.new(foo.key, a="value c", b="value d")
|
||||
lst = [foo_1, foo_2]
|
||||
|
||||
sheerka.printer_handler.register_format_d(foo)
|
||||
sheerka.print(lst)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """(1001)foo a b
|
||||
a : 'value a'
|
||||
var.a: *name 'var' is not defined*
|
||||
b : 'value b'
|
||||
var.b: *name 'var' is not defined*
|
||||
id : '1001'
|
||||
name : 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body : __NOT_INITIALIZED
|
||||
self : (1001)foo a b
|
||||
(1001)foo a b
|
||||
a : 'value c'
|
||||
var.a: *name 'var' is not defined*
|
||||
b : 'value d'
|
||||
var.b: *name 'var' is not defined*
|
||||
id : '1001'
|
||||
name : 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body : __NOT_INITIALIZED
|
||||
self : (1001)foo a b
|
||||
"""
|
||||
|
||||
def test_i_can_format_d_when_dictionary(self, capsys):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo a b").def_var("a").def_var("b"))
|
||||
dict_value = {
|
||||
"a": "value a",
|
||||
"beta": {"b1": 10, "b2": Obj("10", 15), "b3": ["items", "in", "a", "list"]},
|
||||
"gamma": {"list": ["'quoted string'", '"double" \'single\'', "c3"], "empty": []},
|
||||
"epsilon": ["a", "b", "c"],
|
||||
"g": {"tuple": ("tuple-a", "tuple-b", "tuple-b"), "empty": tuple()},
|
||||
"h": {"set": {"set-a"}, "empty": set()},
|
||||
}
|
||||
foo_1 = sheerka.new(foo.key, a="value a", b=dict_value)
|
||||
lst = [foo_1]
|
||||
|
||||
sheerka.printer_handler.register_format_d(foo)
|
||||
sheerka.print(lst)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """(1001)foo a b
|
||||
a : 'value a'
|
||||
var.a: *name 'var' is not defined*
|
||||
b : {'a' : 'value a'
|
||||
'beta' : {'b1': 10
|
||||
'b2': Obj(a='10', b=15)
|
||||
'b3': ['items',
|
||||
'in',
|
||||
'a',
|
||||
'list']}
|
||||
'gamma' : {'list' : ["'quoted string'",
|
||||
""double" 'single'",
|
||||
'c3']
|
||||
'empty': []}
|
||||
'epsilon': ['a',
|
||||
'b',
|
||||
'c']
|
||||
'g' : {'tuple': ('tuple-a',
|
||||
'tuple-b',
|
||||
'tuple-b')
|
||||
'empty': ()}
|
||||
'h' : {'set' : {'set-a'}
|
||||
'empty': {}}}
|
||||
var.b: *name 'var' is not defined*
|
||||
id : '1001'
|
||||
name : 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body : __NOT_INITIALIZED
|
||||
self : (1001)foo a b
|
||||
"""
|
||||
|
||||
def test_i_can_manage_when_property_does_not_exist(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = Obj("value a", "value b")
|
||||
|
||||
sheerka.printer_handler.register_format_d(TrueNode(), ["foo", "bar"])
|
||||
sheerka.printer_handler.register_format_d(Obj, ["foo", "bar"])
|
||||
sheerka.print(foo)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """Obj(a='value a', b='value b')
|
||||
foo: *Undefined*
|
||||
bar: *Undefined*
|
||||
"""
|
||||
|
||||
def test_i_can_select_the_object_to_format_d(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
foo = [Obj("value a", "value b"), ObjLongProp("value c", "value d")]
|
||||
|
||||
sheerka.printer_handler.register_format_d(LambdaNode(lambda o: isinstance(o, Obj)), ["a", "b"])
|
||||
sheerka.print(foo)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """Obj(a='value a', b='value b')
|
||||
a: value a
|
||||
b: value b
|
||||
ObjLongProp(first_property_name='value c', second='value d')
|
||||
foo: *name 'foo' is not defined*
|
||||
bar: *name 'bar' is not defined*
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize("template, expected", [
|
||||
@@ -265,7 +437,6 @@ ObjLongProp(first_property_name='value c', second='value d')
|
||||
("{b}\\+", "value b+\n"),
|
||||
("+", "+\n"),
|
||||
("\\+", "\\+\n"),
|
||||
("+\\", "+\\\n"),
|
||||
])
|
||||
def test_i_can_concat_print_instruction_and_register_format(self, capsys, template, expected):
|
||||
sheerka = self.get_sheerka()
|
||||
@@ -277,3 +448,39 @@ ObjLongProp(first_property_name='value c', second='value d')
|
||||
sheerka.print(foo, instructions)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == expected
|
||||
|
||||
def test_i_can_manage_exception_when_printing(self, capsys):
|
||||
sheerka = self.get_sheerka()
|
||||
filter_service = SheerkaFilter(sheerka)
|
||||
predicate = "self='two'" # it should be self=='two'
|
||||
items = ["one", "two", "three"] | Pipe(filter_service.pipe_filter)(predicate)
|
||||
|
||||
sheerka.print(items)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "\x1b[31mSyntaxError: invalid syntax\nself='two'\n ^\x1b[0m\n"
|
||||
|
||||
@pytest.mark.parametrize("template, expected", [
|
||||
(None, []),
|
||||
("", []),
|
||||
("foo", []),
|
||||
("{foo}", [BraceToken(0, 4, -1)]),
|
||||
("xxx{foo}yyy", [BraceToken(3, 7, -1)]),
|
||||
("{foo}{bar}-{baz}", [BraceToken(0, 4, -1), BraceToken(5, 9, -1), BraceToken(11, 15, -1)]),
|
||||
("xxx{{foo}}yyy", []),
|
||||
("xxx{{foo}yyy", []),
|
||||
("xxx{yyy", []),
|
||||
("xxx{", []),
|
||||
])
|
||||
def test_i_can_get_braces(self, template, expected):
|
||||
assert list(Formatter.braces(template)) == expected
|
||||
|
||||
@pytest.mark.parametrize("template, expected", [
|
||||
(None, None),
|
||||
("", ""),
|
||||
("foo", "foo"),
|
||||
("{foo}", "{format_obj(foo, 0)}"),
|
||||
("{foo : >16}", "{format_obj(foo , 0): >16}"),
|
||||
("{foo : >16}{bar}xxx{baz}", "{format_obj(foo , 0): >16}{format_obj(bar, 0)}xxx{format_obj(baz, 0)}"),
|
||||
])
|
||||
def test_i_can_inject_format_obj(self, template, expected):
|
||||
assert Formatter.inject_format_obj(template, 0) == expected
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import ParserResultConcept, ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from evaluators.ExplainEvaluator import ExplainEvaluator
|
||||
from parsers.ExplainParser import ExplanationNode, RecurseDefNode, FormatLNode, UnionNode, FilterNode, FormatDNode
|
||||
from parsers.ExpressionParser import PropertyEqualsNode, PropertyEqualsSequenceNode, TrueNode, IsaNode
|
||||
from printer.FormatInstructions import FormatDetailDesc, FormatDetailType
|
||||
from pytest import fixture
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
from sdp.sheerkaSerializer import Serializer, SerializerContext
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
@fixture(scope="module")
|
||||
def serializer():
|
||||
"""
|
||||
Return a :class:`sdp.sheerkaSerializer.Serializer` instance for the module
|
||||
"""
|
||||
return Serializer()
|
||||
|
||||
|
||||
class EC:
|
||||
"""
|
||||
Helper to create execution context (AKA execution result)
|
||||
"""
|
||||
|
||||
def __init__(self, children=None, **props):
|
||||
self.props = props
|
||||
self.children = children
|
||||
|
||||
|
||||
def get_return_value(expr):
|
||||
if isinstance(expr, ExplanationNode):
|
||||
value = expr
|
||||
else:
|
||||
value = ExplanationNode("xxx_test_explain_evaluator_xxx", "", expr=expr)
|
||||
|
||||
return ReturnValueConcept(
|
||||
"TestEvaluator",
|
||||
True,
|
||||
ParserResultConcept(parser="parser", value=value))
|
||||
|
||||
|
||||
def create_executions_results(context, list_of_ecs):
|
||||
def update(execution_context, ec):
|
||||
for prop_name, pro_value in ec.props.items():
|
||||
setattr(execution_context, prop_name, pro_value)
|
||||
|
||||
if ec.children:
|
||||
for child_ec in ec.children:
|
||||
child_execution_context = execution_context.push("TestEvaluator")
|
||||
update(child_execution_context, child_ec)
|
||||
|
||||
res = []
|
||||
for ec in list_of_ecs:
|
||||
execution_context = ExecutionContext("TestEvaluator", context.event, context.sheerka)
|
||||
update(execution_context, ec)
|
||||
res.append(execution_context)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def get_execution_result_from_file(sheerka, digest, serializer):
|
||||
target_path = os.path.join("../_fixture/", digest) + "_result"
|
||||
with open(target_path, "rb") as f:
|
||||
context = SerializerContext(sheerka=sheerka)
|
||||
return serializer.deserialize(f, context)
|
||||
|
||||
|
||||
def get_execution_result_from_list(executions_result):
|
||||
return executions_result
|
||||
|
||||
|
||||
class TestExplainEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@staticmethod
|
||||
def init_evaluator_with_file(self, serializer):
|
||||
sheerka = self.get_sheerka()
|
||||
context = self.get_context(sheerka)
|
||||
evaluator = ExplainEvaluator()
|
||||
evaluator.get_execution_result = lambda s, d: get_execution_result_from_file(s, d, serializer)
|
||||
|
||||
return sheerka, context, evaluator
|
||||
|
||||
def init_evaluator_with_list(self, list_of_ecs):
|
||||
sheerka = self.get_sheerka()
|
||||
context = self.get_context(sheerka)
|
||||
evaluator = ExplainEvaluator()
|
||||
|
||||
executions_result = create_executions_results(context, list_of_ecs)
|
||||
evaluator.get_execution_result = lambda s, d: get_execution_result_from_list(executions_result)
|
||||
|
||||
return sheerka, context, evaluator, executions_result
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("some_name", True, ParserResultConcept(value=ExplanationNode("", ""))), 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 ExplainEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
def test_i_can_eval_in_list(self, serializer):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list(
|
||||
[
|
||||
EC(desc="correct desc"),
|
||||
EC(desc="wrong desc"),
|
||||
]
|
||||
)
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("desc", "correct desc")),
|
||||
]))
|
||||
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.EXPLANATION)
|
||||
|
||||
filtered = res.body.body
|
||||
assert filtered == [execution_results[0]]
|
||||
|
||||
def test_i_can_eval_in_children(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list(
|
||||
[
|
||||
EC(desc="wrong desc", children=[EC(desc="wrong sub"), EC(desc="good sub")]),
|
||||
EC(desc="wrong desc", children=[EC(desc="good sub")]),
|
||||
]
|
||||
)
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("desc", "good sub")),
|
||||
]))
|
||||
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.EXPLANATION)
|
||||
|
||||
filtered = res.body.body
|
||||
assert filtered == [
|
||||
execution_results[0].children[1],
|
||||
execution_results[1].children[0],
|
||||
]
|
||||
|
||||
def test_i_can_evaluate_multiple_filter_node(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list(
|
||||
[
|
||||
EC(desc="parent1", _id=1, children=[EC(desc="wrong sub"), EC(desc="good sub")]),
|
||||
EC(desc="parent2", children=[EC(desc="wrong sub"), EC(desc="good sub")]),
|
||||
EC(desc="good sub")
|
||||
])
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("id", "1")),
|
||||
FilterNode(PropertyEqualsNode("desc", "good sub")),
|
||||
]))
|
||||
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert len(res.body) == 2
|
||||
|
||||
assert sheerka.isinstance(res.body[0], BuiltinConcepts.EXPLANATION)
|
||||
assert sheerka.isinstance(res.body[1], BuiltinConcepts.EXPLANATION)
|
||||
|
||||
assert res.body[0].body == [execution_results[0]]
|
||||
assert res.body[1].body == [
|
||||
execution_results[0].children[1],
|
||||
execution_results[1].children[1],
|
||||
execution_results[2]
|
||||
]
|
||||
|
||||
def test_i_can_eval_parent_and_child(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list(
|
||||
[
|
||||
EC(desc="parent1", children=[EC(desc="wrong sub"), EC(desc="good sub")]),
|
||||
EC(desc="parent2", children=[EC(desc="wrong sub"), EC(desc="good sub")]),
|
||||
EC(desc="good sub")
|
||||
]
|
||||
)
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsSequenceNode(["desc", "desc"], ["parent1", "good sub"])),
|
||||
]))
|
||||
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.EXPLANATION)
|
||||
|
||||
filtered = res.body.body
|
||||
assert filtered == [
|
||||
execution_results[0].children[1],
|
||||
]
|
||||
|
||||
def test_i_correctly_create_format_instructions(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list([])
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode(), [
|
||||
RecurseDefNode(2),
|
||||
FormatLNode("abc"),
|
||||
FormatDNode({"a": "{a}", "b": "{b}"})
|
||||
]),
|
||||
]))
|
||||
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.EXPLANATION)
|
||||
|
||||
instructions = res.body.instructions
|
||||
assert instructions.recursive_props == {"children": 2}
|
||||
assert instructions.format_l == {'core.sheerka.ExecutionContext.ExecutionContext': 'abc'}
|
||||
assert instructions.format_d == [FormatDetailDesc(
|
||||
IsaNode(ExecutionContext),
|
||||
FormatDetailType.Props_In_Line,
|
||||
{"a": "{a}", "b": "{b}"})]
|
||||
|
||||
def test_i_correctly_create_format_instructions_with_filtering(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list([])
|
||||
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("id", "1"), [RecurseDefNode(2), FormatLNode("abc")]),
|
||||
]))
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.EXPLANATION)
|
||||
|
||||
instructions = res.body.instructions
|
||||
assert instructions.format_l == {'core.sheerka.ExecutionContext.ExecutionContext': 'abc'}
|
||||
assert instructions.recursive_props == {"children": 2}
|
||||
|
||||
def test_i_can_have_different_instructions_for_different_filtering(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list([])
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("id", "1"), [RecurseDefNode(2)]),
|
||||
FilterNode(PropertyEqualsNode("desc", "good sub"), [FormatLNode("abc")]),
|
||||
]))
|
||||
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert len(res.body) == 2
|
||||
|
||||
assert res.body[0].instructions.recursive_props == {"children": 2}
|
||||
assert res.body[1].instructions.format_l == {'core.sheerka.ExecutionContext.ExecutionContext': 'abc'}
|
||||
|
||||
def test_filtering_instructions_inherit_from_the_first_filtering_node(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list([])
|
||||
ret_val = get_return_value(UnionNode(
|
||||
[
|
||||
FilterNode(TrueNode(), [RecurseDefNode(2)]),
|
||||
FilterNode(PropertyEqualsNode("id", "1"), [RecurseDefNode(1)]),
|
||||
FilterNode(PropertyEqualsNode("desc", "good sub"), [FormatLNode("abc")]),
|
||||
]))
|
||||
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert res.status
|
||||
assert len(res.body) == 2
|
||||
|
||||
assert res.body[0].instructions.recursive_props == {"children": 1} # overridden
|
||||
|
||||
assert res.body[1].instructions.format_l == {'core.sheerka.ExecutionContext.ExecutionContext': 'abc'}
|
||||
assert res.body[1].instructions.recursive_props == {"children": 2}
|
||||
|
||||
def test_i_can_reuse_a_recorded_digest(self):
|
||||
sheerka, context, evaluator, execution_results = self.init_evaluator_with_list([])
|
||||
expr = UnionNode([FilterNode(TrueNode(), [RecurseDefNode(2)])])
|
||||
|
||||
# need a valid result to test this feature
|
||||
event = Event("fake message")
|
||||
execution_context = ExecutionContext("TestExplainEvaluator", event, sheerka)
|
||||
sheerka.sdp.save_result(execution_context)
|
||||
|
||||
# save another result
|
||||
event2 = Event("fake message")
|
||||
execution_context = ExecutionContext("TestExplainEvaluator", event2, sheerka)
|
||||
sheerka.sdp.save_result(execution_context)
|
||||
|
||||
# digest is recorded during the first call
|
||||
explanation_node = ExplanationNode(event.get_digest(), "", expr=expr, record_digest=True)
|
||||
ret_val = get_return_value(explanation_node)
|
||||
evaluator.eval(context, ret_val)
|
||||
|
||||
# the next call to get_event_digest will load the recorded digest
|
||||
explanation_node = ExplanationNode("", "", expr=expr, record_digest=False) # digest is not provided
|
||||
digest = evaluator.get_event_digest(sheerka, explanation_node)
|
||||
assert digest == event.get_digest()
|
||||
|
||||
# test I can record another digest
|
||||
explanation_node = ExplanationNode(event2.get_digest(), "", expr=expr, record_digest=True)
|
||||
ret_val = get_return_value(explanation_node)
|
||||
evaluator.eval(context, ret_val)
|
||||
|
||||
explanation_node = ExplanationNode("", "", expr=expr, record_digest=False) # digest is not provided
|
||||
digest = evaluator.get_event_digest(sheerka, explanation_node)
|
||||
assert digest == event2.get_digest()
|
||||
|
||||
# test can now reset the recorded digest
|
||||
# (a digest is provided, but record_digest is set to False)
|
||||
explanation_node = ExplanationNode(event.get_digest(), "", expr=expr, record_digest=False)
|
||||
ret_val = get_return_value(explanation_node)
|
||||
evaluator.eval(context, ret_val)
|
||||
|
||||
explanation_node = ExplanationNode("", "", expr=expr, record_digest=False) # digest is not provided
|
||||
digest = evaluator.get_event_digest(sheerka, explanation_node)
|
||||
assert digest is None
|
||||
@@ -1,205 +0,0 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from parsers.BaseParser import UnexpectedTokenErrorNode, UnexpectedEof
|
||||
from parsers.ExplainParser import ExplainParser, ExplanationNode, MultipleDigestError, ValueErrorNode, \
|
||||
RecurseDefNode, FormatLNode, UnionNode, FilterNode, FormatDNode
|
||||
from parsers.ExpressionParser import PropertyContainsNode, PropertyEqualsNode, TrueNode, AndNode, OrNode
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestExplainParser(TestUsingMemoryBasedSheerka):
|
||||
def init_parser(self, **kwargs):
|
||||
sheerka = self.get_sheerka(singleton=True, **kwargs)
|
||||
context = self.get_context(sheerka)
|
||||
parser = ExplainParser()
|
||||
return sheerka, context, parser
|
||||
|
||||
def test_i_cannot_parse_empty_string(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, "")
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
|
||||
|
||||
def test_i_cannot_parse_if_not_for_me(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
text = "foo"
|
||||
res = parser.parse(context, text)
|
||||
not_for_me = res.body
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(not_for_me, BuiltinConcepts.NOT_FOR_ME)
|
||||
assert not_for_me.body == text
|
||||
assert isinstance(not_for_me.reason[0], UnexpectedTokenErrorNode)
|
||||
|
||||
@pytest.mark.parametrize("text, digest, command, directives", [
|
||||
# ("explain", "", "explain", []),
|
||||
("explain digest", "digest", "explain digest", []),
|
||||
("explain -r 3", "", "explain -r 3", [RecurseDefNode(3)]),
|
||||
("explain digest -r 3", "digest", "explain digest -r 3", [RecurseDefNode(3)]),
|
||||
])
|
||||
def test_i_can_parse_explain_without_filter(self, text, digest, command, directives):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, text)
|
||||
parser_result = res.body
|
||||
explanation_node = res.body.body
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
||||
assert parser_result.parser.name == "parsers.Explain"
|
||||
assert parser_result.source == text
|
||||
|
||||
assert explanation_node.digest == digest
|
||||
assert explanation_node.command == command
|
||||
assert explanation_node.expr == UnionNode([FilterNode(TrueNode(), directives)])
|
||||
|
||||
def test_i_can_parse_using_filter(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
text = "explain -f a=b"
|
||||
res = parser.parse(context, text)
|
||||
parser_result = res.body
|
||||
explanation_node = res.body.body
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
||||
assert parser_result.parser.name == "parsers.Explain"
|
||||
assert parser_result.source == text
|
||||
|
||||
assert explanation_node.expr == UnionNode([
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyContainsNode("a", "b"))])
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("-f a==b", PropertyEqualsNode("a", "b")),
|
||||
("--filter a==b", PropertyEqualsNode("a", "b")),
|
||||
("-f a==b and c=d", AndNode(PropertyEqualsNode("a", "b"), PropertyContainsNode("c", "d"))),
|
||||
("-f a==b or c=d", OrNode(PropertyEqualsNode("a", "b"), PropertyContainsNode("c", "d"))),
|
||||
("-f a==b or c==d and e==f", OrNode(
|
||||
PropertyEqualsNode("a", "b"),
|
||||
AndNode(PropertyEqualsNode("c", "d"), PropertyEqualsNode("e", "f")))),
|
||||
("-f a==b and c==d or e==f", OrNode(
|
||||
AndNode(PropertyEqualsNode("a", "b"), PropertyEqualsNode("c", "d")),
|
||||
PropertyEqualsNode("e", "f"))),
|
||||
("-f (a==b or c==d) and e==f", AndNode(
|
||||
OrNode(PropertyEqualsNode("a", "b"), PropertyEqualsNode("c", "d")),
|
||||
PropertyEqualsNode("e", "f"))),
|
||||
])
|
||||
def test_i_can_parse_filter_expressions(self, text, expected):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, "explain " + text)
|
||||
parser_result = res.body
|
||||
explanation_node = res.body.body
|
||||
expr_node = explanation_node.expr.filters[-1].expr
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
||||
assert isinstance(explanation_node, ExplanationNode)
|
||||
|
||||
assert expr_node == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("-r 2", [
|
||||
FilterNode(TrueNode(), [RecurseDefNode(2)])
|
||||
]),
|
||||
("--format_l 'abc'", [
|
||||
FilterNode(TrueNode(), [FormatLNode('abc')])
|
||||
]),
|
||||
("--format_d 'abc'", [
|
||||
FilterNode(TrueNode(), [FormatDNode({"abc": "{abc}"})])
|
||||
]),
|
||||
("--format_d a,b,c", [
|
||||
FilterNode(TrueNode(), [FormatDNode({"a": "{a}", "b": "{b}", "c": "{c}"})])
|
||||
]),
|
||||
("--format_d a , b , c", [
|
||||
FilterNode(TrueNode(), [FormatDNode({"a": "{a}", "b": "{b}", "c": "{c}"})])
|
||||
]),
|
||||
("-r 2 --format_l 'abc'", [
|
||||
FilterNode(TrueNode(), [RecurseDefNode(2), FormatLNode('abc')])
|
||||
]),
|
||||
("--format_d a, b -r 2", [
|
||||
FilterNode(TrueNode(), [FormatDNode({"a": "{a}", "b": "{b}"}), RecurseDefNode(2)])
|
||||
]),
|
||||
("-f a==b -r 3", [
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("a", "b"), [RecurseDefNode(3)]),
|
||||
]),
|
||||
("-f a==b --format_l 'abc'", [
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("a", "b"), [FormatLNode("abc")]),
|
||||
]),
|
||||
("-r 3 -f a==b", [
|
||||
FilterNode(TrueNode(), [RecurseDefNode(3)]),
|
||||
FilterNode(PropertyEqualsNode("a", "b"), []),
|
||||
]),
|
||||
("--format_l 'abc' -f a==b", [
|
||||
FilterNode(TrueNode(), [FormatLNode("abc")]),
|
||||
FilterNode(PropertyEqualsNode("a", "b"), []),
|
||||
]),
|
||||
("-f a==b -f c==d", [
|
||||
FilterNode(TrueNode()),
|
||||
FilterNode(PropertyEqualsNode("a", "b")),
|
||||
FilterNode(PropertyEqualsNode("c", "d"))
|
||||
]),
|
||||
("-r 1 -f a==b -r 2 -f c==d -r 3", [
|
||||
FilterNode(TrueNode(), [RecurseDefNode(1)]),
|
||||
FilterNode(PropertyEqualsNode("a", "b"), [RecurseDefNode(2)]),
|
||||
FilterNode(PropertyEqualsNode("c", "d"), [RecurseDefNode(3)])
|
||||
]),
|
||||
])
|
||||
def test_i_can_parse_other_directives(self, text, expected):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, "explain " + text)
|
||||
parser_result = res.body
|
||||
explanation_node = res.body.body
|
||||
expr_node = explanation_node.expr
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
||||
assert isinstance(explanation_node, ExplanationNode)
|
||||
|
||||
assert expr_node.filters == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("explain -d digest", "digest"),
|
||||
("explain -d", ""),
|
||||
("explain -d -f a=b", "")
|
||||
])
|
||||
def test_i_can_parse_record_digest(self, text, expected):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, text)
|
||||
explanation_node = res.body.body
|
||||
|
||||
assert explanation_node.digest == expected
|
||||
assert explanation_node.record_digest
|
||||
|
||||
@pytest.mark.parametrize("text, expected_error_type", [
|
||||
("explain digest1 digest2", MultipleDigestError),
|
||||
("explain -r", UnexpectedEof),
|
||||
("explain -r foo", ValueErrorNode),
|
||||
("explain -r 1.2", ValueErrorNode),
|
||||
("explain -f -r 1.2", UnexpectedTokenErrorNode),
|
||||
("explain -f", UnexpectedEof),
|
||||
("explain --format_d", UnexpectedEof),
|
||||
("explain --format_l", UnexpectedEof),
|
||||
("explain --format_l -r foo", UnexpectedTokenErrorNode),
|
||||
("explain --format_d -r foo", UnexpectedTokenErrorNode),
|
||||
])
|
||||
def test_i_cannot_parse(self, text, expected_error_type):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, text)
|
||||
error = res.body
|
||||
errors = res.body.body
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(error, BuiltinConcepts.ERROR)
|
||||
assert len(errors) == 1
|
||||
assert isinstance(errors[0], expected_error_type)
|
||||
Reference in New Issue
Block a user