def test_func_call_multiple_args() -> None: assert [ Call( Pos(0, 4, FNAME), Pos(0, 27, FNAME), FUNCTIONS["fmt"], [ Literal(Pos(0, 8, FNAME), Pos(0, 15, FNAME), "{} {}"), Literal(Pos(0, 17, FNAME), Pos(0, 22, FNAME), "abc"), Literal(Pos(0, 24, FNAME), Pos(0, 27, FNAME), 123), ], [], ) ] == PARSER.parse(list(tokenize('${{ fmt("{} {}", "abc", 123) }}', START)))
def test_operator_parse_brackets() -> None: assert [ BinOp( start=Pos(line=0, col=4, filename=FNAME), end=Pos(line=0, col=24, filename=FNAME), op=logical_or, left=Lookup( start=Pos(line=0, col=4, filename=FNAME), end=Pos(line=0, col=7, filename=FNAME), root="foo", trailer=[], ), right=BinOp( start=Pos(line=0, col=12, filename=FNAME), end=Pos(line=0, col=24, filename=FNAME), op=operator.eq, left=Lookup( start=Pos(line=0, col=12, filename=FNAME), end=Pos(line=0, col=15, filename=FNAME), root="bar", trailer=[], ), right=Literal( start=Pos(line=0, col=19, filename=FNAME), end=Pos(line=0, col=24, filename=FNAME), val="baz", ), ), ) ] == PARSER.parse(list(tokenize("""${{ foo or (bar == "baz") }}""", START)))
def test_func_call_with_trailer_item() -> None: assert [ Call( Pos(0, 4, FNAME), Pos(0, 41, FNAME), FUNCTIONS["from_json"], [Literal(Pos(0, 14, FNAME), Pos(0, 36, FNAME), '{"a": 1, "b": "val"}')], [ ItemGetter( Pos(0, 38, FNAME), Pos(0, 41, FNAME), Literal(Pos(0, 38, FNAME), Pos(0, 41, FNAME), "a"), ) ], ) ] == PARSER.parse( list(tokenize("""${{ from_json('{"a": 1, "b": "val"}')['a'] }}""", START)) )
def test_func_call_single_arg() -> None: assert [ Call( Pos(0, 4, FNAME), Pos(0, 13, FNAME), FUNCTIONS["len"], [Literal(Pos(0, 8, FNAME), Pos(0, 13, FNAME), "abc")], [], ) ] == PARSER.parse(list(tokenize("${{ len('abc') }}", START)))
def test_dict() -> None: assert [ DictMaker( start=Pos(0, 5, FNAME), end=Pos(0, 26, FNAME), items=[ ( Literal( start=Pos(0, 5, FNAME), end=Pos(0, 6, FNAME), val=1, ), Literal( start=Pos(0, 8, FNAME), end=Pos(0, 11, FNAME), val="2", ), ), ( Literal( start=Pos(0, 13, FNAME), end=Pos(0, 17, FNAME), val=True, ), Call( start=Pos(0, 19, FNAME), end=Pos(0, 26, FNAME), func=FUNCTIONS["len"], args=[ Lookup( start=Pos(0, 23, FNAME), end=Pos(0, 26, FNAME), root="ctx", trailer=[], ) ], trailer=[], ), ), ], ) ] == PARSER.parse(list(tokenize("${{ {1: '2', True: len(ctx)} }}", START)))
def test_dict_short() -> None: assert [ DictMaker( start=Pos(0, 5, FNAME), end=Pos(0, 11, FNAME), items=[ ( Literal( start=Pos(0, 5, FNAME), end=Pos(0, 6, FNAME), val=1, ), Literal( start=Pos(0, 8, FNAME), end=Pos(0, 11, FNAME), val="2", ), ), ], ) ] == PARSER.parse(list(tokenize("${{ {1: '2'} }}", START)))
def test_unary_operator_parse(op_str: str, op_func: Any) -> None: assert [ UnaryOp( Pos(0, 4, FNAME), Pos(0, 10 + len(op_str), FNAME), op_func, Literal( Pos(0, 5 + len(op_str), FNAME), Pos(0, 10 + len(op_str), FNAME), "bar", ), ) ] == PARSER.parse(list(tokenize(f"""${{{{ {op_str} "bar" }}}}""", START)))
def test_list() -> None: assert [ ListMaker( start=Pos(0, 4, FNAME), end=Pos(0, 25, FNAME), items=[ Literal( start=Pos(0, 4, FNAME), end=Pos(0, 5, FNAME), val=1, ), Literal( start=Pos(0, 7, FNAME), end=Pos(0, 10, FNAME), val="2", ), Literal( start=Pos(0, 12, FNAME), end=Pos(0, 16, FNAME), val=True, ), Call( start=Pos(0, 18, FNAME), end=Pos(0, 25, FNAME), func=FUNCTIONS["len"], args=[ Lookup( start=Pos(0, 22, FNAME), end=Pos(0, 25, FNAME), root="ctx", trailer=[], ) ], trailer=[], ), ], ) ] == PARSER.parse(list(tokenize("${{[1, '2', True, len(ctx)]}}", START)))
def test_operator_parse(op_str: str, op_func: Any) -> None: assert [ BinOp( Pos(0, 4, FNAME), Pos(0, 14 + len(op_str), FNAME), op_func, Lookup(Pos(0, 4, FNAME), Pos(0, 7, FNAME), "foo", []), Literal( Pos(0, 9 + len(op_str), FNAME), Pos(0, 14 + len(op_str), FNAME), "bar", ), ) ] == PARSER.parse(list(tokenize(f"""${{{{ foo {op_str} "bar" }}}}""", START)))
def test_tmpl_literal_str1() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 9, FNAME), "str")] == PARSER.parse( list(tokenize("${{ 'str' }}", START)) )
def test_tmpl_literal_int3() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 9, FNAME), -1234)] == PARSER.parse( list(tokenize("${{ -1234 }}", START)) )
def test_tmpl_literal_hex2() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 11, FNAME), 0x12AB)] == PARSER.parse( list(tokenize("${{ 0X12_ab }}", START)) )
def test_tmpl_literal_oct2() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 11, FNAME), 0o1234)] == PARSER.parse( list(tokenize("${{ 0O12_34 }}", START)) )
def test_tmpl_literal_bin2() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 11, FNAME), 0b0110)] == PARSER.parse( list(tokenize("${{ 0B01_10 }}", START)) )
def test_tmpl_literal_bool1() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 8, FNAME), True)] == PARSER.parse( list(tokenize("${{ True }}", START)) )
def test_tmpl_literal_exp() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 14, FNAME), -12.34e-21)] == PARSER.parse( list(tokenize("${{ -12.34e-21 }}", START)) )
def test_tmpl_literal_bool2() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 9, FNAME), False)] == PARSER.parse( list(tokenize("${{ False }}", START)) )
def test_tmpl_literal_str2() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 13, FNAME), "abc\tdef")] == PARSER.parse( list(tokenize("${{ 'abc\tdef' }}", START)) )
def test_tmpl_literal_none() -> None: assert [Literal(Pos(0, 4, FNAME), Pos(0, 8, FNAME), None)] == PARSER.parse( list(tokenize("${{ None }}", START)) )