From 1ffb815f25b9f7db7b946f9db436974a687cf818 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 08:28:14 +0100 Subject: folder rename due to python import conflict --- test/query/ast/__init__.py | 0 test/query/ast/test_filter_.py | 480 ------------------------------------ test/query/ast_test/__init__.py | 0 test/query/ast_test/test_filter_.py | 480 ++++++++++++++++++++++++++++++++++++ 4 files changed, 480 insertions(+), 480 deletions(-) delete mode 100644 test/query/ast/__init__.py delete mode 100644 test/query/ast/test_filter_.py create mode 100644 test/query/ast_test/__init__.py create mode 100644 test/query/ast_test/test_filter_.py (limited to 'test/query') diff --git a/test/query/ast/__init__.py b/test/query/ast/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/test/query/ast/test_filter_.py b/test/query/ast/test_filter_.py deleted file mode 100644 index 4f69bdc..0000000 --- a/test/query/ast/test_filter_.py +++ /dev/null @@ -1,480 +0,0 @@ -""" - -Part of the tagit test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" -# imports -import unittest - -# bsfs imports -from bsfs.namespace import ns -from bsfs.utils import URI - -# objects to test -from bsfs.query.ast.filter_ import _Expression, FilterExpression, PredicateExpression -from bsfs.query.ast.filter_ import _Branch, Any, All -from bsfs.query.ast.filter_ import _Agg, And, Or -from bsfs.query.ast.filter_ import Not, Has -from bsfs.query.ast.filter_ import _Value, Is, Equals, Substring, StartsWith, EndsWith -from bsfs.query.ast.filter_ import _Bounded, LessThan, GreaterThan -from bsfs.query.ast.filter_ import Predicate, OneOf -from bsfs.query.ast.filter_ import IsIn, IsNotIn - - -## code ## - -class TestExpression(unittest.TestCase): - def test_essentials(self): - # comparison - self.assertEqual(_Expression(), _Expression()) - self.assertEqual(FilterExpression(), FilterExpression()) - self.assertEqual(PredicateExpression(), PredicateExpression()) - self.assertEqual(hash(_Expression()), hash(_Expression())) - self.assertEqual(hash(FilterExpression()), hash(FilterExpression())) - self.assertEqual(hash(PredicateExpression()), hash(PredicateExpression())) - # comparison respects type - self.assertNotEqual(FilterExpression(), _Expression()) - self.assertNotEqual(_Expression(), PredicateExpression()) - self.assertNotEqual(PredicateExpression(), FilterExpression()) - self.assertNotEqual(hash(FilterExpression()), hash(_Expression())) - self.assertNotEqual(hash(_Expression()), hash(PredicateExpression())) - self.assertNotEqual(hash(PredicateExpression()), hash(FilterExpression())) - # string conversion - self.assertEqual(str(_Expression()), '_Expression()') - self.assertEqual(str(FilterExpression()), 'FilterExpression()') - self.assertEqual(str(PredicateExpression()), 'PredicateExpression()') - self.assertEqual(repr(_Expression()), '_Expression()') - self.assertEqual(repr(FilterExpression()), 'FilterExpression()') - self.assertEqual(repr(PredicateExpression()), 'PredicateExpression()') - - -class TestBranch(unittest.TestCase): # _Branch, Any, All - def test_essentials(self): - pred = PredicateExpression() - expr = FilterExpression() - - # comparison respects type - self.assertNotEqual(_Branch(pred, expr), Any(pred, expr)) - self.assertNotEqual(Any(pred, expr), All(pred, expr)) - self.assertNotEqual(All(pred, expr), _Branch(pred, expr)) - self.assertNotEqual(hash(_Branch(pred, expr)), hash(Any(pred, expr))) - self.assertNotEqual(hash(Any(pred, expr)), hash(All(pred, expr))) - self.assertNotEqual(hash(All(pred, expr)), hash(_Branch(pred, expr))) - - for cls in (_Branch, Any, All): - # comparison - self.assertEqual(cls(pred, expr), cls(pred, expr)) - self.assertEqual(hash(cls(pred, expr)), hash(cls(pred, expr))) - # comparison respects predicate - self.assertNotEqual(cls(ns.bse.filename, expr), cls(ns.bse.filesize, expr)) - self.assertNotEqual(hash(cls(ns.bse.filename, expr)), hash(cls(ns.bse.filesize, expr))) - # comparison respects expression - self.assertNotEqual(cls(pred, Equals('hello')), cls(pred, Equals('world'))) - self.assertNotEqual(hash(cls(pred, Equals('hello'))), hash(cls(pred, Equals('world')))) - - # string conversion - self.assertEqual(str(_Branch(pred, expr)), f'_Branch({pred}, {expr})') - self.assertEqual(repr(_Branch(pred, expr)), f'_Branch({pred}, {expr})') - self.assertEqual(str(Any(pred, expr)), f'Any({pred}, {expr})') - self.assertEqual(repr(Any(pred, expr)), f'Any({pred}, {expr})') - self.assertEqual(str(All(pred, expr)), f'All({pred}, {expr})') - self.assertEqual(repr(All(pred, expr)), f'All({pred}, {expr})') - - def test_members(self): - class Foo(): pass - pred = PredicateExpression() - expr = FilterExpression() - - for cls in (_Branch, Any, All): - # predicate returns member - self.assertEqual(cls(PredicateExpression(), expr).predicate, PredicateExpression()) - # can pass an URI - self.assertEqual(cls(ns.bse.filename, expr).predicate, Predicate(ns.bse.filename)) - # can pass a PredicateExpression - self.assertEqual(cls(Predicate(ns.bse.filename), expr).predicate, Predicate(ns.bse.filename)) - # must pass an URI or PredicateExpression - self.assertRaises(TypeError, cls, Foo(), expr) - # expression returns member - self.assertEqual(cls(pred, Equals('hello')).expr, Equals('hello')) - # expression must be a FilterExpression - self.assertRaises(TypeError, cls, ns.bse.filename, 'hello') - self.assertRaises(TypeError, cls, ns.bse.filename, 1234) - self.assertRaises(TypeError, cls, ns.bse.filename, Foo()) - - -class TestAgg(unittest.TestCase): # _Agg, And, Or - def test_essentials(self): - expr = {Equals('hello'), Equals('world')} - - # comparison respects type - self.assertNotEqual(_Agg(expr), And(expr)) - self.assertNotEqual(And(expr), Or(expr)) - self.assertNotEqual(Or(expr), _Agg(expr)) - self.assertNotEqual(hash(_Agg(expr)), hash(And(expr))) - self.assertNotEqual(hash(And(expr)), hash(Or(expr))) - self.assertNotEqual(hash(Or(expr)), hash(_Agg(expr))) - - for cls in (_Agg, And, Or): - # comparison - self.assertEqual(cls(expr), cls(expr)) - self.assertEqual(hash(cls(expr)), hash(cls(expr))) - # comparison respects expression - self.assertNotEqual(cls(expr), cls(Equals('world'))) - self.assertNotEqual(hash(cls(expr)), hash(cls(Equals('world')))) - self.assertNotEqual(cls(Equals('hello')), cls(Equals('world'))) - self.assertNotEqual(hash(cls(Equals('hello'))), hash(cls(Equals('world')))) - - # string conversion - self.assertEqual(str(_Agg(Equals('hello'))), '_Agg({Equals(hello)})') - self.assertEqual(repr(_Agg(Equals('hello'))), '_Agg({Equals(hello)})') - self.assertEqual(str(And(Equals('hello'))), 'And({Equals(hello)})') - self.assertEqual(repr(And(Equals('hello'))), 'And({Equals(hello)})') - self.assertEqual(str(Or(Equals('hello'))), 'Or({Equals(hello)})') - self.assertEqual(repr(Or(Equals('hello'))), 'Or({Equals(hello)})') - - def test_expression(self): - class Foo(): pass - - for cls in (_Agg, And, Or): - # can pass expressions as arguments - self.assertSetEqual(cls(Equals('hello'), Equals('world')).expr, {Equals('hello'), Equals('world')}) - # can pass one expressions as argument - self.assertSetEqual(cls(Equals('hello')).expr, {Equals('hello')}) - # can pass expressions as iterator - self.assertSetEqual(cls(iter((Equals('hello'), Equals('world')))).expr, {Equals('hello'), Equals('world')}) - # can pass expressions as generator - def gen(): - yield Equals('hello') - yield Equals('world') - self.assertSetEqual(cls(gen()).expr, {Equals('hello'), Equals('world')}) - # can pass expressions as list-like - self.assertSetEqual(cls((Equals('hello'), Equals('world'))).expr, {Equals('hello'), Equals('world')}) - # can pass one expression as list-like - self.assertSetEqual(cls([Equals('hello')]).expr, {Equals('hello')}) - # must pass expressions - self.assertRaises(TypeError, cls, Foo(), Foo()) - self.assertRaises(TypeError, cls, [Foo(), Foo()]) - - # iter - self.assertSetEqual(set(iter(cls(Equals('hello'), Equals('world')))), {Equals('hello'), Equals('world')}) - # contains - self.assertIn(Equals('world'), cls(Equals('hello'), Equals('world'))) - self.assertNotIn(Equals('foo'), cls(Equals('hello'), Equals('world'))) - # len - self.assertEqual(len(cls(Equals('hello'), Equals('world'))), 2) - self.assertEqual(len(cls(Equals('hello'), Equals('world'), Equals('foo'))), 3) - - - -class TestNot(unittest.TestCase): - def test_essentials(self): - expr = FilterExpression() - # comparison - self.assertEqual(Not(expr), Not(expr)) - self.assertEqual(hash(Not(expr)), hash(Not(expr))) - # comparison respects type - self.assertNotEqual(Not(expr), FilterExpression()) - self.assertNotEqual(hash(Not(expr)), hash(FilterExpression())) - # comparison respects expression - self.assertNotEqual(Not(Equals('hello')), Not(Equals('world'))) - self.assertNotEqual(hash(Not(Equals('hello'))), hash(Not(Equals('world')))) - # string conversion - self.assertEqual(str(Not(Equals('hello'))), 'Not(Equals(hello))') - self.assertEqual(repr(Not(Equals('hello'))), 'Not(Equals(hello))') - - def test_expression(self): - # Not requires an expression argument - self.assertRaises(TypeError, Not) - # expression must be a FilterExpression - self.assertRaises(TypeError, Not, 'hello') - self.assertRaises(TypeError, Not, 1234) - self.assertRaises(TypeError, Not, Predicate(ns.bse.filesize)) - # member returns expression - self.assertEqual(Not(Equals('hello')).expr, Equals('hello')) - - -class TestHas(unittest.TestCase): - def test_essentials(self): - pred = PredicateExpression() - count = FilterExpression() - # comparison - self.assertEqual(Has(pred, count), Has(pred, count)) - self.assertEqual(hash(Has(pred, count)), hash(Has(pred, count))) - # comparison respects type - self.assertNotEqual(Has(pred, count), FilterExpression()) - self.assertNotEqual(hash(Has(pred, count)), hash(FilterExpression())) - # comparison respects predicate - self.assertNotEqual(Has(pred, count), Has(Predicate(ns.bse.filesize), count)) - self.assertNotEqual(hash(Has(pred, count)), hash(Has(Predicate(ns.bse.filesize), count))) - # comparison respects count - self.assertNotEqual(Has(pred, count), Has(pred, LessThan(5))) - self.assertNotEqual(hash(Has(pred, count)), hash(Has(pred, LessThan(5)))) - # string conversion - self.assertEqual(str(Has(Predicate(ns.bse.filesize), LessThan(5))), - f'Has(Predicate({ns.bse.filesize}, False), LessThan(5.0, True))') - self.assertEqual(repr(Has(Predicate(ns.bse.filesize), LessThan(5))), - f'Has(Predicate({ns.bse.filesize}, False), LessThan(5.0, True))') - - def test_members(self): - pred = PredicateExpression() - count = FilterExpression() - # member returns expression - # predicate must be an URI or a PredicateExpression - self.assertEqual(Has(ns.bse.filesize, count).predicate, Predicate(ns.bse.filesize)) - self.assertEqual(Has(Predicate(ns.bse.filesize), count).predicate, Predicate(ns.bse.filesize)) - self.assertRaises(TypeError, Has, 1234, FilterExpression()) - self.assertRaises(TypeError, Has, FilterExpression(), FilterExpression()) - # member returns count - # count must be None, an integer, or a FilterExpression - self.assertEqual(Has(pred).count, GreaterThan(1, False)) - self.assertEqual(Has(pred, LessThan(5)).count, LessThan(5)) - self.assertEqual(Has(pred, 5).count, Equals(5)) - self.assertRaises(TypeError, Has, pred, 'hello') - self.assertRaises(TypeError, Has, pred, Predicate(ns.bse.filesize)) - - - -class TestValue(unittest.TestCase): - def test_essentials(self): - # comparison respects type - self.assertNotEqual(_Value('hello'), Equals('hello')) - self.assertNotEqual(Equals('hello'), Is('hello')) - self.assertNotEqual(Is('hello'), Substring('hello')) - self.assertNotEqual(Substring('hello'), StartsWith('hello')) - self.assertNotEqual(StartsWith('hello'), EndsWith('hello')) - self.assertNotEqual(EndsWith('hello'), _Value('hello')) - self.assertNotEqual(hash(_Value('hello')), hash(Equals('hello'))) - self.assertNotEqual(hash(Equals('hello')), hash(Is('hello'))) - self.assertNotEqual(hash(Is('hello')), hash(Substring('hello'))) - self.assertNotEqual(hash(Substring('hello')), hash(StartsWith('hello'))) - self.assertNotEqual(hash(StartsWith('hello')), hash(EndsWith('hello'))) - self.assertNotEqual(hash(EndsWith('hello')), hash(_Value('hello'))) - - for cls in (_Value, Is, Equals, Substring, StartsWith, EndsWith): - # comparison - self.assertEqual(cls('hello'), cls('hello')) - self.assertEqual(hash(cls('hello')), hash(cls('hello'))) - # comparison respects value - self.assertNotEqual(cls('hello'), cls('world')) - self.assertNotEqual(hash(cls('hello')), hash(cls('world'))) - - # string conversion - self.assertEqual(str(_Value('hello')), '_Value(hello)') - self.assertEqual(repr(_Value('hello')), '_Value(hello)') - self.assertEqual(str(Is('hello')), 'Is(hello)') - self.assertEqual(repr(Is('hello')), 'Is(hello)') - self.assertEqual(str(Equals('hello')), 'Equals(hello)') - self.assertEqual(repr(Equals('hello')), 'Equals(hello)') - self.assertEqual(str(Substring('hello')), 'Substring(hello)') - self.assertEqual(repr(Substring('hello')), 'Substring(hello)') - self.assertEqual(str(StartsWith('hello')), 'StartsWith(hello)') - self.assertEqual(repr(StartsWith('hello')), 'StartsWith(hello)') - self.assertEqual(str(EndsWith('hello')), 'EndsWith(hello)') - self.assertEqual(repr(EndsWith('hello')), 'EndsWith(hello)') - - def test_value(self): - class Foo(): pass - for cls in (_Value, Is, Equals, Substring, StartsWith, EndsWith): - # value can be anything - # value returns member - f = Foo() - self.assertEqual(cls('hello').value, 'hello') - self.assertEqual(cls(1234).value, 1234) - self.assertEqual(cls(f).value, f) - - -class TestBounded(unittest.TestCase): - def test_essentials(self): - # comparison respects type - self.assertNotEqual(_Bounded(1234), LessThan(1234)) - self.assertNotEqual(LessThan(1234), GreaterThan(1234)) - self.assertNotEqual(GreaterThan(1234), _Bounded(1234)) - self.assertNotEqual(hash(_Bounded(1234)), hash(LessThan(1234))) - self.assertNotEqual(hash(LessThan(1234)), hash(GreaterThan(1234))) - self.assertNotEqual(hash(GreaterThan(1234)), hash(_Bounded(1234))) - - for cls in (_Bounded, LessThan, GreaterThan): - # comparison - self.assertEqual(cls(1234), cls(1234)) - self.assertEqual(hash(cls(1234)), hash(cls(1234))) - # comparison respects threshold - self.assertNotEqual(cls(1234), cls(4321)) - self.assertNotEqual(hash(cls(1234)), hash(cls(4321))) - # comparison respects strict - self.assertNotEqual(cls(1234, True), cls(1234, False)) - self.assertNotEqual(hash(cls(1234, True)), hash(cls(1234, False))) - - # string conversion - self.assertEqual(str(_Bounded(1234, False)), '_Bounded(1234.0, False)') - self.assertEqual(repr(_Bounded(1234, False)), '_Bounded(1234.0, False)') - self.assertEqual(str(LessThan(1234, False)), 'LessThan(1234.0, False)') - self.assertEqual(repr(LessThan(1234, False)), 'LessThan(1234.0, False)') - self.assertEqual(str(GreaterThan(1234, False)), 'GreaterThan(1234.0, False)') - self.assertEqual(repr(GreaterThan(1234, False)), 'GreaterThan(1234.0, False)') - - def test_members(self): - class Foo(): pass - for cls in (_Bounded, LessThan, GreaterThan): - # threshold becomes float - self.assertEqual(cls(1.234).threshold, 1.234) - self.assertEqual(cls(1234).threshold, 1234.0) - self.assertEqual(cls('1234').threshold, 1234) - self.assertRaises(TypeError, cls, Foo()) - # strict becomes bool - self.assertEqual(cls(1234, True).strict, True) - self.assertEqual(cls(1234, False).strict, False) - self.assertEqual(cls(1234, Foo()).strict, True) - - -class TestPredicate(unittest.TestCase): - def test_essentials(self): - # comparison - self.assertEqual(Predicate(ns.bse.filesize), Predicate(ns.bse.filesize)) - self.assertEqual(hash(Predicate(ns.bse.filesize)), hash(Predicate(ns.bse.filesize))) - # comparison respects type - self.assertNotEqual(Predicate(ns.bse.filesize), PredicateExpression()) - self.assertNotEqual(hash(Predicate(ns.bse.filesize)), hash(PredicateExpression())) - # comparison respects predicate - self.assertNotEqual(Predicate(ns.bse.filesize), Predicate(ns.bse.filename)) - self.assertNotEqual(hash(Predicate(ns.bse.filesize)), hash(Predicate(ns.bse.filename))) - # comparison respects reverse - self.assertNotEqual(Predicate(ns.bse.filesize, True), Predicate(ns.bse.filesize, False)) - self.assertNotEqual(hash(Predicate(ns.bse.filesize, True)), hash(Predicate(ns.bse.filesize, False))) - # string conversion - self.assertEqual(str(Predicate(ns.bse.filesize)), f'Predicate({ns.bse.filesize}, False)') - self.assertEqual(str(Predicate(ns.bse.filesize, True)), - f'Predicate({ns.bse.filesize}, True)') - self.assertEqual(repr(Predicate(ns.bse.filesize)), f'Predicate({ns.bse.filesize}, False)') - self.assertEqual(repr(Predicate(ns.bse.filesize, True)), - f'Predicate({ns.bse.filesize}, True)') - - def test_members(self): - # member returns predicate - # predicate must be an URI - self.assertEqual(Predicate(ns.bse.filesize).predicate, ns.bse.filesize) - self.assertEqual(Predicate(URI('hello world')).predicate, URI('hello world')) - self.assertRaises(TypeError, Predicate, 1234) - self.assertRaises(TypeError, Predicate, FilterExpression()) - self.assertRaises(TypeError, Predicate, FilterExpression()) - # reverse becomes a boolean - self.assertEqual(Predicate(ns.bse.filesize, True).reverse, True) - self.assertEqual(Predicate(ns.bse.filesize, False).reverse, False) - self.assertEqual(Predicate(ns.bse.filesize, 'abc').reverse, True) - - -class TestOneOf(unittest.TestCase): - def test_essentials(self): - expr = {Predicate(ns.bse.filename), Predicate(ns.bse.filesize)} - # comparison - self.assertEqual(OneOf(expr), OneOf(expr)) - self.assertEqual(hash(OneOf(expr)), hash(OneOf(expr))) - # comparison respects type - self.assertNotEqual(OneOf(expr), PredicateExpression()) - self.assertNotEqual(hash(OneOf(expr)), hash(PredicateExpression())) - # comparison respects expression - self.assertNotEqual(OneOf(expr), OneOf(Predicate(ns.bse.filename))) - self.assertNotEqual(hash(OneOf(expr)), hash(OneOf(Predicate(ns.bse.filename)))) - # string conversion - self.assertEqual(str(OneOf(Predicate(ns.bse.filesize))), - f'OneOf({{Predicate({ns.bse.filesize}, False)}})') - self.assertEqual(repr(OneOf(Predicate(ns.bse.filesize))), - f'OneOf({{Predicate({ns.bse.filesize}, False)}})') - - def test_expression(self): - class Foo(): pass - # can pass expressions as arguments - self.assertSetEqual(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename)).expr, - {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) - # can pass one expressions as argument - self.assertSetEqual(OneOf(Predicate(ns.bse.filesize)).expr, - {Predicate(ns.bse.filesize)}) - # can pass expressions as iterator - self.assertSetEqual(OneOf(iter((Predicate(ns.bse.filesize), Predicate(ns.bse.filename)))).expr, - {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) - # can pass expressions as generator - def gen(): - yield Predicate(ns.bse.filesize) - yield Predicate(ns.bse.filename) - self.assertSetEqual(OneOf(gen()).expr, - {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) - # can pass expressions as list-like - self.assertSetEqual(OneOf((Predicate(ns.bse.filesize), Predicate(ns.bse.filename))).expr, - {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) - # can pass one expression as list-like - self.assertSetEqual(OneOf([Predicate(ns.bse.filesize)]).expr, - {Predicate(ns.bse.filesize)}) - # must pass expressions - self.assertRaises(TypeError, OneOf, Foo(), Foo()) - self.assertRaises(TypeError, OneOf, [Foo(), Foo()]) - # must pass at least one expression - self.assertRaises(AttributeError, OneOf) - - # iter - self.assertSetEqual(set(iter(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename)))), - {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) - # contains - self.assertIn(Predicate(ns.bse.filesize), - OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename))) - self.assertNotIn(Predicate(ns.bse.tag), - OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename))) - # len - self.assertEqual(len(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename))), 2) - self.assertEqual(len(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename), Predicate(ns.bse.tag))), 3) - - - def testIsIn(self): - # can pass expressions as arguments - self.assertEqual(IsIn('http://example.com/entity#1234', 'http://example.com/entity#4321'), - Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) - # can pass one expression as argument - self.assertEqual(IsIn('http://example.com/entity#1234'), - Or(Is('http://example.com/entity#1234'))) - # can pass expressions as iterator - self.assertEqual(IsIn(iter(('http://example.com/entity#1234', 'http://example.com/entity#4321'))), - Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) - # can pass expressions as generator - def gen(): - yield 'http://example.com/entity#1234' - yield 'http://example.com/entity#4321' - self.assertEqual(IsIn(gen()), - Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) - # can pass expressions as list-like - self.assertEqual(IsIn(['http://example.com/entity#1234', 'http://example.com/entity#4321']), - Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) - # can pass one expression as list-like - self.assertEqual(IsIn(['http://example.com/entity#1234']), - Or(Is('http://example.com/entity#1234'))) - - - def testIsNotIn(self): - # can pass expressions as arguments - self.assertEqual(IsNotIn('http://example.com/entity#1234', 'http://example.com/entity#4321'), - Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) - # can pass one expression as argument - self.assertEqual(IsNotIn('http://example.com/entity#1234'), - Not(Or(Is('http://example.com/entity#1234')))) - # can pass expressions as iterator - self.assertEqual(IsNotIn(iter(('http://example.com/entity#1234', 'http://example.com/entity#4321'))), - Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) - # can pass expressions as generator - def gen(): - yield 'http://example.com/entity#1234' - yield 'http://example.com/entity#4321' - self.assertEqual(IsNotIn(gen()), - Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) - # can pass expressions as list-like - self.assertEqual(IsNotIn(['http://example.com/entity#1234', 'http://example.com/entity#4321']), - Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) - # can pass one expression as list-like - self.assertEqual(IsNotIn(['http://example.com/entity#1234']), - Not(Or(Is('http://example.com/entity#1234')))) - - - -## main ## - -if __name__ == '__main__': - unittest.main() - -## EOF ## diff --git a/test/query/ast_test/__init__.py b/test/query/ast_test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/query/ast_test/test_filter_.py b/test/query/ast_test/test_filter_.py new file mode 100644 index 0000000..4f69bdc --- /dev/null +++ b/test/query/ast_test/test_filter_.py @@ -0,0 +1,480 @@ +""" + +Part of the tagit test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsfs imports +from bsfs.namespace import ns +from bsfs.utils import URI + +# objects to test +from bsfs.query.ast.filter_ import _Expression, FilterExpression, PredicateExpression +from bsfs.query.ast.filter_ import _Branch, Any, All +from bsfs.query.ast.filter_ import _Agg, And, Or +from bsfs.query.ast.filter_ import Not, Has +from bsfs.query.ast.filter_ import _Value, Is, Equals, Substring, StartsWith, EndsWith +from bsfs.query.ast.filter_ import _Bounded, LessThan, GreaterThan +from bsfs.query.ast.filter_ import Predicate, OneOf +from bsfs.query.ast.filter_ import IsIn, IsNotIn + + +## code ## + +class TestExpression(unittest.TestCase): + def test_essentials(self): + # comparison + self.assertEqual(_Expression(), _Expression()) + self.assertEqual(FilterExpression(), FilterExpression()) + self.assertEqual(PredicateExpression(), PredicateExpression()) + self.assertEqual(hash(_Expression()), hash(_Expression())) + self.assertEqual(hash(FilterExpression()), hash(FilterExpression())) + self.assertEqual(hash(PredicateExpression()), hash(PredicateExpression())) + # comparison respects type + self.assertNotEqual(FilterExpression(), _Expression()) + self.assertNotEqual(_Expression(), PredicateExpression()) + self.assertNotEqual(PredicateExpression(), FilterExpression()) + self.assertNotEqual(hash(FilterExpression()), hash(_Expression())) + self.assertNotEqual(hash(_Expression()), hash(PredicateExpression())) + self.assertNotEqual(hash(PredicateExpression()), hash(FilterExpression())) + # string conversion + self.assertEqual(str(_Expression()), '_Expression()') + self.assertEqual(str(FilterExpression()), 'FilterExpression()') + self.assertEqual(str(PredicateExpression()), 'PredicateExpression()') + self.assertEqual(repr(_Expression()), '_Expression()') + self.assertEqual(repr(FilterExpression()), 'FilterExpression()') + self.assertEqual(repr(PredicateExpression()), 'PredicateExpression()') + + +class TestBranch(unittest.TestCase): # _Branch, Any, All + def test_essentials(self): + pred = PredicateExpression() + expr = FilterExpression() + + # comparison respects type + self.assertNotEqual(_Branch(pred, expr), Any(pred, expr)) + self.assertNotEqual(Any(pred, expr), All(pred, expr)) + self.assertNotEqual(All(pred, expr), _Branch(pred, expr)) + self.assertNotEqual(hash(_Branch(pred, expr)), hash(Any(pred, expr))) + self.assertNotEqual(hash(Any(pred, expr)), hash(All(pred, expr))) + self.assertNotEqual(hash(All(pred, expr)), hash(_Branch(pred, expr))) + + for cls in (_Branch, Any, All): + # comparison + self.assertEqual(cls(pred, expr), cls(pred, expr)) + self.assertEqual(hash(cls(pred, expr)), hash(cls(pred, expr))) + # comparison respects predicate + self.assertNotEqual(cls(ns.bse.filename, expr), cls(ns.bse.filesize, expr)) + self.assertNotEqual(hash(cls(ns.bse.filename, expr)), hash(cls(ns.bse.filesize, expr))) + # comparison respects expression + self.assertNotEqual(cls(pred, Equals('hello')), cls(pred, Equals('world'))) + self.assertNotEqual(hash(cls(pred, Equals('hello'))), hash(cls(pred, Equals('world')))) + + # string conversion + self.assertEqual(str(_Branch(pred, expr)), f'_Branch({pred}, {expr})') + self.assertEqual(repr(_Branch(pred, expr)), f'_Branch({pred}, {expr})') + self.assertEqual(str(Any(pred, expr)), f'Any({pred}, {expr})') + self.assertEqual(repr(Any(pred, expr)), f'Any({pred}, {expr})') + self.assertEqual(str(All(pred, expr)), f'All({pred}, {expr})') + self.assertEqual(repr(All(pred, expr)), f'All({pred}, {expr})') + + def test_members(self): + class Foo(): pass + pred = PredicateExpression() + expr = FilterExpression() + + for cls in (_Branch, Any, All): + # predicate returns member + self.assertEqual(cls(PredicateExpression(), expr).predicate, PredicateExpression()) + # can pass an URI + self.assertEqual(cls(ns.bse.filename, expr).predicate, Predicate(ns.bse.filename)) + # can pass a PredicateExpression + self.assertEqual(cls(Predicate(ns.bse.filename), expr).predicate, Predicate(ns.bse.filename)) + # must pass an URI or PredicateExpression + self.assertRaises(TypeError, cls, Foo(), expr) + # expression returns member + self.assertEqual(cls(pred, Equals('hello')).expr, Equals('hello')) + # expression must be a FilterExpression + self.assertRaises(TypeError, cls, ns.bse.filename, 'hello') + self.assertRaises(TypeError, cls, ns.bse.filename, 1234) + self.assertRaises(TypeError, cls, ns.bse.filename, Foo()) + + +class TestAgg(unittest.TestCase): # _Agg, And, Or + def test_essentials(self): + expr = {Equals('hello'), Equals('world')} + + # comparison respects type + self.assertNotEqual(_Agg(expr), And(expr)) + self.assertNotEqual(And(expr), Or(expr)) + self.assertNotEqual(Or(expr), _Agg(expr)) + self.assertNotEqual(hash(_Agg(expr)), hash(And(expr))) + self.assertNotEqual(hash(And(expr)), hash(Or(expr))) + self.assertNotEqual(hash(Or(expr)), hash(_Agg(expr))) + + for cls in (_Agg, And, Or): + # comparison + self.assertEqual(cls(expr), cls(expr)) + self.assertEqual(hash(cls(expr)), hash(cls(expr))) + # comparison respects expression + self.assertNotEqual(cls(expr), cls(Equals('world'))) + self.assertNotEqual(hash(cls(expr)), hash(cls(Equals('world')))) + self.assertNotEqual(cls(Equals('hello')), cls(Equals('world'))) + self.assertNotEqual(hash(cls(Equals('hello'))), hash(cls(Equals('world')))) + + # string conversion + self.assertEqual(str(_Agg(Equals('hello'))), '_Agg({Equals(hello)})') + self.assertEqual(repr(_Agg(Equals('hello'))), '_Agg({Equals(hello)})') + self.assertEqual(str(And(Equals('hello'))), 'And({Equals(hello)})') + self.assertEqual(repr(And(Equals('hello'))), 'And({Equals(hello)})') + self.assertEqual(str(Or(Equals('hello'))), 'Or({Equals(hello)})') + self.assertEqual(repr(Or(Equals('hello'))), 'Or({Equals(hello)})') + + def test_expression(self): + class Foo(): pass + + for cls in (_Agg, And, Or): + # can pass expressions as arguments + self.assertSetEqual(cls(Equals('hello'), Equals('world')).expr, {Equals('hello'), Equals('world')}) + # can pass one expressions as argument + self.assertSetEqual(cls(Equals('hello')).expr, {Equals('hello')}) + # can pass expressions as iterator + self.assertSetEqual(cls(iter((Equals('hello'), Equals('world')))).expr, {Equals('hello'), Equals('world')}) + # can pass expressions as generator + def gen(): + yield Equals('hello') + yield Equals('world') + self.assertSetEqual(cls(gen()).expr, {Equals('hello'), Equals('world')}) + # can pass expressions as list-like + self.assertSetEqual(cls((Equals('hello'), Equals('world'))).expr, {Equals('hello'), Equals('world')}) + # can pass one expression as list-like + self.assertSetEqual(cls([Equals('hello')]).expr, {Equals('hello')}) + # must pass expressions + self.assertRaises(TypeError, cls, Foo(), Foo()) + self.assertRaises(TypeError, cls, [Foo(), Foo()]) + + # iter + self.assertSetEqual(set(iter(cls(Equals('hello'), Equals('world')))), {Equals('hello'), Equals('world')}) + # contains + self.assertIn(Equals('world'), cls(Equals('hello'), Equals('world'))) + self.assertNotIn(Equals('foo'), cls(Equals('hello'), Equals('world'))) + # len + self.assertEqual(len(cls(Equals('hello'), Equals('world'))), 2) + self.assertEqual(len(cls(Equals('hello'), Equals('world'), Equals('foo'))), 3) + + + +class TestNot(unittest.TestCase): + def test_essentials(self): + expr = FilterExpression() + # comparison + self.assertEqual(Not(expr), Not(expr)) + self.assertEqual(hash(Not(expr)), hash(Not(expr))) + # comparison respects type + self.assertNotEqual(Not(expr), FilterExpression()) + self.assertNotEqual(hash(Not(expr)), hash(FilterExpression())) + # comparison respects expression + self.assertNotEqual(Not(Equals('hello')), Not(Equals('world'))) + self.assertNotEqual(hash(Not(Equals('hello'))), hash(Not(Equals('world')))) + # string conversion + self.assertEqual(str(Not(Equals('hello'))), 'Not(Equals(hello))') + self.assertEqual(repr(Not(Equals('hello'))), 'Not(Equals(hello))') + + def test_expression(self): + # Not requires an expression argument + self.assertRaises(TypeError, Not) + # expression must be a FilterExpression + self.assertRaises(TypeError, Not, 'hello') + self.assertRaises(TypeError, Not, 1234) + self.assertRaises(TypeError, Not, Predicate(ns.bse.filesize)) + # member returns expression + self.assertEqual(Not(Equals('hello')).expr, Equals('hello')) + + +class TestHas(unittest.TestCase): + def test_essentials(self): + pred = PredicateExpression() + count = FilterExpression() + # comparison + self.assertEqual(Has(pred, count), Has(pred, count)) + self.assertEqual(hash(Has(pred, count)), hash(Has(pred, count))) + # comparison respects type + self.assertNotEqual(Has(pred, count), FilterExpression()) + self.assertNotEqual(hash(Has(pred, count)), hash(FilterExpression())) + # comparison respects predicate + self.assertNotEqual(Has(pred, count), Has(Predicate(ns.bse.filesize), count)) + self.assertNotEqual(hash(Has(pred, count)), hash(Has(Predicate(ns.bse.filesize), count))) + # comparison respects count + self.assertNotEqual(Has(pred, count), Has(pred, LessThan(5))) + self.assertNotEqual(hash(Has(pred, count)), hash(Has(pred, LessThan(5)))) + # string conversion + self.assertEqual(str(Has(Predicate(ns.bse.filesize), LessThan(5))), + f'Has(Predicate({ns.bse.filesize}, False), LessThan(5.0, True))') + self.assertEqual(repr(Has(Predicate(ns.bse.filesize), LessThan(5))), + f'Has(Predicate({ns.bse.filesize}, False), LessThan(5.0, True))') + + def test_members(self): + pred = PredicateExpression() + count = FilterExpression() + # member returns expression + # predicate must be an URI or a PredicateExpression + self.assertEqual(Has(ns.bse.filesize, count).predicate, Predicate(ns.bse.filesize)) + self.assertEqual(Has(Predicate(ns.bse.filesize), count).predicate, Predicate(ns.bse.filesize)) + self.assertRaises(TypeError, Has, 1234, FilterExpression()) + self.assertRaises(TypeError, Has, FilterExpression(), FilterExpression()) + # member returns count + # count must be None, an integer, or a FilterExpression + self.assertEqual(Has(pred).count, GreaterThan(1, False)) + self.assertEqual(Has(pred, LessThan(5)).count, LessThan(5)) + self.assertEqual(Has(pred, 5).count, Equals(5)) + self.assertRaises(TypeError, Has, pred, 'hello') + self.assertRaises(TypeError, Has, pred, Predicate(ns.bse.filesize)) + + + +class TestValue(unittest.TestCase): + def test_essentials(self): + # comparison respects type + self.assertNotEqual(_Value('hello'), Equals('hello')) + self.assertNotEqual(Equals('hello'), Is('hello')) + self.assertNotEqual(Is('hello'), Substring('hello')) + self.assertNotEqual(Substring('hello'), StartsWith('hello')) + self.assertNotEqual(StartsWith('hello'), EndsWith('hello')) + self.assertNotEqual(EndsWith('hello'), _Value('hello')) + self.assertNotEqual(hash(_Value('hello')), hash(Equals('hello'))) + self.assertNotEqual(hash(Equals('hello')), hash(Is('hello'))) + self.assertNotEqual(hash(Is('hello')), hash(Substring('hello'))) + self.assertNotEqual(hash(Substring('hello')), hash(StartsWith('hello'))) + self.assertNotEqual(hash(StartsWith('hello')), hash(EndsWith('hello'))) + self.assertNotEqual(hash(EndsWith('hello')), hash(_Value('hello'))) + + for cls in (_Value, Is, Equals, Substring, StartsWith, EndsWith): + # comparison + self.assertEqual(cls('hello'), cls('hello')) + self.assertEqual(hash(cls('hello')), hash(cls('hello'))) + # comparison respects value + self.assertNotEqual(cls('hello'), cls('world')) + self.assertNotEqual(hash(cls('hello')), hash(cls('world'))) + + # string conversion + self.assertEqual(str(_Value('hello')), '_Value(hello)') + self.assertEqual(repr(_Value('hello')), '_Value(hello)') + self.assertEqual(str(Is('hello')), 'Is(hello)') + self.assertEqual(repr(Is('hello')), 'Is(hello)') + self.assertEqual(str(Equals('hello')), 'Equals(hello)') + self.assertEqual(repr(Equals('hello')), 'Equals(hello)') + self.assertEqual(str(Substring('hello')), 'Substring(hello)') + self.assertEqual(repr(Substring('hello')), 'Substring(hello)') + self.assertEqual(str(StartsWith('hello')), 'StartsWith(hello)') + self.assertEqual(repr(StartsWith('hello')), 'StartsWith(hello)') + self.assertEqual(str(EndsWith('hello')), 'EndsWith(hello)') + self.assertEqual(repr(EndsWith('hello')), 'EndsWith(hello)') + + def test_value(self): + class Foo(): pass + for cls in (_Value, Is, Equals, Substring, StartsWith, EndsWith): + # value can be anything + # value returns member + f = Foo() + self.assertEqual(cls('hello').value, 'hello') + self.assertEqual(cls(1234).value, 1234) + self.assertEqual(cls(f).value, f) + + +class TestBounded(unittest.TestCase): + def test_essentials(self): + # comparison respects type + self.assertNotEqual(_Bounded(1234), LessThan(1234)) + self.assertNotEqual(LessThan(1234), GreaterThan(1234)) + self.assertNotEqual(GreaterThan(1234), _Bounded(1234)) + self.assertNotEqual(hash(_Bounded(1234)), hash(LessThan(1234))) + self.assertNotEqual(hash(LessThan(1234)), hash(GreaterThan(1234))) + self.assertNotEqual(hash(GreaterThan(1234)), hash(_Bounded(1234))) + + for cls in (_Bounded, LessThan, GreaterThan): + # comparison + self.assertEqual(cls(1234), cls(1234)) + self.assertEqual(hash(cls(1234)), hash(cls(1234))) + # comparison respects threshold + self.assertNotEqual(cls(1234), cls(4321)) + self.assertNotEqual(hash(cls(1234)), hash(cls(4321))) + # comparison respects strict + self.assertNotEqual(cls(1234, True), cls(1234, False)) + self.assertNotEqual(hash(cls(1234, True)), hash(cls(1234, False))) + + # string conversion + self.assertEqual(str(_Bounded(1234, False)), '_Bounded(1234.0, False)') + self.assertEqual(repr(_Bounded(1234, False)), '_Bounded(1234.0, False)') + self.assertEqual(str(LessThan(1234, False)), 'LessThan(1234.0, False)') + self.assertEqual(repr(LessThan(1234, False)), 'LessThan(1234.0, False)') + self.assertEqual(str(GreaterThan(1234, False)), 'GreaterThan(1234.0, False)') + self.assertEqual(repr(GreaterThan(1234, False)), 'GreaterThan(1234.0, False)') + + def test_members(self): + class Foo(): pass + for cls in (_Bounded, LessThan, GreaterThan): + # threshold becomes float + self.assertEqual(cls(1.234).threshold, 1.234) + self.assertEqual(cls(1234).threshold, 1234.0) + self.assertEqual(cls('1234').threshold, 1234) + self.assertRaises(TypeError, cls, Foo()) + # strict becomes bool + self.assertEqual(cls(1234, True).strict, True) + self.assertEqual(cls(1234, False).strict, False) + self.assertEqual(cls(1234, Foo()).strict, True) + + +class TestPredicate(unittest.TestCase): + def test_essentials(self): + # comparison + self.assertEqual(Predicate(ns.bse.filesize), Predicate(ns.bse.filesize)) + self.assertEqual(hash(Predicate(ns.bse.filesize)), hash(Predicate(ns.bse.filesize))) + # comparison respects type + self.assertNotEqual(Predicate(ns.bse.filesize), PredicateExpression()) + self.assertNotEqual(hash(Predicate(ns.bse.filesize)), hash(PredicateExpression())) + # comparison respects predicate + self.assertNotEqual(Predicate(ns.bse.filesize), Predicate(ns.bse.filename)) + self.assertNotEqual(hash(Predicate(ns.bse.filesize)), hash(Predicate(ns.bse.filename))) + # comparison respects reverse + self.assertNotEqual(Predicate(ns.bse.filesize, True), Predicate(ns.bse.filesize, False)) + self.assertNotEqual(hash(Predicate(ns.bse.filesize, True)), hash(Predicate(ns.bse.filesize, False))) + # string conversion + self.assertEqual(str(Predicate(ns.bse.filesize)), f'Predicate({ns.bse.filesize}, False)') + self.assertEqual(str(Predicate(ns.bse.filesize, True)), + f'Predicate({ns.bse.filesize}, True)') + self.assertEqual(repr(Predicate(ns.bse.filesize)), f'Predicate({ns.bse.filesize}, False)') + self.assertEqual(repr(Predicate(ns.bse.filesize, True)), + f'Predicate({ns.bse.filesize}, True)') + + def test_members(self): + # member returns predicate + # predicate must be an URI + self.assertEqual(Predicate(ns.bse.filesize).predicate, ns.bse.filesize) + self.assertEqual(Predicate(URI('hello world')).predicate, URI('hello world')) + self.assertRaises(TypeError, Predicate, 1234) + self.assertRaises(TypeError, Predicate, FilterExpression()) + self.assertRaises(TypeError, Predicate, FilterExpression()) + # reverse becomes a boolean + self.assertEqual(Predicate(ns.bse.filesize, True).reverse, True) + self.assertEqual(Predicate(ns.bse.filesize, False).reverse, False) + self.assertEqual(Predicate(ns.bse.filesize, 'abc').reverse, True) + + +class TestOneOf(unittest.TestCase): + def test_essentials(self): + expr = {Predicate(ns.bse.filename), Predicate(ns.bse.filesize)} + # comparison + self.assertEqual(OneOf(expr), OneOf(expr)) + self.assertEqual(hash(OneOf(expr)), hash(OneOf(expr))) + # comparison respects type + self.assertNotEqual(OneOf(expr), PredicateExpression()) + self.assertNotEqual(hash(OneOf(expr)), hash(PredicateExpression())) + # comparison respects expression + self.assertNotEqual(OneOf(expr), OneOf(Predicate(ns.bse.filename))) + self.assertNotEqual(hash(OneOf(expr)), hash(OneOf(Predicate(ns.bse.filename)))) + # string conversion + self.assertEqual(str(OneOf(Predicate(ns.bse.filesize))), + f'OneOf({{Predicate({ns.bse.filesize}, False)}})') + self.assertEqual(repr(OneOf(Predicate(ns.bse.filesize))), + f'OneOf({{Predicate({ns.bse.filesize}, False)}})') + + def test_expression(self): + class Foo(): pass + # can pass expressions as arguments + self.assertSetEqual(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename)).expr, + {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) + # can pass one expressions as argument + self.assertSetEqual(OneOf(Predicate(ns.bse.filesize)).expr, + {Predicate(ns.bse.filesize)}) + # can pass expressions as iterator + self.assertSetEqual(OneOf(iter((Predicate(ns.bse.filesize), Predicate(ns.bse.filename)))).expr, + {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) + # can pass expressions as generator + def gen(): + yield Predicate(ns.bse.filesize) + yield Predicate(ns.bse.filename) + self.assertSetEqual(OneOf(gen()).expr, + {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) + # can pass expressions as list-like + self.assertSetEqual(OneOf((Predicate(ns.bse.filesize), Predicate(ns.bse.filename))).expr, + {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) + # can pass one expression as list-like + self.assertSetEqual(OneOf([Predicate(ns.bse.filesize)]).expr, + {Predicate(ns.bse.filesize)}) + # must pass expressions + self.assertRaises(TypeError, OneOf, Foo(), Foo()) + self.assertRaises(TypeError, OneOf, [Foo(), Foo()]) + # must pass at least one expression + self.assertRaises(AttributeError, OneOf) + + # iter + self.assertSetEqual(set(iter(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename)))), + {Predicate(ns.bse.filesize), Predicate(ns.bse.filename)}) + # contains + self.assertIn(Predicate(ns.bse.filesize), + OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename))) + self.assertNotIn(Predicate(ns.bse.tag), + OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename))) + # len + self.assertEqual(len(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename))), 2) + self.assertEqual(len(OneOf(Predicate(ns.bse.filesize), Predicate(ns.bse.filename), Predicate(ns.bse.tag))), 3) + + + def testIsIn(self): + # can pass expressions as arguments + self.assertEqual(IsIn('http://example.com/entity#1234', 'http://example.com/entity#4321'), + Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) + # can pass one expression as argument + self.assertEqual(IsIn('http://example.com/entity#1234'), + Or(Is('http://example.com/entity#1234'))) + # can pass expressions as iterator + self.assertEqual(IsIn(iter(('http://example.com/entity#1234', 'http://example.com/entity#4321'))), + Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) + # can pass expressions as generator + def gen(): + yield 'http://example.com/entity#1234' + yield 'http://example.com/entity#4321' + self.assertEqual(IsIn(gen()), + Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) + # can pass expressions as list-like + self.assertEqual(IsIn(['http://example.com/entity#1234', 'http://example.com/entity#4321']), + Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321'))) + # can pass one expression as list-like + self.assertEqual(IsIn(['http://example.com/entity#1234']), + Or(Is('http://example.com/entity#1234'))) + + + def testIsNotIn(self): + # can pass expressions as arguments + self.assertEqual(IsNotIn('http://example.com/entity#1234', 'http://example.com/entity#4321'), + Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) + # can pass one expression as argument + self.assertEqual(IsNotIn('http://example.com/entity#1234'), + Not(Or(Is('http://example.com/entity#1234')))) + # can pass expressions as iterator + self.assertEqual(IsNotIn(iter(('http://example.com/entity#1234', 'http://example.com/entity#4321'))), + Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) + # can pass expressions as generator + def gen(): + yield 'http://example.com/entity#1234' + yield 'http://example.com/entity#4321' + self.assertEqual(IsNotIn(gen()), + Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) + # can pass expressions as list-like + self.assertEqual(IsNotIn(['http://example.com/entity#1234', 'http://example.com/entity#4321']), + Not(Or(Is('http://example.com/entity#1234'), Is('http://example.com/entity#4321')))) + # can pass one expression as list-like + self.assertEqual(IsNotIn(['http://example.com/entity#1234']), + Not(Or(Is('http://example.com/entity#1234')))) + + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## -- cgit v1.2.3 From 6fd984e694b0a7b749ab947211d792f5b011ee6f Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 08:44:25 +0100 Subject: renamed get_child to child in schema.types._Type and _Vertex to Vertex in schema.types --- test/query/test_validator.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'test/query') diff --git a/test/query/test_validator.py b/test/query/test_validator.py index 4f8364a..bf3ceeb 100644 --- a/test/query/test_validator.py +++ b/test/query/test_validator.py @@ -69,8 +69,8 @@ class TestFilter(unittest.TestCase): self.assertRaises(TypeError, self.validate, '1234', None) self.assertRaises(TypeError, self.validate, self.schema.literal(ns.bsfs.URI), None) # root_type must exist in the schema - self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Node).get_child(ns.bsfs.Image), None) - self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Entity).get_child(ns.bsfs.Image), None) + self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Image), None) + self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Entity).child(ns.bsfs.Image), None) # valid query returns true self.assertTrue(self.validate(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ast.filter.OneOf(ns.bse.tag, ns.bse.buddy), @@ -130,7 +130,7 @@ class TestFilter(unittest.TestCase): # type must be a node self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.literal(ns.bsfs.Literal), None) # type must be in the schema - self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node).get_child(ns.bsfs.Invalid), None) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), None) # predicate is verified self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bsfs.Invalid, ast.filter.Is('http://example.com/entity#1234'))) @@ -187,7 +187,7 @@ class TestFilter(unittest.TestCase): self.assertRaises(errors.ConsistencyError, self.validate._has, self.schema.literal(ns.bsfs.Literal), ast.filter.Has(ns.bse.tag)) # type must be in the schema - self.assertRaises(errors.ConsistencyError, self.validate._has, self.schema.node(ns.bsfs.Node).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._has, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), ast.filter.Has(ns.bse.tag)) # has checks predicate self.assertRaises(errors.ConsistencyError, self.validate._has, self.schema.node(ns.bsfs.Entity), @@ -206,7 +206,7 @@ class TestFilter(unittest.TestCase): self.assertRaises(errors.ConsistencyError, self.validate._is, self.schema.literal(ns.bsfs.Literal), ast.filter.Is('http://example.com/foo')) # type must be in the schema - self.assertRaises(errors.ConsistencyError, self.validate._is, self.schema.node(ns.bsfs.Node).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._is, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), ast.filter.Is('http://example.com/foo')) # is accepts correct expressions self.assertIsNone(self.validate._is(self.schema.node(ns.bsfs.Entity), ast.filter.Is('http://example.com/entity#1234'))) @@ -222,13 +222,13 @@ class TestFilter(unittest.TestCase): self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.node(ns.bsfs.Node), ast.filter.EndsWith('hello world')) # type must be in the schema - self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).child(ns.bsfs.Invalid), ast.filter.Equals('hello world')) - self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).child(ns.bsfs.Invalid), ast.filter.Substring('hello world')) - self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).child(ns.bsfs.Invalid), ast.filter.StartsWith('hello world')) - self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.literal(ns.bsfs.Literal).child(ns.bsfs.Invalid), ast.filter.EndsWith('hello world')) # value accepts correct expressions self.assertIsNone(self.validate._value(self.schema.literal(ns.xsd.string), ast.filter.Equals('hello world'))) @@ -243,9 +243,9 @@ class TestFilter(unittest.TestCase): self.assertRaises(errors.ConsistencyError, self.validate._bounded, self.schema.node(ns.bsfs.Node), ast.filter.LessThan(0)) # type must be in the schema - self.assertRaises(errors.ConsistencyError, self.validate._bounded, self.schema.literal(ns.bsfs.Literal).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._bounded, self.schema.literal(ns.bsfs.Literal).child(ns.bsfs.Invalid), ast.filter.GreaterThan(0)) - self.assertRaises(errors.ConsistencyError, self.validate._bounded, self.schema.literal(ns.bsfs.Literal).get_child(ns.bsfs.Invalid), + self.assertRaises(errors.ConsistencyError, self.validate._bounded, self.schema.literal(ns.bsfs.Literal).child(ns.bsfs.Invalid), ast.filter.LessThan(0)) # bounded accepts correct expressions self.assertIsNone(self.validate._bounded(self.schema.literal(ns.xsd.integer), ast.filter.LessThan(0))) -- cgit v1.2.3 From 6b3e32b29799a8143e8ce9d20c5f27e3e166b9bb Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 10:17:07 +0100 Subject: changed path to from_string in clients --- test/query/test_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/query') diff --git a/test/query/test_validator.py b/test/query/test_validator.py index bf3ceeb..405872c 100644 --- a/test/query/test_validator.py +++ b/test/query/test_validator.py @@ -21,7 +21,7 @@ from bsfs.query.validator import Filter class TestFilter(unittest.TestCase): def setUp(self): - self.schema = _schema.Schema.from_string(''' + self.schema = _schema.from_string(''' prefix rdfs: prefix xsd: -- cgit v1.2.3 From b0ff4ed674ad78bf113c3cc0c2ccd187ccb91048 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 10:26:30 +0100 Subject: number literal adaptions --- test/query/test_validator.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'test/query') diff --git a/test/query/test_validator.py b/test/query/test_validator.py index 405872c..ea56a57 100644 --- a/test/query/test_validator.py +++ b/test/query/test_validator.py @@ -33,7 +33,8 @@ class TestFilter(unittest.TestCase): bsfs:Tag rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Literal . + bsfs:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsfs:Number . bse:comment rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Node ; @@ -247,6 +248,9 @@ class TestFilter(unittest.TestCase): ast.filter.GreaterThan(0)) self.assertRaises(errors.ConsistencyError, self.validate._bounded, self.schema.literal(ns.bsfs.Literal).child(ns.bsfs.Invalid), ast.filter.LessThan(0)) + # type must be a number + self.assertRaises(errors.ConsistencyError, self.validate._bounded, self.schema.literal(ns.xsd.string), + ast.filter.LessThan(0)) # bounded accepts correct expressions self.assertIsNone(self.validate._bounded(self.schema.literal(ns.xsd.integer), ast.filter.LessThan(0))) self.assertIsNone(self.validate._bounded(self.schema.literal(ns.xsd.integer), ast.filter.GreaterThan(0))) -- cgit v1.2.3 From ccaee71e2b6135d3b324fe551c8652940b67aab3 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sun, 15 Jan 2023 20:57:42 +0100 Subject: Feature as Literal instead of Predicate subtype --- test/query/test_validator.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'test/query') diff --git a/test/query/test_validator.py b/test/query/test_validator.py index ea56a57..63ead52 100644 --- a/test/query/test_validator.py +++ b/test/query/test_validator.py @@ -34,6 +34,8 @@ class TestFilter(unittest.TestCase): bsfs:Tag rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . bsfs:Number rdfs:subClassOf bsfs:Literal . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array . xsd:integer rdfs:subClassOf bsfs:Number . bse:comment rdfs:subClassOf bsfs:Predicate ; -- cgit v1.2.3 From 80a97bfa9f22d0d6dd25928fe1754a3a0d1de78a Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sun, 15 Jan 2023 21:00:12 +0100 Subject: Distance filter ast node --- test/query/ast_test/test_filter_.py | 35 ++++++++++++++++++++++++++++++++++- test/query/test_validator.py | 27 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) (limited to 'test/query') diff --git a/test/query/ast_test/test_filter_.py b/test/query/ast_test/test_filter_.py index 4f69bdc..9eb92e2 100644 --- a/test/query/ast_test/test_filter_.py +++ b/test/query/ast_test/test_filter_.py @@ -15,7 +15,7 @@ from bsfs.utils import URI from bsfs.query.ast.filter_ import _Expression, FilterExpression, PredicateExpression from bsfs.query.ast.filter_ import _Branch, Any, All from bsfs.query.ast.filter_ import _Agg, And, Or -from bsfs.query.ast.filter_ import Not, Has +from bsfs.query.ast.filter_ import Not, Has, Distance from bsfs.query.ast.filter_ import _Value, Is, Equals, Substring, StartsWith, EndsWith from bsfs.query.ast.filter_ import _Bounded, LessThan, GreaterThan from bsfs.query.ast.filter_ import Predicate, OneOf @@ -284,6 +284,39 @@ class TestValue(unittest.TestCase): self.assertEqual(cls(f).value, f) +class TestDistance(unittest.TestCase): + def test_essentials(self): + ref = (1,2,3) + # comparison + self.assertEqual(Distance(ref, 3), Distance(ref, 3)) + self.assertEqual(hash(Distance(ref, 3)), hash(Distance(ref, 3))) + # comparison respects type + self.assertNotEqual(Distance(ref, 3), FilterExpression()) + self.assertNotEqual(hash(Distance(ref, 3)), hash(FilterExpression())) + # comparison respects reference + self.assertNotEqual(Distance((1,2,3), 3, False), Distance((1,2), 3, False)) + self.assertNotEqual(hash(Distance((1,2,3), 3, False)), hash(Distance((1,2), 3, False))) + self.assertNotEqual(Distance((1,2,3), 3, False), Distance((1,5,3), 3, False)) + self.assertNotEqual(hash(Distance((1,2,3), 3, False)), hash(Distance((1,5,3), 3, False))) + # comparison respects threshold + self.assertNotEqual(Distance((1,2,3), 3, False), Distance((1,2,3), 3.1, False)) + self.assertNotEqual(hash(Distance((1,2,3), 3, False)), hash(Distance((1,2,3), 3.1, False))) + # comparison respects strict flag + self.assertNotEqual(Distance((1,2,3), 3, False), Distance((1,2,3), 3, True)) + self.assertNotEqual(hash(Distance((1,2,3), 3, False)), hash(Distance((1,2,3), 3, True))) + # string conversion + self.assertEqual(str(Distance(ref, 3, False)), 'Distance((1, 2, 3), 3.0, False)') + self.assertEqual(repr(Distance(ref, 3, False)), 'Distance((1, 2, 3), 3.0, False)') + + def test_members(self): + self.assertEqual(Distance((1,2,3), 3, False).reference, (1,2,3)) + self.assertEqual(Distance((3,2,1), 3, False).reference, (3,2,1)) + self.assertEqual(Distance((1,2,3), 3, False).threshold, 3.0) + self.assertEqual(Distance((1,2,3), 53.45, False).threshold, 53.45) + self.assertEqual(Distance((1,2,3), 3, False).strict, False) + self.assertEqual(Distance((1,2,3), 3, True).strict, True) + + class TestBounded(unittest.TestCase): def test_essentials(self): # comparison respects type diff --git a/test/query/test_validator.py b/test/query/test_validator.py index 63ead52..dc9d913 100644 --- a/test/query/test_validator.py +++ b/test/query/test_validator.py @@ -38,6 +38,15 @@ class TestFilter(unittest.TestCase): bsfs:Feature rdfs:subClassOf bsfs:Array . xsd:integer rdfs:subClassOf bsfs:Number . + bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:dimension "5"^^xsd:integer ; + bsfs:dtype bsfs:f32 . + + bse:color rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:Colors ; + bsfs:unique "true"^^xsd:boolean . + bse:comment rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Node ; rdfs:range xsd:string ; @@ -88,6 +97,7 @@ class TestFilter(unittest.TestCase): ), ast.filter.Not(ast.filter.Any(ns.bse.comment, ast.filter.Not(ast.filter.Equals('hello world')))), + ast.filter.Any(ns.bse.color, ast.filter.Distance([1,2,3,4,5], 3)), ))))) # invalid paths raise consistency error self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Entity), @@ -257,6 +267,23 @@ class TestFilter(unittest.TestCase): self.assertIsNone(self.validate._bounded(self.schema.literal(ns.xsd.integer), ast.filter.LessThan(0))) self.assertIsNone(self.validate._bounded(self.schema.literal(ns.xsd.integer), ast.filter.GreaterThan(0))) + def test_distance(self): + # type must be a literal + self.assertRaises(errors.ConsistencyError, self.validate._distance, self.schema.node(ns.bsfs.Node), + ast.filter.Distance([1,2,3], 1, False)) + # type must be a feature + self.assertRaises(errors.ConsistencyError, self.validate._distance, self.schema.literal(ns.bsfs.Array), + ast.filter.Distance([1,2,3], 1, False)) + # type must be in the schema + self.assertRaises(errors.ConsistencyError, self.validate._distance, self.schema.literal(ns.bsfs.Feature).child(ns.bsfs.Invalid), + ast.filter.Distance([1,2,3], 1, False)) + # FIXME: reference must be a numpy array + # reference must have the correct dimension + self.assertRaises(errors.ConsistencyError, self.validate._distance, self.schema.literal(ns.bsfs.Colors), + ast.filter.Distance([1,2,3], 1, False)) + # FIXME: reference must have the correct dtype + # distance accepts correct expressions + self.assertIsNone(self.validate._distance(self.schema.literal(ns.bsfs.Colors), ast.filter.Distance([1,2,3,4,5], 1, False))) ## main ## -- cgit v1.2.3