Files
Sheerka-Old/tests/core/test_sheerka_printer.py

493 lines
18 KiB
Python

from dataclasses import dataclass
import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, ConceptParts, freeze_concept_attrs
from core.simple_debug import my_debug
from printer.Formatter import Formatter, BraceToken
from printer.SheerkaPrinter import FormatInstructions
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
@dataclass
class Obj:
a: object
b: object
@dataclass()
class ObjLongProp:
first_property_name: object
second: object
class TestSheerkaPrinter(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("text, expected", [
("Hello world!", "Hello world!\n"),
("%black%%red%%green%%yellow%%reset%", "\x1b[30m\x1b[31m\x1b[32m\x1b[33m\x1b[0m\n"),
("%blue%%magenta%%cyan%%white%%reset%", "\x1b[34m\x1b[35m\x1b[36m\x1b[37m\x1b[0m\n"),
(["Hello", "world!"], "Hello\nworld!\n"),
(("Hello", "world!"), "Hello\nworld!\n"),
])
def test_i_can_print(self, capsys, text, expected):
sheerka = self.get_sheerka()
sheerka.print(text)
captured = capsys.readouterr()
assert captured.out == expected
def test_i_can_disable_color(self, capsys):
sheerka = self.get_sheerka()
sheerka.print("%red%Hello world !%reset%", FormatInstructions(no_color=True))
captured = capsys.readouterr()
assert captured.out == "Hello world !\n"
def test_i_can_print_concept(self, capsys):
sheerka = self.get_sheerka()
foo = Concept("foo a b").def_var("a").def_var("b")
sheerka.print(foo)
captured = capsys.readouterr()
assert captured.out == str(foo) + "\n"
def test_i_can_use_custom_format(self, capsys):
sheerka = self.get_sheerka()
foo = Concept("foo a b").def_var("a").def_var("b").init_key()
sheerka.printer_handler.register_custom_printer(
foo,
lambda printer, instr, item: printer.fp(instr, f"foo a={item.a}, b={item.b}"))
foo.set_value("a", "value a").set_value("b", "value b")
sheerka.print(foo)
captured = capsys.readouterr()
assert captured.out == "foo a=value a, b=value b\n"
def test_i_can_print_and_recurse(self, capsys):
sheerka = self.get_sheerka()
level3 = Concept("level3")
level2 = Concept("level2").set_value(ConceptParts.BODY, level3)
level1 = Concept("level1").set_value(ConceptParts.BODY, level2)
sheerka.print(level1)
captured = capsys.readouterr()
assert captured.out == f"{level1}\n"
sheerka.print(level1, FormatInstructions().set_recurse("body", 1))
captured = capsys.readouterr()
assert captured.out == f"{level1}\n {level2}\n"
sheerka.print(level1, FormatInstructions().set_recurse("body", 2))
captured = capsys.readouterr()
assert captured.out == f"{level1}\n {level2}\n {level3}\n"
sheerka.print(level1, FormatInstructions().set_recurse("body", 10))
captured = capsys.readouterr()
assert captured.out == f"{level1}\n {level2}\n {level3}\n"
def test_i_can_print_and_recurse_list(self, capsys):
sheerka = self.get_sheerka()
level31 = Concept("level31")
level32 = Concept("level32")
level33 = Concept("level33")
level21 = Concept("level21").set_value(ConceptParts.BODY, [level31, level32])
level22 = Concept("level22").set_value(ConceptParts.BODY, [level33])
level1 = Concept("level1").set_value(ConceptParts.BODY, [level21, level22])
sheerka.print(level1)
captured = capsys.readouterr()
assert captured.out == f"{level1}\n"
sheerka.print(level1, FormatInstructions().set_recurse("body", 1))
captured = capsys.readouterr()
assert captured.out == f"{level1}\n {level21}\n {level22}\n"
sheerka.print(level1, FormatInstructions().set_recurse("body", 3))
captured = capsys.readouterr()
assert captured.out == f"{level1}\n {level21}\n {level31}\n {level32}\n {level22}\n {level33}\n"
def test_explanation_concept_can_control_recursion(self, capsys):
sheerka = self.get_sheerka()
level31 = Concept("level31")
level32 = Concept("level32")
level33 = Concept("level33")
level21 = Concept("level21").set_value(ConceptParts.BODY, [level31, level32])
level22 = Concept("level22").set_value(ConceptParts.BODY, [level33])
level1 = Concept("level1").set_value(ConceptParts.BODY, [level21, level22])
instructions = FormatInstructions(no_color=True)
explanation = sheerka.new(
BuiltinConcepts.EXPLANATION,
digest="digest",
command="command",
title="title",
instructions=instructions,
body=[level1])
sheerka.print(explanation)
captured = capsys.readouterr()
assert captured.out == f"digest : command\n(None)level1\n"
instructions = FormatInstructions(no_color=True).set_recurse("body", 2)
explanation = sheerka.new(
BuiltinConcepts.EXPLANATION,
digest="digest",
command="command",
title="title",
instructions=instructions,
body=[level1])
sheerka.print(explanation)
captured = capsys.readouterr()
assert captured.out == """digest : command
(None)level1
(None)level21
(None)level31
(None)level32
(None)level22
(None)level33
"""
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()
sheerka.printer_handler.reset()
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)
freeze_concept_attrs(foo)
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()
sheerka.printer_handler.reset()
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)
freeze_concept_attrs(foo)
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()
sheerka.printer_handler.reset()
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)
freeze_concept_attrs(foo)
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}")
foo.set_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS, item_instructions)
sheerka.print(foo, context_instructions)
captured = capsys.readouterr()
assert captured.out == "ITEM:1001-foo a b-foo __var__0 __var__1-body-value a-value b\n"
def test_i_can_format_l_objects(self, capsys):
sheerka = self.get_sheerka()
foo = Obj("value a", "value b")
sheerka.printer_handler.register_format_l(foo, "{a}-{b}")
sheerka.print(foo)
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(BuiltinConcepts.NOP,
None,
who="test_sheerka_printer",
desc="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")
sheerka.printer_handler.register_format_l("tests.core.test_sheerka_printer.Obj", "{a}-{b}")
sheerka.print(foo)
captured = capsys.readouterr()
assert captured.out == "value a-value b\n"
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"))
sheerka.printer_handler.reset()
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}"})
sheerka.print(lst)
captured = capsys.readouterr()
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_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"))
sheerka.printer_handler.reset()
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}"})
sheerka.print(lst, context_instructions)
captured = capsys.readouterr()
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_concepts_using_item_definition(self, capsys):
sheerka, context, foo = self.init_concepts(Concept("foo a b").def_var("a").def_var("b"))
sheerka.printer_handler.reset()
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(Obj, {"a": "CUSTOM:{a}", "b": "CUSTOM:{b}"})
sheerka.print(foo)
captured = capsys.readouterr()
assert captured.out == """Obj(a='value a', b='value b')
a: CUSTOM:'value a'
b: CUSTOM:'value b'
Obj(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(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'
ObjLongProp(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
id : '1001'
name: 'foo a b'
key : 'foo __var__0 __var__1'
a : 'value a'
b : 'value b'
body: **NotInit**
self: (1001)foo a b
(1001)foo a b
id : '1001'
name: 'foo a b'
key : 'foo __var__0 __var__1'
a : 'value c'
b : 'value d'
body: **NotInit**
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"))
sheerka.printer_handler.reset()
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
id : '1001'
name: 'foo a b'
key : 'foo __var__0 __var__1'
a : 'value a'
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': {}}}
body: **NotInit**
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(Obj, ["foo", "bar"])
sheerka.print(foo)
captured = capsys.readouterr()
assert captured.out == """Obj(a='value a', b='value b')
foo: *name 'foo' is not defined*
bar: *name 'bar' is not defined*
"""
@pytest.mark.parametrize("template, expected", [
("+-{b}", "value a-value b\n"),
("{b}-+", "value b-value a\n"),
("\\+{b}", "+value b\n"),
("{b}\\+", "value b+\n"),
("+", "+\n"),
("\\+", "\\+\n"),
])
def test_i_can_concat_print_instruction_and_register_format(self, capsys, template, expected):
sheerka = self.get_sheerka()
sheerka.printer_handler.reset()
foo = Obj("value a", "value b")
sheerka.printer_handler.register_format_l("tests.core.test_sheerka_printer.Obj", "{a}")
instructions = FormatInstructions().set_format_l("tests.core.test_sheerka_printer.Obj", template)
sheerka.print(foo, instructions)
captured = capsys.readouterr()
assert captured.out == expected
@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