def test_copy(self): qlObjs = QueryableListObjs(self.dataObjs) assert copy.copy( qlObjs) == qlObjs, "Expected copy to equal the original" assert id(copy.copy(qlObjs)) != id( qlObjs), 'Expected id of copy to not euqla original' assert copy.deepcopy( qlObjs) != qlObjs, "Expected deepcopy to NOT equal the original" assert copy.deepcopy(qlObjs).count() == qlObjs.count( ), 'Expected deepcopy to have same number of items' aObjs = qlObjs.filter(a='one') assert copy.copy( aObjs ) == aObjs, 'After filter, expected copy to equal filtered original' assert id(copy.copy(aObjs)) != id( aObjs ), 'After filter, expected id of copy to not equal id of filtered original' assert copy.deepcopy( aObjs ) != aObjs, 'After filter, expected deepcopy to NOT equal filtered original' assert copy.deepcopy(aObjs).count() == aObjs.count( ), 'Expected deepcopy to have same number of items'
def test_sub(self): testHasItems = self._testHasItems set1Nums = [0, 1, 5, 1, 3] set2Nums = [3, 1] set3Nums = [0, 5] qObjs1 = QueryableListObjs(gdo(self, set1Nums)) qObjs2 = QueryableListObjs(gdo(self, set2Nums)) subRes = qObjs1 - qObjs2 # Assert sub removes items in 2 from 1 testHasItems(subRes, gdo(self, set3Nums), mkOpStr('o', set1Nums, '-', set2Nums, set3Nums)) # Assert originals are unchanged testHasItems(qObjs1, gdo(self, set1Nums), mkNumSet('o', set1Nums)) testHasItems(qObjs2, gdo(self, set2Nums), mkNumSet('o', set2Nums)) qDicts1 = QueryableListDicts(gdd(self, set1Nums)) qDicts2 = QueryableListDicts(gdd(self, set2Nums)) subRes = qDicts1 - qDicts2 # Assert sub removes items in 2 from 1 testHasItems(subRes, gdd(self, set3Nums), mkOpStr('d', set1Nums, '-', set2Nums, set3Nums)) # Assert originals are unchanged testHasItems(qDicts1, gdd(self, set1Nums), mkNumSet('d', set1Nums)) testHasItems(qDicts2, gdd(self, set2Nums), mkNumSet('d', set2Nums))
def test_add(self): testHasItems = self._testHasItems set1Nums = [0, 1] set2Nums = [3, 5] set3Nums = [0, 1, 3, 5] qObjs1 = QueryableListObjs(gdo(self, set1Nums)) qObjs2 = QueryableListObjs(gdo(self, set2Nums)) addRes = qObjs1 + qObjs2 # Assert add appends 2 to 1 testHasItems(addRes, gdo(self, set3Nums), mkOpStr('o', set1Nums, '+', set2Nums, set3Nums)) # Assert originals are unchanged testHasItems(qObjs1, gdo(self, set1Nums)) testHasItems(qObjs2, gdo(self, set2Nums)) qDicts1 = QueryableListDicts(gdd(self, set1Nums)) qDicts2 = QueryableListDicts(gdd(self, set2Nums)) addRes = qDicts1 + qDicts2 # Assert add appends 2 to 1 testHasItems(addRes, gdd(self, set3Nums), mkOpStr('d', set1Nums, '+', set2Nums, set3Nums)) # Assert originals are unchanged testHasItems(qDicts1, gdd(self, set1Nums), mkNumSet('d', set1Nums)) testHasItems(qDicts2, gdd(self, set2Nums), mkNumSet('d', set2Nums))
def __init__(self, val=None, mdl=None): ''' __init__ - Create this object @param val - None for empty list, IndexedRedisModel for a one-item list, or a list/tuple or subclass of initial values. @param mdl - The IndexedRedisModel that this list will contain. Provide this now if you can, otherwise it will be inferred from the first item added or present in the list. @raises ValueError if "mdl" is not an IndexedRedisModel ''' if val is None: QueryableListObjs.__init__(self) else: QueryableListObjs.__init__(self, val) self.mdl = mdl if not mdl: # If not explicitly defined, try to infer model if objects were provided. # otherwise, inference will be attempted when an operation that requires it is performed. self.mdl = self.getModel() else: # This is called in getModel() if we did infer, so no need to call twice. self.__validate_model(mdl)
def test_performance(self): # Test __eq and = both qlObjs = QueryableListObjs(self.dataObjs) qlDicts = QueryableListDicts(self.dataDicts) start = time.time() for i in range(1, NUMI + 1, 1): filterA = 'x' * ((i * 7) % 5) filterA2 = 'x' * ((i * 13) % 5) filterB = 'y' * ((i * 11) % 5) filterB2 = 'y' * ((i * 3) % 5) filterNums1 = [(i * 100) % 5, (i * 33) % 5, (i * 121) % 5] filterNums2 = [(i * 177) % 5, (i * 62) % 5, (i * 101) % 5] res = qlObjs.filter( a=filterA, a__ne=filterB, b__in=[filterB[:min(len(filterB) - 1, 1)], filterB]).filterOr(num__gt=filterNums1[i % 3], num__ne=filterNums2[i % 3]) end = time.time() print("Total time: %f" % (end - start, ))
def test_Dicts(self): gotException = False try: qlDicts = QueryableListDicts(self.dataDicts) found = qlDicts.filter(a='one') except Exception as e: gotException = e assert gotException is False, 'Got Exception for QueryableListDicts when should not have: %s%s' % ( str(type(e)), str(e)) assert len(found) == 2, 'Did not find correct number of items' gotException = False try: dDicts = QueryableListObjs(self.dataDicts) found = dDicts.filter(a='one') except Exception as e: # I personally think this should raise an exception, so test is written like this, # but it would be too performant loss to check every time. gotException = e #assert gotException is not False, 'Expected to get exception, but did not.' assert len( found ) == 0, 'Expected not to find any items when using QueryableListDicts with list of objs'
def test_isub(self): testHasItems = self._testHasItems set1Nums = [0, 1, 5, 1, 3] # A set2Nums = [3, 1] # B set3Nums = [0, 5] # = C qObjs1 = QueryableListObjs(gdo(self, [0, 1, 5, 1, 3])) qObjs2 = QueryableListObjs(gdo(self, [3, 1])) origRef1 = qObjs1 origID1 = id(qObjs1) qObjs1 -= qObjs2 # Assert sub removes items from 1 that are in 2 testHasItems(qObjs1, gdo(self, set3Nums), mkOpStr('o', set1Nums, '-', set2Nums, set3Nums)) # Assert original1 is modified, 2 is not testHasItems(qObjs1, gdo(self, set3Nums), 'o1 = ' + mkNumSet('o', set3Nums)) testHasItems(qObjs2, gdo(self, set2Nums), 'o2 = ' + mkNumSet('o', set2Nums)) afterID1 = id(qObjs1) assert origID1 == afterID1, 'Expected id to not change after iadd (i.e. a copy was not made.)\nBefore = %d\nAfter = %d' % ( origID1, afterID1) testHasItems(origRef1, gdo(self, set3Nums), 'o1ref = ' + mkNumSet('o', set3Nums)) qDicts1 = QueryableListDicts(gdd(self, set1Nums)) qDicts2 = QueryableListDicts(gdd(self, set2Nums)) origRef1 = qDicts1 origID1 = id(qDicts1) qDicts1 -= qDicts2 # Assert sub removes items from 1 that are in 2 testHasItems(qDicts1, gdd(self, set3Nums), mkOpStr('d', set1Nums, '-=', set2Nums)) # Assert original1 is modified, 2 is not testHasItems(qDicts1, gdd(self, set3Nums), 'd1 = ' + mkNumSet('d', set3Nums)) testHasItems(qDicts2, gdd(self, set2Nums), 'd1 = ' + mkNumSet('d', set2Nums)) afterID1 = id(qDicts1) assert origID1 == afterID1, 'Expected id to not change after iadd (i.e. a copy was not made.)\nBefore = %d\nAfter = %d' % ( origID1, afterID1) testHasItems(origRef1, gdd(self, set3Nums), 'd1ref = ' + mkNumSet('d', set3Nums))
def test_ne(self): qlObjs = QueryableListObjs(self.dataObjs) found = qlObjs.filter(a__ne='one') assert len( found) == 1, 'Expected to find one item in query, found %d' % ( len(found), ) assert found[0].a == 'six' and found[ 0].c == 'eleven', 'Found wrong item from equals query'
def test_chaining(self): qlObjs = QueryableListObjs(self.dataObjs) found = qlObjs.filter(a__eq='one').filter(b__eq='two') assert len( found ) == 1, 'Expected chained filter to return one element, got %d' % ( len(found), ) assert found[0].a == 'one' and found[ 0].b == 'two', 'Got wrong item in chained query'
def test_iadd(self): testHasItems = self._testHasItems set1Nums = [0, 1] set2Nums = [3, 5] set3Nums = [0, 1, 3, 5] qObjs1 = QueryableListObjs(gdo(self, set1Nums)) qObjs2 = QueryableListObjs(gdo(self, set2Nums)) origRef1 = qObjs1 origID1 = id(qObjs1) qObjs1 += qObjs2 # Assert add appends 2 to 1 testHasItems(qObjs1, gdo(self, set3Nums), mkOpStr('o', set1Nums, '+=', set2Nums)) # Assert original1 is modified, 2 is not testHasItems(qObjs1, gdo(self, set3Nums), mkNumSet('o', set3Nums)) testHasItems(qObjs2, gdo(self, set2Nums), mkNumSet('o', set2Nums)) afterID1 = id(qObjs1) assert origID1 == afterID1, 'Expected id to not change after iadd (i.e. a copy was not made.)\nBefore = %d\nAfter = %d' % ( origID1, afterID1) testHasItems(origRef1, gdo(self, set3Nums), mkNumSet('o', set3Nums)) qDicts1 = QueryableListDicts(gdd(self, set1Nums)) qDicts2 = QueryableListDicts(gdd(self, set2Nums)) origRef1 = qDicts1 origID1 = id(qDicts1) qDicts1 += qDicts2 # Assert add appends 2 to 1 testHasItems(qDicts1, gdd(self, set3Nums), mkOpStr('d', set1Nums, '+', set2Nums, set3Nums)) # Assert original1 is modified, 2 is not testHasItems(qDicts1, gdd(self, set3Nums), mkNumSet('d', set3Nums)) testHasItems(qDicts2, gdd(self, set2Nums), mkNumSet('d', set2Nums)) afterID1 = id(qDicts1) assert origID1 == afterID1, 'Expected id to not change after iadd (i.e. a copy was not made.)\nBefore = %d\nAfter = %d' % ( origID1, afterID1) testHasItems(origRef1, gdd(self, set3Nums), mkNumSet('d', set3Nums))
def test_filterOr(self): qlObjs = QueryableListObjs(self.dataObjs) found = qlObjs.filterOr(a='six', b='five') assert len( found ) == 2, 'Expected "or" filter to return 2 items for a="6" and b="five". Got: %s\n' % ( str(found), ) assert ( (found[0].a == 'six' or found[0].b == 'five') or (found[1].a == 'six' or found[1].b == 'five') ), 'Got wrong items for a="6" and b="five". Got: %s' % (str(found), )
def test_equals(self): # Test __eq and = both qlObjs = QueryableListObjs(self.dataObjs) found = qlObjs.filter(a='six') assert len( found) == 1, 'Expected to find one item in query(=), found %d' % ( len(found), ) assert found[0].a == 'six' and found[ 0].c == 'eleven', 'Found wrong item from equals query' found = qlObjs.filter(a__eq='six') assert len( found ) == 1, 'Expected to find one item in query(__eq), found %d' % ( len(found), ) assert found[0].a == 'six' and found[ 0].c == 'eleven', 'Found wrong item from equals query' found = QueryableListObjs(self.dataObjs).filter(a__eq='one') assert len( found) == 2, 'Expected to find two items in query, found %d' % ( len(found), ) assert found.count( ) == 2, 'Expected count() to return 2 elements. Got: %d' % ( found.count(), )
def test_customMatch(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'q__customMatch': lambda q: q and len(q) > 5}, (dataObjs[0], dataObjs[1]))
def test_all(self): qlObjs = QueryableListObjs(self.dataObjs) qlObjsAll = qlObjs.all() assert qlObjsAll == qlObjs, 'Expected .all() to equal original' assert id(qlObjsAll) != id( qlObjs), 'Expected id of .all() to not equal id of original' aObjs = qlObjs.filter(a='one') aObjsAll = aObjs.all() assert aObjs == aObjsAll, 'After filter, Expected .all() to equal filtered original' assert id(aObjs) != id( aObjsAll ), 'After filter, expected id of .all() NOT to equal id of filtered original'
def test_ne(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'a__ne': 'one'}, (dataObjs[2], )) doTest(qlObjs, 'OR', { 'b__ne': 'two', 'num__ne': -5 }, (dataObjs[0], dataObjs[1], dataObjs[2]))
def text_mixed(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'a__eq': 'six', 'num__ne': 7}, tuple()) doTest(qlObjs, 'AND', { 'a__eq': 'one', 'num__ne': 7 }, tuple(dataObjs[1]))
def test_eq(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'a__eq': 'one'}, (dataObjs[0], dataObjs[1])) doTest(qlObjs, 'OR', { 'b__eq': 'five', 'num__eq': 7 }, (dataObjs[0], dataObjs[1], dataObjs[2])) doTest(qlObjs, 'AND', {'a__eq': 'nine'}, tuple())
def test_sortObjsByInt(self): dataObjs = self.dataObjs qlObjs = QueryableListObjs(self.dataObjs) sortedByA = qlObjs.sort_by('a') sortedByAList = list(sortedByA) expectedList = [dataObjs[0], dataObjs[3], dataObjs[2], dataObjs[1]] assert sortedByAList == expectedList, 'Sort by field "a" failed to return expected order.\nGot: %s\nExpected: %s\n' % ( repr(self._get_list_of_values(sortedByAList, 'a')), repr(self._get_list_of_values(expectedList, 'a'))) assert dataObjs == self.dataObjsCopy, 'Expected sort_by to not modify original list' assert isinstance( sortedByA, QueryableListObjs ), 'Expected return to be a QueryableListObjs instance. Got: %s' % ( sortedByA.__class__.__name__, ) sortedByARev = qlObjs.sort_by('a', reverse=True) sortedByARevList = list(sortedByARev) expectedRevList = list(reversed(expectedList)) assert sortedByARevList == expectedRevList, 'Reverse sort by field "a" failed to return expected order.\nGot: %s\nExpected: %s\n' % ( repr(self._get_list_of_values(sortedByARevList, 'a')), repr(self._get_list_of_values(expectedRevList, 'a'))) assert dataObjs == self.dataObjsCopy, 'Expected sort_by to not modify original list' assert isinstance( sortedByARev, QueryableListObjs ), 'Expected return to be a QueryableListObjs instance. Got: %s' % ( sortedByARev.__class__.__name__, )
def test_gt(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'num__gt': 8}, tuple()) doTest(qlObjs, 'OR', { 'num__gt': 0, }, (dataObjs[0], dataObjs[2])) doTest(qlObjs, 'AND', {'num__gt': 7}, tuple()) doTest(qlObjs, 'AND', {'num__gt': -5}, (dataObjs[0], dataObjs[2])) doTest(qlObjs, 'AND', {'num__gt': -6}, (dataObjs[0], dataObjs[1], dataObjs[2]))
def test_Dicts(self): gotException = False try: qlDicts = QueryableListDicts(self.dataDicts) found = qlDicts.filter(a='one') except Exception as e: gotException = e assert gotException is False, 'Got Exception for QueryableListDicts when should not have: %s%s' %(str(type(e)), str(e)) assert len(found) == 2, 'Did not find correct number of items' gotException = False try: dDicts = QueryableListObjs(self.dataDicts) found = dDicts.filter(a='one') except Exception as e: # I personally think this should raise an exception, so test is written like this, # but it would be too performant loss to check every time. gotException = e #assert gotException is not False, 'Expected to get exception, but did not.' assert len(found) == 0, 'Expected not to find any items when using QueryableListDicts with list of objs'
def test_lt(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'num__lt': 8}, ( dataObjs[0], dataObjs[1], dataObjs[2], )) doTest(qlObjs, 'OR', { 'num__lt': 0, }, (dataObjs[1], )) doTest(qlObjs, 'AND', {'num__lt': 7}, (dataObjs[1], ))
def test_customFilter(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) matchFunc = lambda item: getattr(item, 'b', None) and item.num > 0 results = qlObjs.customFilter(matchFunc) assert len(results) == 1, 'Expected to get one result, got %d' % ( len(results), ) assert results[0] == dataObjs[0] matchFunc = lambda item: item.a.upper() == 'ONE' results = qlObjs.customFilter(matchFunc) assert len(results) == 2, 'Expected to get two results, got %d' % ( len(results), ) assert dataObjs[0] in results, 'Expected dataObjs[0] to be in match' assert dataObjs[1] in results, 'Expected dataObjs[1] to be in match'
def test_ne(self): dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'a__ne': 'six'}, (dataObjs[0], dataObjs[1])) doTest(qlObjs, 'AND', {'a__ne': 'five'}, (dataObjs[0], dataObjs[1], dataObjs[2])) doTest(qlObjs, 'AND', {'num__ne': -5, 'a__ne': 'one'}, (dataObjs[2], )) doTest(qlObjs, 'AND', {'num__ne': -5, 'a__ne': 'six'}, (dataObjs[0], )) doTest(qlObjs, 'OR', { 'a__ne': 'one', 'q__ne': 'cheese' }, (dataObjs[2], )) doTest(qlObjs, 'OR', { 'a__ne': 'six', 'num__ne': -5 }, (dataObjs[0], dataObjs[1], dataObjs[2]))
def test_eq(self): # Test __eq and = both dataObjs = self.dataObjs doTest = self._doTest qlObjs = QueryableListObjs(dataObjs) doTest(qlObjs, 'AND', {'a': 'six'}, (dataObjs[2], )) doTest(qlObjs, 'AND', {'a__eq': 'six'}, (dataObjs[2], )) doTest(qlObjs, 'AND', {'a': 'one'}, (dataObjs[0], dataObjs[1])) doTest(qlObjs, 'AND', { 'a': 'one', 'emptyStr': '' }, (dataObjs[0], dataObjs[1])) doTest(qlObjs, 'AND', { 'a': 'one', 'q': 'cheese' }, (dataObjs[0], dataObjs[1])) doTest(qlObjs, 'AND', { 'emptyStr': '', 'num__eq': 7 }, (dataObjs[0], dataObjs[2])) doTest(qlObjs, 'OR', {'a': 'six'}, (dataObjs[2], )) doTest(qlObjs, 'OR', {'a__eq': 'six'}, (dataObjs[2], )) doTest(qlObjs, 'OR', { 'a': 'one', 'q__eq': 'bacon' }, (dataObjs[0], dataObjs[1], dataObjs[2])) doTest(qlObjs, 'OR', { 'a': 'one', 'emptyStr': '' }, (dataObjs[0], dataObjs[1], dataObjs[2])) doTest(qlObjs, 'OR', { 'a': 'six', 'num__eq': 7 }, (dataObjs[0], dataObjs[2]))
# a mixed dataset of objects and dicts dataset2 = [ SampleDataObj(colour='blue', age=25, name='Tim', likes=['batteries', 'cheese']), SampleDataObj(colour='red', age=55, name='Jack', likes=['puppies', 'milk']), { 'colour' : 'green', 'age' : 88, 'name' : 'John', 'likes' : ['puppies', 'games'] }, { 'colour' : 'orange', 'age' : 18, 'name' : 'Phil', 'likes' : ['puppies', 'gnomes'] }, ] # data = QueryableListDicts(data) data = QueryableListObjs(data) sys.stdout.write("Data: %s\n\n" %(data,)) sys.stdout.write('People who are over 22 years old:\n%s\n\n' %(data.filter(age__gt=22),)) # sys.stdout.write('People who like puppies or bricks, and their favourite colour is purple:\n\n' %(data.filter(likes__containsAny=('puppies', 'bricks')).filter(colour__ieq='purple'),)) sys.stdout.write('People who like puppies or bricks, and their favourite colour is purple:\n%s\n\n' %(data.filter(likes__containsAny=('puppies', 'bricks'), colour__ieq='purple'),)) sys.stdout.write('People who are at least 30 years old or like cheese:\n%s\n\n' %(data.filterOr(likes__contains='cheese', age__gte=30),)) # Create a QueryBuilder to execute a query builder = QueryBuilder() builder.addFilter("AND", age__gt=22) builder.addFilter(likes__contains='puppies')