diff --git a/doc/api/pycassa/contrib/stubs.rst b/doc/api/pycassa/contrib/stubs.rst index 32e1e95e..91c266ac 100644 --- a/doc/api/pycassa/contrib/stubs.rst +++ b/doc/api/pycassa/contrib/stubs.rst @@ -5,9 +5,9 @@ .. autoclass:: pycassa.contrib.stubs.ColumnFamilyStub(pool=None, column_family=None, rows=None) - .. automethod:: get(key[, columns][, column_start][, column_finish][, column_count][, include_timestamp]) + .. automethod:: get(key[, columns][, column_start][, column_finish][, column_reversed][, column_count][, include_timestamp]) - .. automethod:: multiget(keys[, columns][, column_start][, column_finish][, column_count][, include_timestamp]) + .. automethod:: multiget(keys[, columns][, column_start][, column_finish][, column_reversed][, column_count][, include_timestamp]) .. automethod:: get_range([columns][, include_timestamp]) diff --git a/pycassa/contrib/stubs.py b/pycassa/contrib/stubs.py index 4b664b03..fd11d631 100644 --- a/pycassa/contrib/stubs.py +++ b/pycassa/contrib/stubs.py @@ -137,7 +137,7 @@ def __contains__(self, obj): return self.rows.__contains__(obj) def get(self, key, columns=None, column_start=None, column_finish=None, - column_count=100, include_timestamp=False, **kwargs): + column_reversed=False, column_count=100, include_timestamp=False, **kwargs): """Get a value from the column family stub.""" my_columns = self.rows.get(key) @@ -151,17 +151,26 @@ def get(self, key, columns=None, column_start=None, column_finish=None, items = my_columns.items() items.sort() - return OrderedDict([(k, get_value(v)) for (k, v) in items - if self._is_column_in_range(k, columns, column_start, column_finish)][:column_count]) + if column_reversed: + items.reverse() + + sliced_items = [(k, get_value(v)) for (k, v) in items + if self._is_column_in_range(k, columns, + column_start, column_finish, column_reversed)][:column_count] + + return OrderedDict(sliced_items) + + def _is_column_in_range(self, k, columns, column_start, column_finish, column_reversed): + lower_bound = column_start if not column_reversed else column_finish + upper_bound = column_finish if not column_reversed else column_start - def _is_column_in_range(self, k, columns, column_start, column_finish): if columns: return k in columns - return (not column_start or k >= column_start) and (not column_finish or k <= column_finish) + return (not lower_bound or k >= lower_bound) and (not upper_bound or k <= upper_bound) def multiget(self, keys, columns=None, column_start=None, column_finish=None, - column_count=100, include_timestamp=False, **kwargs): + column_reversed=False, column_count=100, include_timestamp=False, **kwargs): """Get multiple key values from the column family stub.""" return OrderedDict( @@ -170,6 +179,7 @@ def multiget(self, keys, columns=None, column_start=None, column_finish=None, columns=columns, column_start=column_start, column_finish=column_finish, + column_reversed=column_reversed, column_count=column_count, include_timestamp=include_timestamp, )) for key in keys if key in self.rows) diff --git a/tests/contrib/stubs.py b/tests/contrib/stubs.py index 64e1183b..c792eb36 100644 --- a/tests/contrib/stubs.py +++ b/tests/contrib/stubs.py @@ -8,6 +8,8 @@ from pycassa.contrib.stubs import ColumnFamilyStub, ConnectionPoolStub, \ SystemManagerStub +from pycassa.util import OrderedDict + pool = cf = None pool_stub = cf_stub = None @@ -66,6 +68,15 @@ def test_insert_get(self): assert_true(isinstance(ts, (int, long))) assert_equal(test_cf.get(key), columns) + def test_insert_get_column_start_and_finish_reversed(self): + key = 'TestColumnFamily.test_insert_get_reversed' + columns = {'1': 'val1', '2': 'val2'} + for test_cf in (cf, cf_stub): + assert_raises(NotFoundException, test_cf.get, key) + ts = test_cf.insert(key, columns) + assert_true(isinstance(ts, (int, long))) + row = test_cf.get(key, column_reversed=True) + def test_insert_get_column_start_and_finish(self): key = 'TestColumnFamily.test_insert_get_column_start_and_finish' columns = {'a': 'val1', 'b': 'val2', 'c': 'val3', 'd': 'val4'} @@ -75,6 +86,15 @@ def test_insert_get_column_start_and_finish(self): assert_true(isinstance(ts, (int, long))) assert_equal(test_cf.get(key, column_start='b', column_finish='c'), {'b': 'val2', 'c': 'val3'}) + def test_insert_get_column_start_and_reversed(self): + key = 'TestColumnFamily.test_insert_get_column_start_and_finish_reversed' + columns = {'a': 'val1', 'b': 'val2', 'c': 'val3', 'd': 'val4'} + for test_cf in (cf, cf_stub): + assert_raises(NotFoundException, test_cf.get, key) + ts = test_cf.insert(key, columns) + assert_true(isinstance(ts, (int, long))) + assert_equal(test_cf.get(key, column_start='b', column_reversed=True), {'b': 'val2', 'a': 'val1'}) + def test_insert_get_column_count(self): key = 'TestColumnFamily.test_insert_get_column_count' columns = {'a': 'val1', 'b': 'val2', 'c': 'val3', 'd': 'val4'} @@ -127,6 +147,22 @@ def test_insert_multiget_column_start_and_finish(self): assert_equal(rows[key2], {'3': 'val1'}) assert_true(missing_key not in rows) + def test_insert_multiget_column_finish_and_reversed(self): + key1 = 'TestColumnFamily.test_insert_multiget_column_finish_and_reversed1' + columns1 = {'1': 'val1', '3': 'val2'} + key2 = 'TestColumnFamily.test_insert_multiget_column_finish_and_reversed2' + columns2 = {'5': 'val1', '7': 'val2'} + missing_key = 'key3' + + for test_cf in (cf, cf_stub): + test_cf.insert(key1, columns1) + test_cf.insert(key2, columns2) + rows = test_cf.multiget([key1, key2, missing_key], column_finish='3', column_reversed=True) + assert_equal(len(rows), 2) + assert_equal(rows[key1], {'3': 'val2'}) + assert_equal(rows[key2], {'5': 'val1', '7': 'val2'}) + assert_true(missing_key not in rows) + def test_insert_multiget_column_start_column_count(self): key1 = 'TestColumnFamily.test_insert_multiget_column_start_column_count' columns1 = {'1': 'val1', '2': 'val2'} @@ -175,7 +211,6 @@ def insert_insert_get_indexed_slices(self): count += 1 assert_equal(count, 3) - def test_remove(self): key = 'TestColumnFamily.test_remove' for test_cf in (cf, cf_stub):