Files
kodjo 1059ce25c5 Fixed #68: Implement SheerkaQL
Fixed #70: SheerkaFilterManager : Pipe functions
Fixed #71: SheerkaFilterManager : filter_objects
Fixed #75: SheerkaMemory: Enhance memory() to use the filtering capabilities
Fixed #76: SheerkaEvaluateConcept: Concepts that modify the state of the system must not be evaluated during question
2021-04-26 19:13:47 +02:00

298 lines
14 KiB
Python

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,<asdf>,{for x in <asdf> return x})]')
def test_i_can_parse_where_conditions_with_quantified_expressions(self):
SheerkaQueryLanguage().compile('hello[every x in <asdf> satisfies (x)]')
with pytest.raises(SyntaxError):
SheerkaQueryLanguage().compile('hello[every x in <asdf> statisfies (x)]')
with pytest.raises(SyntaxError):
SheerkaQueryLanguage().compile('hello[every x in <asdf> statisfies x]')
SheerkaQueryLanguage().compile('hello[some x in <asdf> satisfies (x)]')
SheerkaQueryLanguage().compile('hello[some x in <self/asdf> satisfies (x)]')
SheerkaQueryLanguage().compile('hello[some x in {for x in <asdf> return x} satisfies (x)]')
SheerkaQueryLanguage().compile('hello[some x in {for x in <asdf> return x} satisfies (x == y)]')
SheerkaQueryLanguage().compile('hello[some x in {for x in <asdf> 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 <qs>]')
SheerkaQueryLanguage().compile('hello[a not in <qs>]')
SheerkaQueryLanguage().compile('hello[not a in <qs>]')
SheerkaQueryLanguage().compile('hello[<a> subset <qs>]')
SheerkaQueryLanguage().compile('hello[<a> superset <qq>]')
SheerkaQueryLanguage().compile('hello[<a> proper subset <aq>]')
SheerkaQueryLanguage().compile('hello[<a> proper superset <aq>]')
SheerkaQueryLanguage().compile('hello[<a> is <qs>]')
SheerkaQueryLanguage().compile('hello[<a> is not <qs>]')
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 <asfd> return x')
SheerkaQueryLanguage().compile('for x in <asfd>, y in <adsf> return x')
SheerkaQueryLanguage().compile('for x in {for x in <asdf> return x} return x')
SheerkaQueryLanguage().compile('for x in <asfd> where x == y return x')
SheerkaQueryLanguage().compile('for x in <asfd> let y = <x/asdf> return x')
SheerkaQueryLanguage().compile('for x in <asfd> let y = {for x in <asdf> return x} return x')
SheerkaQueryLanguage().compile('for x in <asfd> let y = <x/asdf>, x = <adf> return x')
SheerkaQueryLanguage().compile('for x in <asfd> let y = <x/asdf> let x = <adf> return x')
SheerkaQueryLanguage().compile('for x in <asfd>, z in <asdf> let y = <x/asdf> let x = <adf> return x')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q)
return x''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q)
return x,y,z''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q)
return x,y.sdf.asd,z''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q)
return x,y.sdf.asd,z()()()[asdf][asfd](1,2,3)''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q)
return 'asdf':asdf''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q)
return 'asdf':asdf, "hello":"hello World!"''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q == z and (<y> is not <z>))
return 'asdf':asdf, "one":1, "2.0":2.0''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>, y in <asdf/asdf>
let y = <x/asdf>
let x = <adf>
where every x in <y> satisfies (q == z and (<y> is not <z>))
return 'asdf':asdf, "one":1, "2.0":2.0''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>, y in <asdf/asdf>
let y = <x/asdf>, y1 = <Afd>, y2 = <asdf>, y3 = <asdf>
let x = <adf>
where every x in <y> satisfies (q == z and (<y> is not <z>))
return 'asdf':asdf, "one":1, "2.0":2.0''')
def test_i_can_parse_flwr_with_attribute_value(self):
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>, y in sdaf.asdf(asdf, asdf)[1]
let y = <x/asdf>, y1 = <Afd>, y2 = <asdf>, y3 = <asdf>
let x = <adf>
where every x in <y> satisfies (q == z and (<y> is not <z>))
return 'asdf':asdf, "one":1, "2.0":2.0''')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>, y in sdaf.asdf(asdf, asdf)[1]
let y = <x/asdf>, y1 = <Afd>, y2 = <asdf>, y3 = <asdf>
let x = <adf>
let q = sadf.asdf().asfd[1](1,2,3)
where every x in <y> satisfies (q == z and (<y> is not <z>))
return 'asdf':asdf, "one":1, "2.0":2.0''')
def test_flwr_orderby(self):
SheerkaQueryLanguage().compile('for x in <asdf> order by "adsf" desc return "adsf":x')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>, y in sdaf.asdf(asdf, asdf)[1]
let y = <x/asdf>, y1 = <Afd>, y2 = <asdf>, y3 = <asdf>
let x = <adf>
where every x in <y> satisfies (q == z and (<y> is not <z>))
order by "asdf" desc
return 'asdf':asdf, "one":1, "2.0":2.0''')
SheerkaQueryLanguage().compile('for x in <asdf> order by 0 asc return x')
SheerkaQueryLanguage().compile('''for x in <asfd>, z in <asdf>, y in sdaf.asdf(asdf, asdf)[1]
let y = <x/asdf>, y1 = <Afd>, y2 = <asdf>, y3 = <asdf>
let x = <adf>
where every x in <y> satisfies (q == z and (<y> is not <z>))
order by 1 asc
return asdf, 1, 2.0''')
def test_flwr_function_noargs(self):
SheerkaQueryLanguage().compile('''
for x in <asdf>
let f = function() { for y in <asdf> return y }
return f
''')
def test_flwr_function_args(self):
SheerkaQueryLanguage().compile('''
for x in <asdf>
let f = function(q) { for y in q return y }
return f
''')
def test_if(self):
SheerkaQueryLanguage().compile('''
for x in <asdf> return if (0) then 1 else 0
''')
def test_reduce(self):
SheerkaQueryLanguage().compile('''
for x in <asdf>
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"}