import pytest from core.tokenizer import Token, TokenKind from parsers.FormatRuleActionParser import FormatAstSequence, FormatAstRawText, FormatAstVariable, FormatAstFunction, \ FormatAstList, FormatAstColor, FormatAstDict, FormatAstMulti, FormatRuleActionParser, UnexpectedEof, \ FormatRuleSyntaxError from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka seq = FormatAstSequence raw = FormatAstRawText var = FormatAstVariable func = FormatAstFunction lst = FormatAstList class TestFormatRuleActionParser(TestUsingMemoryBasedSheerka): @pytest.mark.parametrize("text, expected", [ ("", FormatAstRawText("")), (" ", FormatAstRawText(" ")), (" raw text ", FormatAstRawText(" raw text ")), ("{variable}", FormatAstVariable("variable")), ("{ variable }", FormatAstVariable("variable")), (" xy {v} z", seq([raw(" xy "), var("v"), raw(" z")])), (r"\{variable}", FormatAstRawText("{variable}")), (r"\\{variable}", seq([raw("\\"), var("variable")])), (r"\\\{variable}", FormatAstRawText(r"\{variable}")), (r"{var1}{var2}", seq([var("var1"), var("var2")])), ("func()", FormatAstFunction("func", [], {})), ("func(a, 'string value', c)", FormatAstFunction("func", ["a", "'string value'", "c"], {})), ("func(a=10, b='string value')", FormatAstFunction("func", [], {"a": "10", "b": "'string value'"})), ("func('string value'='another string value')", func("func", [], {"'string value'": "'another string value'"})), ("red(' xy {v}')", FormatAstColor("red", seq([raw(" xy "), var("v")]))), ('blue(" xy {v}")', FormatAstColor("blue", seq([raw(" xy "), var("v")]))), ('green( xy )', FormatAstColor("green", var("xy"))), ('green()', FormatAstColor("green", raw(""))), ('green("")', FormatAstColor("green", raw(""))), ("list(var_name, 2, 'children')", FormatAstList("var_name", recurse_on="children", recursion_depth=2)), ("list(var_name, recursion_depth=2, recurse_on='children')", FormatAstList("var_name", recurse_on="children", recursion_depth=2)), ("list(var_name, recursion_depth=2, 'children')", FormatAstList("var_name", recursion_depth=2)), ("list(var_name, 'children', recursion_depth=2)", FormatAstList("var_name", recursion_depth=2)), ("list(var_name)", FormatAstList("var_name")), ("{obj.prop1.prop2[0].prop3['value']}", FormatAstVariable("obj.prop1.prop2[0].prop3['value']")), ("[{id}]", seq([raw("["), var("id"), raw("]")])), ("{variable:format}", FormatAstVariable("variable", "format")), ("{variable:3}", FormatAstVariable("variable", "3")), (r"\not_a_function(a={var})", seq([raw("not_a_function(a="), var("var"), raw(")")])), ("dict(var_name)", FormatAstDict("var_name")), ("dict(var_name, items_prop='props')", FormatAstDict("var_name", items_prop='props')), ("dict(var_name, debug=True)", FormatAstDict("var_name", debug=True, prefix="{", suffix="}")), ("multi(var_name)", FormatAstMulti("var_name")), ]) def test_i_can_parse_format_rule(self, text, expected): assert FormatRuleActionParser(text).parse() == expected @pytest.mark.parametrize("text, expected_error", [ ("{", UnexpectedEof("while parsing variable", Token(TokenKind.LBRACE, "{", 0, 1, 1))), ("{var_name", UnexpectedEof("while parsing variable", Token(TokenKind.LBRACE, "{", 0, 1, 1))), ("{}", FormatRuleSyntaxError("variable name not found", None)), ("func(", UnexpectedEof("while parsing function", Token(TokenKind.IDENTIFIER, "func", 0, 1, 1))), ("func(a,b,c", UnexpectedEof("while parsing function", Token(TokenKind.IDENTIFIER, "func", 0, 1, 1))), ("func(a,,c", FormatRuleSyntaxError("no parameter found", Token(TokenKind.COMMA, ",", 7, 1, 8))), ("func(a,,c)", FormatRuleSyntaxError("no parameter found", Token(TokenKind.COMMA, ",", 7, 1, 8))), ("red(a,b)", FormatRuleSyntaxError("only one parameter supported", Token(TokenKind.IDENTIFIER, "b", 6, 1, 7))), ("red(a=b)", FormatRuleSyntaxError("keyword arguments are not supported", None)), ("red(xy {v})", FormatRuleSyntaxError("Invalid identifier", None)), ("list()", FormatRuleSyntaxError("variable name not found", None)), ("list(recursion_depth=2)", FormatRuleSyntaxError("variable name not found", None)), ("list(a,b,c,d,e)", FormatRuleSyntaxError("too many positional arguments", Token(TokenKind.IDENTIFIER, "e", 13, 1, 14))), ("list(a, recursion_depth=hello)", FormatRuleSyntaxError("'hello' is not numeric", None)), ("list(a, recursion_depth='hello')", FormatRuleSyntaxError("'recursion_depth' must be an integer", None)), ("dict()", FormatRuleSyntaxError("variable name not found", None)), ]) def test_i_cannot_parse_invalid_format(self, text, expected_error): parser = FormatRuleActionParser(text) parser.parse() assert parser.error_sink == expected_error