Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit de62ecf

Browse files
committed
Merge pull request #1309 from dhermes/bigtable-row-filter-5
Implementing Bigtable ValueRangeFilter.
2 parents f89b76a + 7e210bb commit de62ecf

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed

gcloud/bigtable/row.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,93 @@ def to_pb(self):
257257
return data_pb2.RowFilter(value_regex_filter=self.regex)
258258

259259

260+
class ValueRangeFilter(RowFilter):
261+
"""A range of values to restrict to in a row filter.
262+
263+
Will only match cells that have values in this range.
264+
265+
Both the start and end value can be included or excluded in the range.
266+
By default, we include them both, but this can be changed with optional
267+
flags.
268+
269+
:type start_value: bytes
270+
:param start_value: The start of the range of values. If no value is used,
271+
the backend applies no lower bound to the values.
272+
273+
:type end_value: bytes
274+
:param end_value: The end of the range of values. If no value is used,
275+
the backend applies no upper bound to the values.
276+
277+
:type inclusive_start: bool
278+
:param inclusive_start: Boolean indicating if the start value should be
279+
included in the range (or excluded). Defaults
280+
to :data:`True` if ``start_value`` is passed and
281+
no ``inclusive_start`` was given.
282+
283+
:type inclusive_end: bool
284+
:param inclusive_end: Boolean indicating if the end value should be
285+
included in the range (or excluded). Defaults
286+
to :data:`True` if ``end_value`` is passed and
287+
no ``inclusive_end`` was given.
288+
289+
:raises: :class:`ValueError <exceptions.ValueError>` if ``inclusive_start``
290+
is set but no ``start_value`` is given or if ``inclusive_end``
291+
is set but no ``end_value`` is given
292+
"""
293+
294+
def __init__(self, start_value=None, end_value=None,
295+
inclusive_start=None, inclusive_end=None):
296+
if inclusive_start is None:
297+
inclusive_start = True
298+
elif start_value is None:
299+
raise ValueError('Inclusive start was specified but no '
300+
'start value was given.')
301+
self.start_value = start_value
302+
self.inclusive_start = inclusive_start
303+
304+
if inclusive_end is None:
305+
inclusive_end = True
306+
elif end_value is None:
307+
raise ValueError('Inclusive end was specified but no '
308+
'end value was given.')
309+
self.end_value = end_value
310+
self.inclusive_end = inclusive_end
311+
312+
def __eq__(self, other):
313+
if not isinstance(other, self.__class__):
314+
return False
315+
return (other.start_value == self.start_value and
316+
other.end_value == self.end_value and
317+
other.inclusive_start == self.inclusive_start and
318+
other.inclusive_end == self.inclusive_end)
319+
320+
def to_pb(self):
321+
"""Converts the row filter to a protobuf.
322+
323+
First converts to a :class:`.data_pb2.ValueRange` and then uses
324+
it to create a row filter protobuf.
325+
326+
:rtype: :class:`.data_pb2.RowFilter`
327+
:returns: The converted current object.
328+
"""
329+
value_range_kwargs = {}
330+
if self.start_value is not None:
331+
if self.inclusive_start:
332+
key = 'start_value_inclusive'
333+
else:
334+
key = 'start_value_exclusive'
335+
value_range_kwargs[key] = _to_bytes(self.start_value)
336+
if self.end_value is not None:
337+
if self.inclusive_end:
338+
key = 'end_value_inclusive'
339+
else:
340+
key = 'end_value_exclusive'
341+
value_range_kwargs[key] = _to_bytes(self.end_value)
342+
343+
value_range = data_pb2.ValueRange(**value_range_kwargs)
344+
return data_pb2.RowFilter(value_range_filter=value_range)
345+
346+
260347
class _CellCountFilter(RowFilter):
261348
"""Row filter that uses an integer count of cells.
262349

gcloud/bigtable/test_row.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,107 @@ def test_to_pb(self):
249249
self.assertEqual(pb_val, expected_pb)
250250

251251

252+
class TestValueRangeFilter(unittest2.TestCase):
253+
254+
def _getTargetClass(self):
255+
from gcloud.bigtable.row import ValueRangeFilter
256+
return ValueRangeFilter
257+
258+
def _makeOne(self, *args, **kwargs):
259+
return self._getTargetClass()(*args, **kwargs)
260+
261+
def test_constructor_defaults(self):
262+
row_filter = self._makeOne()
263+
self.assertEqual(row_filter.start_value, None)
264+
self.assertEqual(row_filter.end_value, None)
265+
self.assertTrue(row_filter.inclusive_start)
266+
self.assertTrue(row_filter.inclusive_end)
267+
268+
def test_constructor_explicit(self):
269+
start_value = object()
270+
end_value = object()
271+
inclusive_start = object()
272+
inclusive_end = object()
273+
row_filter = self._makeOne(start_value=start_value,
274+
end_value=end_value,
275+
inclusive_start=inclusive_start,
276+
inclusive_end=inclusive_end)
277+
self.assertTrue(row_filter.start_value is start_value)
278+
self.assertTrue(row_filter.end_value is end_value)
279+
self.assertTrue(row_filter.inclusive_start is inclusive_start)
280+
self.assertTrue(row_filter.inclusive_end is inclusive_end)
281+
282+
def test_constructor_bad_start(self):
283+
self.assertRaises(ValueError, self._makeOne, inclusive_start=True)
284+
285+
def test_constructor_bad_end(self):
286+
self.assertRaises(ValueError, self._makeOne, inclusive_end=True)
287+
288+
def test___eq__(self):
289+
start_value = object()
290+
end_value = object()
291+
inclusive_start = object()
292+
inclusive_end = object()
293+
row_filter1 = self._makeOne(start_value=start_value,
294+
end_value=end_value,
295+
inclusive_start=inclusive_start,
296+
inclusive_end=inclusive_end)
297+
row_filter2 = self._makeOne(start_value=start_value,
298+
end_value=end_value,
299+
inclusive_start=inclusive_start,
300+
inclusive_end=inclusive_end)
301+
self.assertEqual(row_filter1, row_filter2)
302+
303+
def test___eq__type_differ(self):
304+
row_filter1 = self._makeOne()
305+
row_filter2 = object()
306+
self.assertNotEqual(row_filter1, row_filter2)
307+
308+
def test_to_pb(self):
309+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
310+
311+
row_filter = self._makeOne()
312+
expected_pb = data_pb2.RowFilter(
313+
value_range_filter=data_pb2.ValueRange())
314+
self.assertEqual(row_filter.to_pb(), expected_pb)
315+
316+
def test_to_pb_inclusive_start(self):
317+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
318+
319+
value = b'some-value'
320+
row_filter = self._makeOne(start_value=value)
321+
val_range_pb = data_pb2.ValueRange(start_value_inclusive=value)
322+
expected_pb = data_pb2.RowFilter(value_range_filter=val_range_pb)
323+
self.assertEqual(row_filter.to_pb(), expected_pb)
324+
325+
def test_to_pb_exclusive_start(self):
326+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
327+
328+
value = b'some-value'
329+
row_filter = self._makeOne(start_value=value, inclusive_start=False)
330+
val_range_pb = data_pb2.ValueRange(start_value_exclusive=value)
331+
expected_pb = data_pb2.RowFilter(value_range_filter=val_range_pb)
332+
self.assertEqual(row_filter.to_pb(), expected_pb)
333+
334+
def test_to_pb_inclusive_end(self):
335+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
336+
337+
value = b'some-value'
338+
row_filter = self._makeOne(end_value=value)
339+
val_range_pb = data_pb2.ValueRange(end_value_inclusive=value)
340+
expected_pb = data_pb2.RowFilter(value_range_filter=val_range_pb)
341+
self.assertEqual(row_filter.to_pb(), expected_pb)
342+
343+
def test_to_pb_exclusive_end(self):
344+
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2
345+
346+
value = b'some-value'
347+
row_filter = self._makeOne(end_value=value, inclusive_end=False)
348+
val_range_pb = data_pb2.ValueRange(end_value_exclusive=value)
349+
expected_pb = data_pb2.RowFilter(value_range_filter=val_range_pb)
350+
self.assertEqual(row_filter.to_pb(), expected_pb)
351+
352+
252353
class Test_CellCountFilter(unittest2.TestCase):
253354

254355
def _getTargetClass(self):

0 commit comments

Comments
 (0)