def test_filter(self): query1 = Query(['col1']) query2 = query1.filter(lambda x: x == 'a') self.assertIsNot(query1, query2, 'should return new object') source = Selector([('col1', 'col2'), ('a', '2'), ('b', '2')]) result = query2.execute(source) self.assertEqual(result.fetch(), ['a']) # No filter arg should default to bool() source = Selector([('col1', ), (1, ), (2, ), (0, ), (3, )]) query = Query(set(['col1'])).filter() # <- No arg! result = query.execute(source) self.assertEqual(result.fetch(), set([1, 2, 3]))
def test_execute_query(self): data = [['A', 'B'], ['x', 101], ['y', 202], ['z', 303]] source = Selector(data) # Test where-clause function. def isodd(x): return x % 2 == 1 result = source('A', B=isodd).fetch() self.assertEqual(result, ['x', 'z']) # Test replacing function. def iseven(x): return x % 2 == 0 result = source('A', B=iseven).fetch() self.assertEqual(result, ['y']) # Test callable-but-unhashable. class IsEven(object): __hash__ = None def __call__(self, x): return x % 2 == 0 unhashable_iseven = IsEven() result = source('A', B=unhashable_iseven).fetch() self.assertEqual(result, ['y'])
def test__copy__(self): # Select-arg only. query = Query(['B']) copied = query.__copy__() self.assertIs(copied.source, query.source) self.assertEqual(copied.args, query.args) self.assertEqual(copied.kwds, query.kwds) self.assertEqual(copied._query_steps, query._query_steps) self.assertIsNot(copied.kwds, query.kwds) self.assertIsNot(copied._query_steps, query._query_steps) # Select and keyword. query = Query(['B'], C='x') copied = query.__copy__() self.assertIs(copied.source, query.source) self.assertEqual(copied.args, query.args) self.assertEqual(copied.kwds, query.kwds) self.assertEqual(copied._query_steps, query._query_steps) # Source, columns, and keyword. source = Selector([('A', 'B'), (1, 2), (1, 2)]) query = Query(source, ['B']) copied = query.__copy__() self.assertIs(copied.source, query.source) self.assertEqual(copied.args, query.args) self.assertEqual(copied.kwds, query.kwds) self.assertEqual(copied._query_steps, query._query_steps) # Select and additional query methods. query = Query(['B']).map(lambda x: str(x).upper()) copied = query.__copy__() self.assertIs(copied.source, query.source) self.assertEqual(copied.args, query.args) self.assertEqual(copied.kwds, query.kwds) self.assertEqual(copied._query_steps, query._query_steps)
def test_map(self): query1 = Query(['col2']) query2 = query1.map(int) self.assertIsNot(query1, query2, 'should return new object') source = Selector([('col1', 'col2'), ('a', '2'), ('b', '2')]) result = query2.execute(source) self.assertEqual(result.fetch(), [2, 2])
def test_reduce(self): query1 = Query(['col1']) query2 = query1.reduce(lambda x, y: x + y) self.assertIsNot(query1, query2, 'should return new object') source = Selector([('col1', 'col2'), ('a', '2'), ('b', '2')]) result = query2.execute(source) self.assertEqual(result, 'ab')
def test_fetch_datasource(self): select = Selector([('A', 'B'), ('1', '2'), ('1', '2')]) query = Query(select, ['B']) query._query_steps = [ ('map', (int, ), {}), ('map', (lambda x: x * 2, ), {}), ('sum', (), {}), ] result = query.fetch() self.assertEqual(result, 8)
def test_init_with_selector(self): source = Selector([('A', 'B'), (1, 2), (1, 2)]) query = Query(source, ['A'], B=2) self.assertEqual(query.source, source) self.assertEqual(query.args, (['A'], )) self.assertEqual(query.kwds, {'B': 2}) self.assertEqual(query._query_steps, []) with self.assertRaises(TypeError): query = Query(None, ['foo'], bar='baz')
def test_load_data(self): select = Selector() # <- Empty selector. self.assertEqual(select.fieldnames, []) readerlike1 = [['col1', 'col2'], ['a', 1], ['b', 2]] select.load_data(readerlike1) self.assertEqual(select.fieldnames, ['col1', 'col2']) readerlike2 = [['col1', 'col3'], ['c', 'x'], ['d', 'y']] select.load_data(readerlike2) self.assertEqual(select.fieldnames, ['col1', 'col2', 'col3'])
def test_repr(self): data = [['A', 'B'], ['x', 100], ['y', 200]] # Empty selector. select = Selector() regex = ('^<datatest.Selector object at [^\n>]+>\n' 'Empty - contains no data\.$') self.assertRegex(repr(select), regex) # Data-only (no args) source = Selector(data) regex = ("^<datatest.Selector object at [^\n>]+>\n" "Data from 1 source:\n" " {0}$".format(re.escape(repr(data)))) self.assertRegex(repr(source), regex) # Data with args and kwds. iterable = iter(data) source = Selector(iterable, 'foo', bar='baz') # Args don't change repr. regex = ('<datatest.Selector object at [^\n>]+>\n' 'Data from 1 source:\n' ' <[a-z_]+ object at [^\n>]+>') self.assertRegex(repr(source), regex) # Extended after instantiation. data1 = [['A', 'B'], ['x', 100]] data2 = [['A', 'B'], ['y', 200]] data3 = [['A', 'B'], ['z', 300]] source = Selector(data1) source.load_data(data2) source.load_data(data3) actual_repr = repr(source) self.assertTrue(actual_repr.startswith('<datatest.Selector object at')) self.assertTrue( actual_repr.endswith(">\n" "Data from 3 sources:\n" " [['A', 'B'], ['x', 100]]\n" " [['A', 'B'], ['y', 200]]\n" " [['A', 'B'], ['z', 300]]"))
def test_repr(self): data = [['A', 'B'], ['x', 100], ['y', 200]] # Empty selector. select = Selector() self.assertEqual(repr(select), '<Selector (no data loaded)>') # Data-only (no args) select = Selector(data) expected = "<Selector [['A', 'B'], ['x', 100], ['y', 200]]>" self.assertEqual(repr(select), expected) # Data with args (args don't affect repr) iterable = iter(data) select = Selector(iterable, 'foo', bar='baz') regex = '<Selector <[a-z_]+ object at [^\n>]+>>' self.assertRegex(repr(select), regex) # Extended after instantiation. select = Selector() select.load_data([['A', 'B'], ['z', 300]]) select.load_data([['A', 'B'], ['y', 200]]) select.load_data([['A', 'B'], ['x', 100]]) expected = ("<Selector (3 sources):\n" " [['A', 'B'], ['x', 100]]\n" " [['A', 'B'], ['y', 200]]\n" " [['A', 'B'], ['z', 300]]>") self.assertEqual(repr(select), expected) # Test long repr truncation. select = Selector([ ['xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'], ['yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'], ]) self.assertEqual(len(repr(select)), 72) expected = "<Selector [['xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'], ['yyyyyyyyyyy...yyyyy']]>" self.assertEqual(repr(select), expected)
def test_init_with_invalid_args(self): # Missing args. with self.assertRaises(TypeError, msg='should require select args'): Query() # Bad "select" field. source = Selector([('A', 'B'), (1, 2), (1, 2)]) with self.assertRaises( LookupError, msg= 'should fail immediately when fieldname conflicts with provided source' ): query = Query(source, ['X'], B=2) # Bad "where" field. source = Selector([('A', 'B'), (1, 2), (1, 2)]) with self.assertRaises( LookupError, msg= 'should fail immediately when fieldname conflicts with provided "where" field' ): query = Query(source, ['A'], Y=2)
def test_execute_datasource(self): select = Selector([('A', 'B'), ('1', '2'), ('1', '2')]) query = Query(select, ['B']) query._query_steps = [ ('map', (int, ), {}), ('map', (lambda x: x * 2, ), {}), ('sum', (), {}), ] result = query.execute() self.assertEqual(result, 8) query = Query(['A']) regex = "expected 'Selector', got 'list'" with self.assertRaisesRegex(TypeError, regex): query.execute(['hello', 'world']) # <- Expects None or Query, not list!
def test_repr(self): # Check "no selector" signature. query = Query(['label1']) regex = r"Query\(\[u?'label1'\]\)" self.assertRegex(repr(query), regex) # Check "no selector" with keyword string. query = Query(['label1'], label2='x') regex = r"Query\(\[u?'label1'\], label2='x'\)" self.assertRegex(repr(query), regex) # Check "no selector" with keyword list. query = Query(['label1'], label2=['x', 'y']) regex = r"Query\(\[u?'label1'\], label2=\[u?'x', u?'y'\]\)" self.assertRegex(repr(query), regex) # Check "selector-provided" signature. select = Selector([('A', 'B'), ('x', 1), ('y', 2), ('z', 3)]) query = Query(select, ['B']) short_repr = super(Selector, select).__repr__() expected = "Query({0}, {1!r})".format(short_repr, ['B']) #print(repr(query)) self.assertEqual(repr(query), expected) # Check "from_object" signature. query = Query.from_object([1, 2, 3]) expected = "Query.from_object([1, 2, 3])" self.assertEqual(repr(query), expected) # Check query steps. query = Query(['label1']).distinct().count() regex = r"Query\(\[u?'label1'\]\).distinct\(\).count\(\)" self.assertRegex(repr(query), regex) # Check query steps with function argument. def upper(x): return str(x.upper()) query = Query(['label1']).map(upper) regex = r"Query\(\[u?'label1'\]\).map\(upper\)" self.assertRegex(repr(query), regex) # Check query steps with lambda argument. lower = lambda x: str(x).lower() query = Query(['label1']).map(lower) regex = r"Query\(\[u?'label1'\]\).map\(<lambda>\)" self.assertRegex(repr(query), regex)
def test_query_objects(self): source = Selector([('A', 'B'), ('1', '2'), ('1', '2')]) query_obj1 = source(['B']) query_obj2 = source(['B']) self.assertValid(query_obj1, query_obj2)
def test_empty_selector(self): select = Selector()
def test_fieldnames(self): expected = ['label1', 'label2', 'value'] self.assertEqual(self.source.fieldnames, expected) select = Selector() # <- Empty selector. self.assertEqual(select.fieldnames, [], msg='should be empty list')
def test_Query(self): source = Selector([('A', 'B'), ('x', 1), ('y', 2)]) query = source({'A': 'B'}).apply(lambda x: next(x)) normalized = DictItems(query) self.assertEqual(list(normalized), [('x', 1), ('y', 2)])
def setUp(self): data = [['label1', 'label2', 'value'], ['a', 'x', '17'], ['a', 'x', '13'], ['a', 'y', '20'], ['a', 'z', '15'], ['b', 'z', '5'], ['b', 'y', '40'], ['b', 'x', '25']] self.source = Selector(data)