import pytest from core.builtin_concepts import BuiltinConcepts from core.concept import Concept from core.sheerka.services.SheerkaExecute import ParserInput from core.sheerka.services.SheerkaRuleManager import FormatAstRawText, RulePredicate, FormatAstVariable from core.tokenizer import Keywords, Tokenizer from parsers.BaseCustomGrammarParser import KeywordNotFound from parsers.DefFormatRuleParser import DefFormatRuleParser, FormatRuleNode from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka cmap = { "is a": Concept("x is a y").def_var("x").def_var("y"), "is a question": Concept("x is a y", pre="is_question()").def_var("x").def_var("y"), "a is good": Concept("a is good").def_var("a"), "b is good": Concept("b is good").def_var("b"), } class TestDefFormatRuleParser(TestUsingMemoryBasedSheerka): shared_ontology = None @classmethod def setup_class(cls): init_test_helper = cls().init_test(cache_only=False, ontology="#TestDefFormatRuleParser#") sheerka, context, *updated = init_test_helper.with_concepts(*cmap.values(), create_new=True).unpack() for i, concept_name in enumerate(cmap): cmap[concept_name] = updated[i] cls.shared_ontology = sheerka.get_ontology(context) sheerka.pop_ontology() def init_parser(self, my_concepts_map=None, **kwargs): if my_concepts_map is None: sheerka, context = self.init_test().unpack() sheerka.add_ontology(context, self.shared_ontology) else: sheerka, context, *updated = self.init_test().with_concepts(*my_concepts_map.values(), **kwargs).unpack() for i, pair in enumerate(my_concepts_map): my_concepts_map[pair] = updated[i] parser = DefFormatRuleParser() return sheerka, context, parser def test_i_can_detect_empty_expression(self): sheerka, context, parser = self.init_parser() res = parser.parse(context, ParserInput("")) assert not res.status assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY) def test_input_must_be_a_parser_input(self): sheerka, context, parser = self.init_parser() parser.parse(context, "not a parser input") is None def test_i_can_parse_a_simple_rule(self): sheerka, context, parser = self.init_parser() text = "when isinstance(last_value(), Concept) print hello world!" res = parser.parse(context, ParserInput(text)) parser_result = res.body format_rule = res.body.body rules = format_rule.rule format_ast = format_rule.format_ast assert res.status assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT) assert isinstance(format_rule, FormatRuleNode) assert self.dump_tokens(format_rule.tokens[Keywords.WHEN][1:]) == self.dump_tokens( Tokenizer("isinstance(last_value(), Concept)", False)) assert self.dump_tokens(format_rule.tokens[Keywords.PRINT][1:]) == self.dump_tokens( Tokenizer("hello world!", False)) assert len(rules) == 1 assert isinstance(rules[0], RulePredicate) assert format_ast == FormatAstRawText("hello world!") def test_when_is_parsed_in_the_context_of_a_question(self): sheerka, context, parser = self.init_parser() text = "when foo is a bar print hello world" res = parser.parse(context, ParserInput(text)) format_rule = res.body.body rules = format_rule.rule assert res.status assert len(rules) == 1 assert isinstance(rules[0], RulePredicate) assert rules[0].predicate.body.body.get_metadata().pre == "is_question()" def test_when_can_support_multiple_possibilities(self): sheerka, context, parser = self.init_parser() text = "when foo is good print hello world" res = parser.parse(context, ParserInput(text)) format_rule = res.body.body rules = format_rule.rule assert res.status assert len(rules) == 2 assert rules[0].predicate.body.body.get_metadata().name == "a is good" assert rules[1].predicate.body.body.get_metadata().name == "b is good" @pytest.mark.parametrize("text, error", [ ("hello world", [KeywordNotFound(None, keywords=['when', 'print'])]), ("when True", [KeywordNotFound([], keywords=['print'])]), ("print True", [KeywordNotFound([], keywords=['when'])]), ]) def test_cannot_parse_when_not_for_me(self, text, error): sheerka, context, parser = self.init_parser() res = parser.parse(context, ParserInput(text)) not_for_me = res.body assert not res.status assert sheerka.isinstance(not_for_me, BuiltinConcepts.NOT_FOR_ME) assert not_for_me.reason == error @pytest.mark.parametrize("text, expected_error", [ ("when a b print hello world!", BuiltinConcepts.TOO_MANY_ERRORS), ]) def test_i_cannot_parse_invalid_predicates(self, text, expected_error): sheerka, context, parser = self.init_parser() res = parser.parse(context, ParserInput(text)) assert not res.status assert sheerka.isinstance(res.body, expected_error) @pytest.mark.parametrize("expr, expected", [ ("hello world", FormatAstRawText("hello world")), ("{id}", FormatAstVariable("id")), ]) def test_i_can_parse_valid_print_expression(self, expr, expected): sheerka, context, parser = self.init_parser() text = "when True print " + expr res = parser.parse(context, ParserInput(text)) format_rule = res.body.body format_ast = format_rule.format_ast assert res.status assert format_ast == expected