Skip to content

Commit 4861e7e

Browse files
committed
Merge pull request #1307 from dhermes/bigtable-row-filter-4
Adding Bigtable row filters for boolean flags.
2 parents 8315501 + b453381 commit 4861e7e

2 files changed

Lines changed: 209 additions & 10 deletions

File tree

gcloud/bigtable/row.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,77 @@ def __ne__(self, other):
4949
return not self.__eq__(other)
5050

5151

52+
class _BoolFilter(RowFilter):
53+
"""Row filter that uses a boolean flag.
54+
55+
:type flag: bool
56+
:param flag: An indicator if a setting is turned on or off.
57+
"""
58+
59+
def __init__(self, flag):
60+
self.flag = flag
61+
62+
def __eq__(self, other):
63+
if not isinstance(other, self.__class__):
64+
return False
65+
return other.flag == self.flag
66+
67+
68+
class SinkFilter(_BoolFilter):
69+
"""Advanced row filter to skip parent filters.
70+
71+
:type flag: bool
72+
:param flag: ADVANCED USE ONLY. Hook for introspection into the row filter.
73+
Outputs all cells directly to the output of the read rather
74+
than to any parent filter. Cannot be used within the
75+
``predicate_filter``, ``true_filter``, or ``false_filter``
76+
of a :class:`ConditionalRowFilter`.
77+
"""
78+
79+
def to_pb(self):
80+
"""Converts the row filter to a protobuf.
81+
82+
:rtype: :class:`.data_pb2.RowFilter`
83+
:returns: The converted current object.
84+
"""
85+
return data_pb2.RowFilter(sink=self.flag)
86+
87+
88+
class PassAllFilter(_BoolFilter):
89+
"""Row filter equivalent to not filtering at all.
90+
91+
:type flag: bool
92+
:param flag: Matches all cells, regardless of input. Functionally
93+
equivalent to leaving ``filter`` unset, but included for
94+
completeness.
95+
"""
96+
97+
def to_pb(self):
98+
"""Converts the row filter to a protobuf.
99+
100+
:rtype: :class:`.data_pb2.RowFilter`
101+
:returns: The converted current object.
102+
"""
103+
return data_pb2.RowFilter(pass_all_filter=self.flag)
104+
105+
106+
class BlockAllFilter(_BoolFilter):
107+
"""Row filter that doesn't match any cells.
108+
109+
:type flag: bool
110+
:param flag: Does not match any cells, regardless of input. Useful for
111+
temporarily disabling just part of a filter.
112+
"""
113+
114+
def to_pb(self):
115+
"""Converts the row filter to a protobuf.
116+
117+
:rtype: :class:`.data_pb2.RowFilter`
118+
:returns: The converted current object.
119+
"""
120+
return data_pb2.RowFilter(block_all_filter=self.flag)
121+
122+
52123
class _RegexFilter(RowFilter):
53124
"""Row filter that uses a regular expression.
54125
@@ -253,3 +324,21 @@ def to_pb(self):
253324
:returns: The converted current object.
254325
"""
255326
return data_pb2.RowFilter(cells_per_column_limit_filter=self.num_cells)
327+
328+
329+
class StripValueTransformerFilter(_BoolFilter):
330+
"""Row filter that transforms cells into empty string (0 bytes).
331+
332+
:type flag: bool
333+
:param flag: If :data:`True`, replaces each cell's value with the empty
334+
string. As the name indicates, this is more useful as a
335+
transformer than a generic query / filter.
336+
"""
337+
338+
def to_pb(self):
339+
"""Converts the row filter to a protobuf.
340+
341+
:rtype: :class:`.data_pb2.RowFilter`
342+
:returns: The converted current object.
343+
"""
344+
return data_pb2.RowFilter(strip_value_transformer=self.flag)

gcloud/bigtable/test_row.py

Lines changed: 120 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,97 @@ def test_constructor_with_non_bytes(self):
4848
self._makeOne(row_key, None)
4949

5050

