import pytest from sheerkaql.SheerkaQueryLangage import SheerkaQueryLanguage from sheerkaql.lexer import Lexer from sheerkaql.parser import Parser class TestSheerkaQueryLanguageParser: def test_hello(self): SheerkaQueryLanguage().compile('hello') with pytest.raises(SyntaxError) as ex: SheerkaQueryLanguage().compile('hello there') def test_i_can_parse_with_slash(self): SheerkaQueryLanguage().compile('hello/part1') SheerkaQueryLanguage().compile('hello/part1/part2/part3') SheerkaQueryLanguage().compile('hello/part1 / part2 / part3') with pytest.raises(SyntaxError): SheerkaQueryLanguage().compile('hello/part1/part3 part4/part5') def test_i_can_parse_with_dot(self): SheerkaQueryLanguage().compile('hello.part1') SheerkaQueryLanguage().compile('hello.part1.part2.part3') SheerkaQueryLanguage().compile('hello.part1 . part2 . part3') with pytest.raises(SyntaxError): SheerkaQueryLanguage().compile('hello.part1.part3 part4.part5') def test_i_can_parse_simple_where_conditions(self): SheerkaQueryLanguage().compile('hello[wheRe]/hello[asdf]') SheerkaQueryLanguage().compile('hello/hello[asdf]/asdf/wef') SheerkaQueryLanguage().compile('hello/hello/wewe[asdf]/wef/waef/awef/weaf') SheerkaQueryLanguage().compile('hello.hello[ asdf ] . wewe. wef[asdf] .waef .awef[asdf].weaf') SheerkaQueryLanguage().compile('hello["foo"]') SheerkaQueryLanguage().compile('hello[123]') SheerkaQueryLanguage().compile('hello[123.234]') with pytest.raises(SyntaxError): SheerkaQueryLanguage().compile('hello/aef[asdf] hello[adsf]') def test_i_can_parse_where_conditions_with_comparisons(self): SheerkaQueryLanguage().compile('hello[1 == 1]') SheerkaQueryLanguage().compile('hello[1 != 1]') SheerkaQueryLanguage().compile('hello[1 < 1]') SheerkaQueryLanguage().compile('hello[1 <= 1]') SheerkaQueryLanguage().compile('hello[1 > 1]') SheerkaQueryLanguage().compile('hello[1 >= 1]') def test_i_can_parse_where_conditions_with_logical_operations(self): SheerkaQueryLanguage().compile('hello[a and b]') SheerkaQueryLanguage().compile('hello[a or b]') SheerkaQueryLanguage().compile('hello[not a or b]') SheerkaQueryLanguage().compile('hello[a or not b]') SheerkaQueryLanguage().compile('hello[not a and b]') SheerkaQueryLanguage().compile('hello[a and not b]') SheerkaQueryLanguage().compile('hello[not a or not b]') SheerkaQueryLanguage().compile('hello[not a and not b]') def test_i_can_parse_where_conditions_with_logical_operations_and_parenthesis(self): SheerkaQueryLanguage().compile('hello[((a and b) and not (a or b) or not (a and b)) and not (not a or b)]') def test_i_can_parse_where_conditions_with_arithmetic_operations(self): SheerkaQueryLanguage().compile('hello[a + b]') SheerkaQueryLanguage().compile('hello[a - b]') SheerkaQueryLanguage().compile('hello[a * b]') SheerkaQueryLanguage().compile('hello[a / b]') SheerkaQueryLanguage().compile('hello[(a + b) / (a - b)]') SheerkaQueryLanguage().compile('hello[-a]') SheerkaQueryLanguage().compile('hello[a + b * c / e]') def test_i_can_parse_nested_where_conditions(self): SheerkaQueryLanguage().compile('hello[a]') SheerkaQueryLanguage().compile("hello[a[0]['hello']]") SheerkaQueryLanguage().compile("hello[a[0][\"hello\"]]") def test_i_can_parse_where_conditions_with_function_call(self): SheerkaQueryLanguage().compile("hello[a[0]['hello']()]") SheerkaQueryLanguage().compile("hello[a[0]['hello'](0)]") SheerkaQueryLanguage().compile("hello[a[0]['hello']('asdf')]") SheerkaQueryLanguage().compile("hello[a[0]['hello'](asdf)]") SheerkaQueryLanguage().compile("hello[a[0]['hello'](0, 'asdf', asdf)()()(1,2)]") SheerkaQueryLanguage().compile('hello[f(1)]') SheerkaQueryLanguage().compile('hello[f(1,2,3)]') SheerkaQueryLanguage().compile('hello[f(a,b,c)]') SheerkaQueryLanguage().compile('hello[f(a(),b(),c())]') SheerkaQueryLanguage().compile('hello[f(a[a],b[b],c[c])]') def test_i_can_parse_where_conditions_with_attributes_parsing(self): SheerkaQueryLanguage().compile('hello[foo.bar.baz]') SheerkaQueryLanguage().compile('hello[foo[12].bar().baz]') def test_i_can_parse_where_conditions_with_flwr(self): SheerkaQueryLanguage().compile('hello[f(1,,{for x in return x})]') def test_i_can_parse_where_conditions_with_quantified_expressions(self): SheerkaQueryLanguage().compile('hello[every x in satisfies (x)]') with pytest.raises(SyntaxError): SheerkaQueryLanguage().compile('hello[every x in statisfies (x)]') with pytest.raises(SyntaxError): SheerkaQueryLanguage().compile('hello[every x in statisfies x]') SheerkaQueryLanguage().compile('hello[some x in satisfies (x)]') SheerkaQueryLanguage().compile('hello[some x in satisfies (x)]') SheerkaQueryLanguage().compile('hello[some x in {for x in return x} satisfies (x)]') SheerkaQueryLanguage().compile('hello[some x in {for x in return x} satisfies (x == y)]') SheerkaQueryLanguage().compile('hello[some x in {for x in return x} satisfies (x and not y(1,2))]') def test_i_can_parse_where_conditions_with_set_comparisons(self): SheerkaQueryLanguage().compile('hello[a in ]') SheerkaQueryLanguage().compile('hello[a not in ]') SheerkaQueryLanguage().compile('hello[not a in ]') SheerkaQueryLanguage().compile('hello[ subset ]') SheerkaQueryLanguage().compile('hello[ superset ]') SheerkaQueryLanguage().compile('hello[ proper subset ]') SheerkaQueryLanguage().compile('hello[ proper superset ]') SheerkaQueryLanguage().compile('hello[ is ]') SheerkaQueryLanguage().compile('hello[ is not ]') def test_i_can_parse_operations_on_sets(self): SheerkaQueryLanguage().compile('asdf - asdf') SheerkaQueryLanguage().compile('asdf & asdf') SheerkaQueryLanguage().compile('asdf | asdf') SheerkaQueryLanguage().compile('(asdf | asdf) & asdf - (asdf & asdf) - (asdf & (afsd | asdf))') SheerkaQueryLanguage().compile('asdf/asdf - asdf/asd[erw]') def test_i_can_parse_flwr_expression(self): SheerkaQueryLanguage().compile('for x in y return x') SheerkaQueryLanguage().compile('for x in return x') SheerkaQueryLanguage().compile('for x in , y in return x') SheerkaQueryLanguage().compile('for x in {for x in return x} return x') SheerkaQueryLanguage().compile('for x in where x == y return x') SheerkaQueryLanguage().compile('for x in let y = return x') SheerkaQueryLanguage().compile('for x in let y = {for x in return x} return x') SheerkaQueryLanguage().compile('for x in let y = , x = return x') SheerkaQueryLanguage().compile('for x in let y = let x = return x') SheerkaQueryLanguage().compile('for x in , z in let y = let x = return x') SheerkaQueryLanguage().compile('''for x in , z in let y = let x = where every x in satisfies (q) return x''') SheerkaQueryLanguage().compile('''for x in , z in let y = let x = where every x in satisfies (q) return x,y,z''') SheerkaQueryLanguage().compile('''for x in , z in let y = let x = where every x in satisfies (q) return x,y.sdf.asd,z''') SheerkaQueryLanguage().compile('''for x in , z in let y = let x = where every x in satisfies (q) return x,y.sdf.asd,z()()()[asdf][asfd](1,2,3)''') SheerkaQueryLanguage().compile('''for x in , z in let y = let x = where every x in satisfies (q) return 'asdf':asdf''') SheerkaQueryLanguage().compile('''for x in , z in let y = let x = where every x in satisfies (q) return 'asdf':asdf, "hello":"hello World!"''') SheerkaQueryLanguage().compile('''for x in , z in let y = let x = where every x in satisfies (q == z and ( is not )) return 'asdf':asdf, "one":1, "2.0":2.0''') SheerkaQueryLanguage().compile('''for x in , z in , y in let y = let x = where every x in satisfies (q == z and ( is not )) return 'asdf':asdf, "one":1, "2.0":2.0''') SheerkaQueryLanguage().compile('''for x in , z in , y in let y = , y1 = , y2 = , y3 = let x = where every x in satisfies (q == z and ( is not )) return 'asdf':asdf, "one":1, "2.0":2.0''') def test_i_can_parse_flwr_with_attribute_value(self): SheerkaQueryLanguage().compile('''for x in , z in , y in sdaf.asdf(asdf, asdf)[1] let y = , y1 = , y2 = , y3 = let x = where every x in satisfies (q == z and ( is not )) return 'asdf':asdf, "one":1, "2.0":2.0''') SheerkaQueryLanguage().compile('''for x in , z in , y in sdaf.asdf(asdf, asdf)[1] let y = , y1 = , y2 = , y3 = let x = let q = sadf.asdf().asfd[1](1,2,3) where every x in satisfies (q == z and ( is not )) return 'asdf':asdf, "one":1, "2.0":2.0''') def test_flwr_orderby(self): SheerkaQueryLanguage().compile('for x in order by "adsf" desc return "adsf":x') SheerkaQueryLanguage().compile('''for x in , z in , y in sdaf.asdf(asdf, asdf)[1] let y = , y1 = , y2 = , y3 = let x = where every x in satisfies (q == z and ( is not )) order by "asdf" desc return 'asdf':asdf, "one":1, "2.0":2.0''') SheerkaQueryLanguage().compile('for x in order by 0 asc return x') SheerkaQueryLanguage().compile('''for x in , z in , y in sdaf.asdf(asdf, asdf)[1] let y = , y1 = , y2 = , y3 = let x = where every x in satisfies (q == z and ( is not )) order by 1 asc return asdf, 1, 2.0''') def test_flwr_function_noargs(self): SheerkaQueryLanguage().compile(''' for x in let f = function() { for y in return y } return f ''') def test_flwr_function_args(self): SheerkaQueryLanguage().compile(''' for x in let f = function(q) { for y in q return y } return f ''') def test_if(self): SheerkaQueryLanguage().compile(''' for x in return if (0) then 1 else 0 ''') def test_reduce(self): SheerkaQueryLanguage().compile(''' for x in collect x.tree as x.attr with function(prev, next) { if prev == None then next else prev.combine(next) } ''') def test_in_list1(self): SheerkaQueryLanguage().compile("hello['foo' in ['foo','bar']]") def test_in_list2(self): SheerkaQueryLanguage().compile("hello['baz' in ['foo','bar']]") def test_not_in_list1(self): SheerkaQueryLanguage().compile("hello['foo' not in ['foo','bar']]") def test_not_in_list2(self): SheerkaQueryLanguage().compile("hello['baz' not in ['foo','bar']]") def test_in_list3(self): result = SheerkaQueryLanguage().execute("res[test_elt in ['foo','bar']]", {'res': True, 'test_elt': 'foo'}) assert bool(result) def test_in_list4(self): result = SheerkaQueryLanguage().execute("res[test_elt in ['foo','bar']]", {'res': True, 'test_elt': 'baz'}) assert not bool(result) def test_not_in_list4(self): result = SheerkaQueryLanguage().execute("res[test_elt not in ['foo','bar']]", {'res': True, 'test_elt': 'baz'}) assert bool(result) def test_not_in_list5(self): result = SheerkaQueryLanguage().execute("res[test_elt not in ['foo','bar']]", {'res': True, 'test_elt': 'foo'}) assert not bool(result) @pytest.mark.parametrize("text, expected", [ ("hello", {"hello"}), ("hello.foo.bar", {"hello"}), ("hello/foo/bar", {"hello"}), ("hello[foo.bar.baz]", {"hello", "foo"}), ("hello[foo()]", {"hello", "foo"}), ("hello[foo(bar)]", {"hello", "foo", "bar"}), ("hello[foo(1, bar.baz)]", {"hello", "foo", "bar"}), ("hello[foo[bar]]", {"hello", "foo", "bar"}), ("hello[foo > bar]", {"hello", "foo", "bar"}), ("hello[foo + bar]", {"hello", "foo", "bar"}), ("hello[[a,b,c]]", {"hello", "a", "b", "c"}), ("hello[{a:b}]", {"hello", "a", "b"}), ]) def test_i_can_get_names(self, text, expected): parser = Parser() parser.parse(bytes(text, 'utf-8').decode('unicode_escape'), lexer=Lexer()) assert parser.names == expected @pytest.mark.parametrize("text", [ "sheerka.method", "sheerka/method", "hello[sheerka.method]", "hello[sheerka.method.xx]", ]) def test_i_can_get_sheerka_methods(self, text): parser = Parser() parser.parse(bytes(text, 'utf-8').decode('unicode_escape'), lexer=Lexer()) assert parser.sheerka_names == {"method"}