Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions gcloud/bigtable/column_family.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ class GarbageCollectionRule(object):
don't support that feature and instead support via native classes.
"""

def to_pb(self):
"""Converts the :class:`GarbageCollectionRule` to a protobuf.

:raises: :class:`NotImplementedError <exceptions.NotImplementedError>`
always since a virtual class.
"""
raise NotImplementedError

def __ne__(self, other):
return not self.__eq__(other)

Expand Down
93 changes: 93 additions & 0 deletions gcloud/bigtable/row.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@


from gcloud._helpers import _to_bytes
from gcloud.bigtable._generated import bigtable_data_pb2 as data_pb2


class Row(object):
Expand All @@ -31,3 +32,95 @@ class Row(object):
def __init__(self, row_key, table):
self._row_key = _to_bytes(row_key)
self._table = table


class RowFilter(object):
"""Basic filter to apply to cells in a row.

These values can be combined via :class:`RowFilterChain`,
:class:`RowFilterUnion` and :class:`ConditionalRowFilter`.

.. note::

This class is a do-nothing base class for all row filters.
"""

def __ne__(self, other):
return not self.__eq__(other)


class _RegexFilter(RowFilter):
"""Row filter that uses a regular expression.

The ``regex`` must be valid RE2 patterns. See Google's
`RE2 reference`_ for the accepted syntax.

.. _RE2 reference: https://github.com/google/re2/wiki/Syntax

:type regex: bytes or str
:param regex: A regular expression (RE2) for some row filter.
"""

def __init__(self, regex):
self.regex = regex

def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return other.regex == self.regex


class RowKeyRegexFilter(_RegexFilter):
"""Row filter for a row key regular expression.

The ``regex`` must be valid RE2 patterns. See Google's
`RE2 reference`_ for the accepted syntax.

.. _RE2 reference: https://github.com/google/re2/wiki/Syntax

.. note::

Special care need be used with the expression used. Since
each of these properties can contain arbitrary bytes, the ``\\C``
escape sequence must be used if a true wildcard is desired. The ``.``
character will not match the new line character ``\\n``, which may be
present in a binary value.

:type regex: bytes
:param regex: A regular expression (RE2) to match cells from rows with row
keys that satisfy this regex. For a
``CheckAndMutateRowRequest``, this filter is unnecessary
since the row key is already specified.
"""

def to_pb(self):
"""Converts the row filter to a protobuf.

:rtype: :class:`.data_pb2.RowFilter`
:returns: The converted current object.
"""
return data_pb2.RowFilter(row_key_regex_filter=self.regex)


class FamilyNameRegexFilter(_RegexFilter):
"""Row filter for a family name regular expression.

The ``regex`` must be valid RE2 patterns. See Google's
`RE2 reference`_ for the accepted syntax.

.. _RE2 reference: https://github.com/google/re2/wiki/Syntax

:type regex: str
:param regex: A regular expression (RE2) to match cells from columns in a
given column family. For technical reasons, the regex must
not contain the ``':'`` character, even if it is not being
used as a literal.
"""

def to_pb(self):
"""Converts the row filter to a protobuf.

:rtype: :class:`.data_pb2.RowFilter`
:returns: The converted current object.
"""
return data_pb2.RowFilter(family_name_regex_filter=self.regex)
36 changes: 11 additions & 25 deletions gcloud/bigtable/test_column_family.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,6 @@ def test_with_negative_seconds(self):
self.assertEqual(result.nanos, -(10**9 - 1000 * microseconds))


class TestGarbageCollectionRule(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.bigtable.column_family import GarbageCollectionRule
return GarbageCollectionRule

def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)

def test_to_pb_virtual(self):
gc_rule = self._makeOne()
self.assertRaises(NotImplementedError, gc_rule.to_pb)


class TestMaxVersionsGCRule(unittest2.TestCase):

def _getTargetClass(self):
Expand All @@ -84,16 +70,16 @@ def _getTargetClass(self):
def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)

def test___eq__max_num_versions(self):
gc_rule1 = self._makeOne(2)
gc_rule2 = self._makeOne(2)
self.assertEqual(gc_rule1, gc_rule2)

def test___eq__type_differ(self):
gc_rule1 = self._makeOne(10)
gc_rule2 = object()
self.assertNotEqual(gc_rule1, gc_rule2)

def test___eq__same_value(self):
gc_rule1 = self._makeOne(2)
gc_rule2 = self._makeOne(2)
self.assertEqual(gc_rule1, gc_rule2)

def test___ne__same_value(self):
gc_rule1 = self._makeOne(99)
gc_rule2 = self._makeOne(99)
Expand All @@ -119,18 +105,18 @@ def _getTargetClass(self):
def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)

def test___eq__max_age(self):
max_age = object()
gc_rule1 = self._makeOne(max_age=max_age)
gc_rule2 = self._makeOne(max_age=max_age)
self.assertEqual(gc_rule1, gc_rule2)

def test___eq__type_differ(self):
max_age = object()
gc_rule1 = self._makeOne(max_age=max_age)
gc_rule2 = object()
self.assertNotEqual(gc_rule1, gc_rule2)

def test___eq__same_value(self):
max_age = object()
gc_rule1 = self._makeOne(max_age=max_age)
gc_rule2 = self._makeOne(max_age=max_age)
self.assertEqual(gc_rule1, gc_rule2)

def test___ne__same_value(self):
max_age = object()
gc_rule1 = self._makeOne(max_age=max_age)
Expand Down
72 changes: 72 additions & 0 deletions gcloud/bigtable/test_row.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,75 @@ def test_constructor_with_non_bytes(self):
row_key = object()
with self.assertRaises(TypeError):
self._makeOne(row_key, None)


class Test_RegexFilter(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.bigtable.row import _RegexFilter
return _RegexFilter

def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)

def test_constructor(self):
regex = object()
row_filter = self._makeOne(regex)
self.assertTrue(row_filter.regex is regex)

def test___eq__type_differ(self):
regex = object()
row_filter1 = self._makeOne(regex=regex)
row_filter2 = object()
self.assertNotEqual(row_filter1, row_filter2)

def test___eq__same_value(self):
regex = object()
row_filter1 = self._makeOne(regex=regex)
row_filter2 = self._makeOne(regex=regex)
self.assertEqual(row_filter1, row_filter2)

def test___ne__same_value(self):
regex = object()
row_filter1 = self._makeOne(regex=regex)
row_filter2 = self._makeOne(regex=regex)
comparison_val = (row_filter1 != row_filter2)
self.assertFalse(comparison_val)


class TestRowKeyRegexFilter(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.bigtable.row import RowKeyRegexFilter
return RowKeyRegexFilter

def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)

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

regex = b'row-key-regex'
row_filter = self._makeOne(regex)
pb_val = row_filter.to_pb()
expected_pb = data_pb2.RowFilter(row_key_regex_filter=regex)
self.assertEqual(pb_val, expected_pb)


class TestFamilyNameRegexFilter(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.bigtable.row import FamilyNameRegexFilter
return FamilyNameRegexFilter

def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)

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

regex = u'family-regex'
row_filter = self._makeOne(regex)
pb_val = row_filter.to_pb()
expected_pb = data_pb2.RowFilter(family_name_regex_filter=regex)
self.assertEqual(pb_val, expected_pb)