Skip to content

Commit

Permalink
Merge pull request googleapis#1387 from dhermes/bigtable-add-mutation…
Browse files Browse the repository at this point in the history
…s-to-row

Adding tracking mutations to Bigtable row.
  • Loading branch information
dhermes committed Jan 15, 2016
2 parents cfc20f2 + ecf3777 commit 5cd168c
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
48 changes: 48 additions & 0 deletions gcloud/bigtable/row.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
class Row(object):
"""Representation of a Google Cloud Bigtable Row.
.. note::
A :class:`Row` accumulates mutations locally via the :meth:`set_cell`,
:meth:`delete`, :meth:`delete_cell` and :meth:`delete_cells` methods.
To actually send these mutations to the Google Cloud Bigtable API, you
must call :meth:`commit`. If a ``filter_`` is set on the :class:`Row`,
the mutations must have an associated state: :data:`True` or
:data:`False`. The mutations will be applied conditionally, based on
whether the filter matches any cells in the :class:`Row` or not.
:type row_key: bytes
:param row_key: The key for the current row.
Expand All @@ -43,6 +53,14 @@ def __init__(self, row_key, table, filter_=None):
self._table = table
self._filter = filter_
self._rule_pb_list = []
if self._filter is None:
self._pb_mutations = []
self._true_pb_mutations = None
self._false_pb_mutations = None
else:
self._pb_mutations = None
self._true_pb_mutations = []
self._false_pb_mutations = []

def append_cell_value(self, column_family_id, column, value):
"""Appends a value to an existing cell.
Expand Down Expand Up @@ -75,6 +93,36 @@ def append_cell_value(self, column_family_id, column, value):
append_value=value)
self._rule_pb_list.append(rule_pb)

def _get_mutations(self, state=None):
"""Gets the list of mutations for a given state.
If the state is :data`None` but there is a filter set, then we've
reached an invalid state. Similarly if no filter is set but the
state is not :data:`None`.
:type state: bool
:param state: (Optional) The state that the mutation should be
applied in. Unset if the mutation is not conditional,
otherwise :data:`True` or :data:`False`.
:rtype: list
:returns: The list to add new mutations to (for the current state).
:raises: :class:`ValueError <exceptions.ValueError>`
"""
if state is None:
if self._filter is not None:
raise ValueError('A filter is set on the current row, but no '
'state given for the mutation')
return self._pb_mutations
else:
if self._filter is None:
raise ValueError('No filter was set on the current row, but a '
'state was given for the mutation')
if state:
return self._true_pb_mutations
else:
return self._false_pb_mutations


class RowFilter(object):
"""Basic filter to apply to cells in a row.
Expand Down
40 changes: 40 additions & 0 deletions gcloud/bigtable/test_row.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,46 @@ def test_constructor_with_non_bytes(self):
with self.assertRaises(TypeError):
self._makeOne(row_key, None)

def _get_mutations_helper(self, filter_=None, state=None):
row_key = b'row_key'
row = self._makeOne(row_key, None, filter_=filter_)
# Mock the mutations with unique objects so we can compare.
row._pb_mutations = no_bool = object()
row._true_pb_mutations = true_mutations = object()
row._false_pb_mutations = false_mutations = object()

mutations = row._get_mutations(state)
return (no_bool, true_mutations, false_mutations), mutations

def test__get_mutations_no_filter(self):
(no_bool, _, _), mutations = self._get_mutations_helper()
self.assertTrue(mutations is no_bool)

def test__get_mutations_no_filter_bad_state(self):
state = object() # State should be null when no filter.
with self.assertRaises(ValueError):
self._get_mutations_helper(state=state)

def test__get_mutations_with_filter_true_state(self):
filter_ = object()
state = True
(_, true_filter, _), mutations = self._get_mutations_helper(
filter_=filter_, state=state)
self.assertTrue(mutations is true_filter)

def test__get_mutations_with_filter_false_state(self):
filter_ = object()
state = False
(_, _, false_filter), mutations = self._get_mutations_helper(
filter_=filter_, state=state)
self.assertTrue(mutations is false_filter)

def test__get_mutations_with_filter_bad_state(self):
filter_ = object()
state = None
with self.assertRaises(ValueError):
self._get_mutations_helper(filter_=filter_, state=state)

def test_append_cell_value(self):
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2

Expand Down

0 comments on commit 5cd168c

Please sign in to comment.