51+
class Test_BoolFilter(unittest2.TestCase):
52+
53+
def _getTargetClass(self):
54+
from gcloud.bigtable.row import _BoolFilter
55+
return _BoolFilter
56+
57+
def _makeOne(self, *args, **kwargs):
58+
return self._getTargetClass()(*args, **kwargs)
59+
60+
def test_constructor(self):
61+
flag = object()
62+
row_filter = self._makeOne(flag)
63+
self.assertTrue(row_filter.flag is flag)
64+
65+
def test___eq__type_differ(self):
66+
flag = object()
67+
row_filter1 = self._makeOne(flag)
68+
row_filter2 = object()
69+
self.assertNotEqual(row_filter1, row_filter2)
70+
71+
def test___eq__same_value(self):
72+
flag = object()
73+
row_filter1 = self._makeOne(flag)
74+
row_filter2 = self._makeOne(flag)
75+
self.assertEqual(row_filter1, row_filter2)
76+
77+
def test___ne__same_value(self):
78+
flag = object()
79+
row_filter1 = self._makeOne(flag)
80+
row_filter2 = self._makeOne(flag)
81+
comparison_val = (row_filter1 != row_filter2)
82+
self.assertFalse(comparison_val)
83+
84+
85+
class TestSinkFilter(unittest2.TestCase):
86+
87+
def _getTargetClass(self):
88+
from gcloud.bigtable.row import SinkFilter
89+
return SinkFilter
90+
91+
def _makeOne(self, *args, **kwargs):
92+
return self._getTargetClass()(*args, **kwargs)
93+
94+
def test_to_pb(self):
95+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
96+
97+
flag = True
98+
row_filter = self._makeOne(flag)
99+
pb_val = row_filter.to_pb()
100+
expected_pb = data_pb2.RowFilter(sink=flag)
101+
self.assertEqual(pb_val, expected_pb)
102+
103+
104+
class TestPassAllFilter(unittest2.TestCase):
105+
106+
def _getTargetClass(self):
107+
from gcloud.bigtable.row import PassAllFilter
108+
return PassAllFilter
109+
110+
def _makeOne(self, *args, **kwargs):
111+
return self._getTargetClass()(*args, **kwargs)
112+
113+
def test_to_pb(self):
114+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
115+
116+
flag = True
117+
row_filter = self._makeOne(flag)
118+
pb_val = row_filter.to_pb()
119+
expected_pb = data_pb2.RowFilter(pass_all_filter=flag)
120+
self.assertEqual(pb_val, expected_pb)
121+
122+
123+
class TestBlockAllFilter(unittest2.TestCase):
124+
125+
def _getTargetClass(self):
126+
from gcloud.bigtable.row import BlockAllFilter
127+
return BlockAllFilter
128+
129+
def _makeOne(self, *args, **kwargs):
130+
return self._getTargetClass()(*args, **kwargs)
131+
132+
def test_to_pb(self):
133+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
134+
135+
flag = True
136+
row_filter = self._makeOne(flag)
137+
pb_val = row_filter.to_pb()
138+
expected_pb = data_pb2.RowFilter(block_all_filter=flag)
139+
self.assertEqual(pb_val, expected_pb)
140+
141+
51142
class Test_RegexFilter(unittest2.TestCase):
52143

53144
def _getTargetClass(self):
@@ -64,20 +155,20 @@ def test_constructor(self):
64155

65156
def test___eq__type_differ(self):
66157
regex = object()
67-
row_filter1 = self._makeOne(regex=regex)
158+
row_filter1 = self._makeOne(regex)
68159
row_filter2 = object()
69160
self.assertNotEqual(row_filter1, row_filter2)
70161

71162
def test___eq__same_value(self):
72163
regex = object()
73-
row_filter1 = self._makeOne(regex=regex)
74-
row_filter2 = self._makeOne(regex=regex)
164+
row_filter1 = self._makeOne(regex)
165+
row_filter2 = self._makeOne(regex)
75166
self.assertEqual(row_filter1, row_filter2)
76167

77168
def test___ne__same_value(self):
78169
regex = object()
79-
row_filter1 = self._makeOne(regex=regex)
80-
row_filter2 = self._makeOne(regex=regex)
170+
row_filter1 = self._makeOne(regex)
171+
row_filter2 = self._makeOne(regex)
81172
comparison_val = (row_filter1 != row_filter2)
82173
self.assertFalse(comparison_val)
83174

@@ -174,20 +265,20 @@ def test_constructor(self):
174265

175266
def test___eq__type_differ(self):
176267
num_cells = object()
177-
row_filter1 = self._makeOne(num_cells=num_cells)
268+
row_filter1 = self._makeOne(num_cells)
178269
row_filter2 = object()
179270
self.assertNotEqual(row_filter1, row_filter2)
180271

181272
def test___eq__same_value(self):
182273
num_cells = object()
183-
row_filter1 = self._makeOne(num_cells=num_cells)
184-
row_filter2 = self._makeOne(num_cells=num_cells)
274+
row_filter1 = self._makeOne(num_cells)
275+
row_filter2 = self._makeOne(num_cells)
185276
self.assertEqual(row_filter1, row_filter2)
186277

187278
def test___ne__same_value(self):
188279
num_cells = object()
189-
row_filter1 = self._makeOne(num_cells=num_cells)
190-
row_filter2 = self._makeOne(num_cells=num_cells)
280+
row_filter1 = self._makeOne(num_cells)
281+
row_filter2 = self._makeOne(num_cells)
191282
comparison_val = (row_filter1 != row_filter2)
192283
self.assertFalse(comparison_val)
193284

@@ -248,3 +339,22 @@ def test_to_pb(self):
248339
expected_pb = data_pb2.RowFilter(
249340
cells_per_column_limit_filter=num_cells)
250341
self.assertEqual(pb_val, expected_pb)
342+
343+
344+
class TestStripValueTransformerFilter(unittest2.TestCase):
345+
346+
def _getTargetClass(self):
347+
from gcloud.bigtable.row import StripValueTransformerFilter
348+
return StripValueTransformerFilter
349+
350+
def _makeOne(self, *args, **kwargs):
351+
return self._getTargetClass()(*args, **kwargs)
352+
353+
def test_to_pb(self):
354+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
355+
356+
flag = True
357+
row_filter = self._makeOne(flag)
358+
pb_val = row_filter.to_pb()
359+
expected_pb = data_pb2.RowFilter(strip_value_transformer=flag)
360+
self.assertEqual(pb_val, expected_pb)

0 commit comments

Comments
 (0)