diff --git a/gcloud/bigtable/row_data.py b/gcloud/bigtable/row_data.py index bf8f4ac16696..533a7f09f896 100644 --- a/gcloud/bigtable/row_data.py +++ b/gcloud/bigtable/row_data.py @@ -109,3 +109,37 @@ def to_dict(self): _to_bytes(column_qual)) result[key] = cells return result + + +class PartialRowsData(object): + """Convenience wrapper for consuming a ``ReadRows`` streaming response. + + :type response_iterator: + :class:`grpc.framework.alpha._reexport._CancellableIterator` + :param response_iterator: A streaming iterator returned from a + ``ReadRows`` request. + """ + + def __init__(self, response_iterator): + # We expect an iterator of `data_messages_pb2.ReadRowsResponse` + self._response_iterator = response_iterator + self._rows = {} + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + return other._response_iterator == self._response_iterator + + def __ne__(self, other): + return not self.__eq__(other) + + @property + def rows(self): + """Property returning all rows accumulated from the stream. + + :rtype: dict + :returns: Dictionary of :class:`PartialRowData`. + """ + # NOTE: To avoid duplicating large objects, this is just the + # mutable private data. + return self._rows diff --git a/gcloud/bigtable/test_row_data.py b/gcloud/bigtable/test_row_data.py index f8bd185c4394..784b5042a3bd 100644 --- a/gcloud/bigtable/test_row_data.py +++ b/gcloud/bigtable/test_row_data.py @@ -176,3 +176,50 @@ def test_to_dict(self): b'name2:col3': cell3, } self.assertEqual(result, expected_result) + + +class TestPartialRowsData(unittest2.TestCase): + + def _getTargetClass(self): + from gcloud.bigtable.row_data import PartialRowsData + return PartialRowsData + + def _makeOne(self, *args, **kwargs): + return self._getTargetClass()(*args, **kwargs) + + def test_constructor(self): + response_iterator = object() + partial_rows_data = self._makeOne(response_iterator) + self.assertTrue(partial_rows_data._response_iterator + is response_iterator) + self.assertEqual(partial_rows_data._rows, {}) + + def test___eq__(self): + response_iterator = object() + partial_rows_data1 = self._makeOne(response_iterator) + partial_rows_data2 = self._makeOne(response_iterator) + self.assertEqual(partial_rows_data1, partial_rows_data2) + + def test___eq__type_differ(self): + partial_rows_data1 = self._makeOne(None) + partial_rows_data2 = object() + self.assertNotEqual(partial_rows_data1, partial_rows_data2) + + def test___ne__same_value(self): + response_iterator = object() + partial_rows_data1 = self._makeOne(response_iterator) + partial_rows_data2 = self._makeOne(response_iterator) + comparison_val = (partial_rows_data1 != partial_rows_data2) + self.assertFalse(comparison_val) + + def test___ne__(self): + response_iterator1 = object() + partial_rows_data1 = self._makeOne(response_iterator1) + response_iterator2 = object() + partial_rows_data2 = self._makeOne(response_iterator2) + self.assertNotEqual(partial_rows_data1, partial_rows_data2) + + def test_rows_getter(self): + partial_rows_data = self._makeOne(None) + partial_rows_data._rows = value = object() + self.assertTrue(partial_rows_data.rows is value)