First version of explain. Creating a new parser was a wrong approach. Need to reimplement

This commit is contained in:
2020-04-17 17:24:57 +02:00
parent 6c7c529016
commit d6ea2461a8
43 changed files with 2679 additions and 162 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ class TestSheerkaHistoryManager(TestUsingMemoryBasedSheerka):
hist("xxx", False),
hist("one", True),
hist("def concept one as 1", True),
hist("Initializing Sheerka.", True)]
hist("Initializing Sheerka.", None)]
h = list(sheerka.history(2))
assert h == [
+71
View File
@@ -0,0 +1,71 @@
from core.concept import Concept, ConceptParts
from core.sheerka.Services.SheerkaVariableManager import SheerkaVariableManager
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
def test_i_can_record_and_load_a_constant(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
res = sheerka.load("TestSheerkaVariable", "my_variable")
assert res == 1
assert sheerka.sdp.exists(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
assert loaded.event_id == context.event.get_digest()
assert loaded.key == "my_variable"
assert loaded.value == 1
assert loaded.who == "TestSheerkaVariable"
assert loaded.parents is None
def test_i_can_record_and_load_a_concept(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
concept = Concept("foo").set_prop("a", "alpha").set_metadata_value(ConceptParts.BODY, 3.14)
sheerka.record(context, "TestSheerkaVariable", "my_variable", concept)
res = sheerka.load("TestSheerkaVariable", "my_variable")
assert res == concept
assert res.body == concept.body
def test_i_can_get_the_parent_when_modified(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 2)
res = sheerka.load("TestSheerkaVariable", "my_variable")
assert res == 2
loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
assert loaded.event_id == context.event.get_digest()
assert loaded.key == "my_variable"
assert loaded.value == 2
assert loaded.who == "TestSheerkaVariable"
assert loaded.parents == ['8c9ada7bf488d84229f6539f76042431638f16d600fe3b7ec7e7161043a40d59']
parent = sheerka.sdp.load_obj(loaded.parents[0])
assert parent.event_id == context.event.get_digest()
assert parent.key == "my_variable"
assert parent.value == 1
assert parent.who == "TestSheerkaVariable"
assert parent.parents is None
def test_variable_is_not_persisted_if_the_value_is_the_same(self):
sheerka = self.get_sheerka()
context = self.get_context(sheerka)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
assert loaded.event_id == context.event.get_digest()
assert loaded.key == "my_variable"
assert loaded.value == 1
assert loaded.who == "TestSheerkaVariable"
assert loaded.parents is None
+278
View File
@@ -0,0 +1,278 @@
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
+17 -3
View File
@@ -4,7 +4,7 @@ from core.tokenizer import Tokenizer, Token, TokenKind, LexerError, Keywords
def test_i_can_tokenize():
source = "+*-/{}[]() ,;:.?\n\n\r\r\r\nidentifier_0\t \t10.15 10 'string\n' \"another string\"=|&<>c:name:"
source += "$£€!_identifier°~_^\\`#"
source += "$£€!_identifier°~_^\\`==#"
tokens = list(Tokenizer(source))
assert tokens[0] == Token(TokenKind.PLUS, "+", 0, 1, 1)
assert tokens[1] == Token(TokenKind.STAR, "*", 1, 1, 2)
@@ -52,9 +52,10 @@ def test_i_can_tokenize():
assert tokens[43] == Token(TokenKind.CARAT, '^', 106, 6, 48)
assert tokens[44] == Token(TokenKind.BACK_SLASH, '\\', 107, 6, 49)
assert tokens[45] == Token(TokenKind.BACK_QUOTE, '`', 108, 6, 50)
assert tokens[46] == Token(TokenKind.HASH, '#', 109, 6, 51)
assert tokens[46] == Token(TokenKind.EQUALSEQUALS, '==', 109, 6, 51)
assert tokens[47] == Token(TokenKind.HASH, '#', 111, 6, 53)
assert tokens[47] == Token(TokenKind.EOF, '', 110, 6, 52)
assert tokens[48] == Token(TokenKind.EOF, '', 112, 6, 54)
@pytest.mark.parametrize("text, expected", [
@@ -74,6 +75,19 @@ def test_i_can_tokenize_identifiers(text, expected):
assert comparison == expected
@pytest.mark.parametrize("text", [
"123abc",
"123",
"abc",
"abc123"
])
def test_i_can_parse_word(text):
tokens = list(Tokenizer(text, parse_word=True))
assert tokens[0].type == TokenKind.WORD
assert tokens[0].value == text
assert tokens[1].index == len(text)
@pytest.mark.parametrize("text, message, error_text, index, line, column", [
("'string", "Missing Trailing quote", "'string", 7, 1, 8),
('"string', "Missing Trailing quote", '"string', 7, 1, 8),