From b4fdfc33b9b4af535d2566095ba4b43ea73c5e0e Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Wed, 13 Dec 2017 15:18:58 -0800 Subject: [PATCH] Adding `PartialRowData.get_cells()`. --- bigtable/google/cloud/bigtable/row_data.py | 70 ++++++++++++++++++---- bigtable/tests/unit/test_row_data.py | 48 +++++++++++++++ 2 files changed, 108 insertions(+), 10 deletions(-) diff --git a/bigtable/google/cloud/bigtable/row_data.py b/bigtable/google/cloud/bigtable/row_data.py index fe9204b91ce70..b86f3331ae3ae 100644 --- a/bigtable/google/cloud/bigtable/row_data.py +++ b/bigtable/google/cloud/bigtable/row_data.py @@ -181,12 +181,43 @@ def row_key(self): """ return self._row_key + def _get_cells_no_copy(self, column_family_id, column): + """Get a time series of cells stored on this instance. + + Args: + column_family_id (str): The ID of the column family. Must be of the + form ``[_a-zA-Z0-9][-_.a-zA-Z0-9]*``. + column (bytes): The column within the column family where the cells + are located. + + Returns: + List[~google.cloud.bigtable.row_data.Cell]: The cells stored in the + specified column. + + Raises: + KeyError: If ``column_family_id`` is not among the cells stored + in this row. + KeyError: If ``column`` is not among the cells stored in this row + for the given ``column_family_id``. + """ + try: + column_family = self._cells[column_family_id] + except KeyError: + raise KeyError(_MISSING_COLUMN_FAMILY.format(column_family_id)) + + try: + cells = column_family[column] + except KeyError: + raise KeyError(_MISSING_COLUMN.format(column, column_family_id)) + + return cells + def get_cell(self, column_family_id, column, index=0): """Get a single cell stored on this instance. .. note:: - This returns a copy of the actual ``Cell`` (so that the + This returns a copy of the actual cell (so that the caller cannot mutate internal state). Args: @@ -210,15 +241,7 @@ def get_cell(self, column_family_id, column, index=0): in this row for the given ``column_family_id``, ``column`` pair. """ - try: - column_family = self._cells[column_family_id] - except KeyError: - raise KeyError(_MISSING_COLUMN_FAMILY.format(column_family_id)) - - try: - cells = column_family[column] - except KeyError: - raise KeyError(_MISSING_COLUMN.format(column, column_family_id)) + cells = self._get_cells_no_copy(column_family_id, column) try: cell = cells[index] @@ -230,6 +253,33 @@ def get_cell(self, column_family_id, column, index=0): return copy.deepcopy(cell) + def get_cells(self, column_family_id, column): + """Get a time series of cells stored on this instance. + + .. note:: + + This returns a copy of the actual cells (so that the + caller cannot mutate internal state). + + Args: + column_family_id (str): The ID of the column family. Must be of the + form ``[_a-zA-Z0-9][-_.a-zA-Z0-9]*``. + column (bytes): The column within the column family where the cells + are located. + + Returns: + List[~google.cloud.bigtable.row_data.Cell]: The cells stored in the + specified column. + + Raises: + KeyError: If ``column_family_id`` is not among the cells stored + in this row. + KeyError: If ``column`` is not among the cells stored in this row + for the given ``column_family_id``. + """ + cells = self._get_cells_no_copy(column_family_id, column) + return copy.deepcopy(cells) + class InvalidReadRowsResponse(RuntimeError): """Exception raised to to invalid response data from back-end.""" diff --git a/bigtable/tests/unit/test_row_data.py b/bigtable/tests/unit/test_row_data.py index c8a20957cdbdf..770261cb5cb3f 100644 --- a/bigtable/tests/unit/test_row_data.py +++ b/bigtable/tests/unit/test_row_data.py @@ -261,6 +261,54 @@ def test_get_cell_bad_index(self): index, qual, family_name, 0) self.assertEqual(exc_info.exception.args, (expected_arg,)) + def test_get_cells(self): + family_name = u'name1' + qual = b'col1' + cell = _make_cell(b'hi-mom') + + partial_row_data = self._make_one(None) + cells = [cell] + partial_row_data._cells = { + family_name: { + qual: cells, + }, + } + + result = partial_row_data.get_cells(family_name, qual) + # Make sure we get a copy, not the original. + self.assertIsNot(result, cells) + self.assertEqual(result, cells) + self.assertIsNot(result[0], cell) + self.assertEqual(result[0], cell) + + def test_get_cells_bad_family(self): + from google.cloud.bigtable import row_data + + family_name = u'name1' + partial_row_data = self._make_one(None) + self.assertEqual(partial_row_data._cells, {}) + + with self.assertRaises(KeyError) as exc_info: + partial_row_data.get_cells(family_name, None) + + expected_arg = row_data._MISSING_COLUMN_FAMILY.format(family_name) + self.assertEqual(exc_info.exception.args, (expected_arg,)) + + def test_get_cell_bad_column(self): + from google.cloud.bigtable import row_data + + family_name = u'name1' + qual = b'col1' + + partial_row_data = self._make_one(None) + partial_row_data._cells = {family_name: {}} + + with self.assertRaises(KeyError) as exc_info: + partial_row_data.get_cells(family_name, qual) + + expected_arg = row_data._MISSING_COLUMN.format(qual, family_name) + self.assertEqual(exc_info.exception.args, (expected_arg,)) + def test_cells_property(self): partial_row_data = self._make_one(None) cells = {1: 2}