import ast import core.utils import pytest from core.builtin_concepts import ParserResultConcept, NotForMeConcept, BuiltinConcepts from core.sheerka.services.SheerkaExecute import ParserInput from core.tokenizer import LexerError, TokenKind from parsers.PythonParser import PythonNode, PythonParser, PythonErrorNode, ConceptDetectedError from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka class TestPythonParser(TestUsingMemoryBasedSheerka): @pytest.mark.parametrize("text, expected", [ ("1+1", PythonNode("1+1", ast.parse("1+1", mode="eval"))), ("a=10", PythonNode("a=10", ast.parse("a=10", mode="exec"))), ]) def test_i_can_parse_a_simple_expression(self, text, expected): parser = PythonParser() res = parser.parse(self.get_context(), ParserInput(text)) assert res.status assert res.who == parser.name assert isinstance(res.value, ParserResultConcept) assert res.value.value == expected @pytest.mark.parametrize("text", [ "1+", "&#é", ]) def test_i_can_detect_python_error(self, text): parser = PythonParser() res = parser.parse(self.get_context(), ParserInput(text)) assert not res.status assert res.who == parser.name assert isinstance(res.value, NotForMeConcept) assert res.value.body == text assert len(res.value.get_value("reason")) == 1 assert isinstance(res.value.get_value("reason")[0], PythonErrorNode) assert isinstance(res.value.get_value("reason")[0].exception, SyntaxError) @pytest.mark.parametrize("text, error_msg, error_text", [ ("c::", "Concept identifiers not found", ""), ("c:: + 1", "Concept identifiers not found", ""), ]) def test_i_can_detect_lexer_errors(self, text, error_msg, error_text): parser = PythonParser() res = parser.parse(self.get_context(), ParserInput(text)) assert not res.status assert isinstance(res.value, NotForMeConcept) assert res.value.body == text assert len(res.value.get_value("reason")) == 1 assert isinstance(res.value.get_value("reason")[0], LexerError) assert res.value.get_value("reason")[0].message == error_msg assert res.value.get_value("reason")[0].text == error_text def test_i_can_parse_a_concept(self): text = "c:name|id: + 1" parser = PythonParser() res = parser.parse(self.get_context(), ParserInput(text)) encoded = core.utils.encode_concept(("name", "id")) assert res assert res.value.source == "c:name|id: + 1" assert res.value.value == PythonNode( "__C__KEY_name__ID_id__C__ + 1", ast.parse(encoded + "+1", mode="eval")) assert len(res.value.value.objects) == 1 assert res.value.value.objects[encoded].type == TokenKind.CONCEPT assert res.value.value.objects[encoded].value == ("name", "id") def test_i_can_parse_a_rule(self): text = "r:name|id: + 1" parser = PythonParser() res = parser.parse(self.get_context(), ParserInput(text)) encoded = core.utils.encode_concept(("name", "id"), "R") assert res assert res.value.source == "r:name|id: + 1" assert res.value.value == PythonNode( "__R__KEY_name__ID_id__R__ + 1", ast.parse(encoded + "+1", mode="eval")) assert len(res.value.value.objects) == 1 assert res.value.value.objects[encoded].type == TokenKind.RULE assert res.value.value.objects[encoded].value == ("name", "id") def test_i_can_parse_a_rule_2(self): text = "r:name|id:.name" parser = PythonParser() res = parser.parse(self.get_context(), ParserInput(text)) encoded = core.utils.encode_concept(("name", "id"), "R") assert res assert res.value.source == "r:name|id:.name" assert res.value.value == PythonNode( "__R__KEY_name__ID_id__R__.name", ast.parse(encoded + ".name", mode="eval")) assert len(res.value.value.objects) == 1 assert res.value.value.objects[encoded].type == TokenKind.RULE assert res.value.value.objects[encoded].value == ("name", "id") @pytest.mark.parametrize("text, expected_id", [ ("foo", "foo"), ("c:foo:", "__C__KEY_foo__ID_00None00__C__") ]) def test_i_cannot_parse_simple_concepts(self, text, expected_id): sheerka, context, foo = self.init_concepts("foo") parser = PythonParser() res = parser.parse(context, ParserInput(text)) assert not res.status assert sheerka.isinstance(res.value, BuiltinConcepts.NOT_FOR_ME) assert res.value.reason == [ConceptDetectedError(expected_id)]