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 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_prop("a").def_prop("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_prop("a").def_prop("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_prop("a", "value a").set_prop("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_metadata_value(ConceptParts.BODY, level3) level1 = Concept("level1").set_metadata_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_metadata_value(ConceptParts.BODY, [level31, level32]) level22 = Concept("level22").set_metadata_value(ConceptParts.BODY, [level33]) level1 = Concept("level1").set_metadata_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_metadata_value(ConceptParts.BODY, [level31, level32]) level22 = Concept("level22").set_metadata_value(ConceptParts.BODY, [level33]) level1 = Concept("level1").set_metadata_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_concept(self, capsys): sheerka = self.get_sheerka() foo = Concept("foo a b").def_prop("a").def_prop("b").init_key() foo.set_prop("a", "value a").set_prop("b", "value b") foo.set_metadata_value(ConceptParts.BODY, "body") sheerka.set_id_if_needed(foo, False) sheerka.printer_handler.register_format_l(foo, "{id}-{name}-{key}-{body}-{a}-{b}") sheerka.print(foo) captured = capsys.readouterr() assert captured.out == "1001-foo a b-foo __var__0 __var__1-body-value a-value b\n" def test_i_can_format_object(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_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_define_format_in_print_instruction(self, capsys): sheerka = self.get_sheerka() foo = Obj("value a", "value b") instructions = FormatInstructions().set_format_l("tests.core.test_sheerka_printer.Obj", "{a}-{b}") sheerka.print(foo, instructions) captured = capsys.readouterr() assert captured.out == "value a-value b\n" def test_format_print_instruction_override_register_format(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}") instructions = FormatInstructions().set_format_l("tests.core.test_sheerka_printer.Obj", "a={a} <> b={b}") sheerka.print(foo, instructions) captured = capsys.readouterr() assert captured.out == "a=value a <> b=value b\n" def test_i_can_format_d(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.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.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_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.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') """ @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"), ("+\\", "+\\\n"), ]) def test_i_can_concat_print_instruction_and_register_format(self, capsys, template, expected): sheerka = self.get_sheerka() 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