Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8315501

Browse filesBrowse files
committed
Merge pull request googleapis#1305 from dhermes/bigtable-convert-gc-rule
Adding helper to convert protobuf GC rules into our types.
2 parents ae01c3a + 650536a commit 8315501
Copy full SHA for 8315501

2 files changed

+150Lines changed: 150 additions & 0 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎gcloud/bigtable/column_family.py‎

Copy file name to clipboardExpand all lines: gcloud/bigtable/column_family.py
+55Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
"""User friendly container for Google Cloud Bigtable Column Family."""
1616

1717

18+
import datetime
19+
1820
from gcloud._helpers import _total_seconds
1921
from gcloud.bigtable._generated import bigtable_table_data_pb2 as data_pb2
2022
from gcloud.bigtable._generated import duration_pb2
@@ -46,6 +48,26 @@ def _timedelta_to_duration_pb(timedelta_val):
4648
return duration_pb2.Duration(seconds=seconds, nanos=nanos)
4749

4850

51+
def _duration_pb_to_timedelta(duration_pb):
52+
"""Convert a duration protobuf to a Python timedelta object.
53+
54+
.. note::
55+
56+
The Python timedelta has a granularity of microseconds while
57+
the protobuf duration type has a duration of nanoseconds.
58+
59+
:type duration_pb: :class:`.duration_pb2.Duration`
60+
:param duration_pb: A protobuf duration object.
61+
62+
:rtype: :class:`datetime.timedelta`
63+
:returns: The converted timedelta object.
64+
"""
65+
return datetime.timedelta(
66+
seconds=duration_pb.seconds,
67+
microseconds=(duration_pb.nanos / 1000.0),
68+
)
69+
70+
4971
class GarbageCollectionRule(object):
5072
"""Garbage collection rule for column families within a table.
5173
@@ -197,3 +219,36 @@ def __eq__(self, other):
197219

198220
def __ne__(self, other):
199221
return not self.__eq__(other)
222+
223+
224+
def _gc_rule_from_pb(gc_rule_pb):
225+
"""Convert a protobuf GC rule to a native object.
226+
227+
:type gc_rule_pb: :class:`.data_pb2.GcRule`
228+
:param gc_rule_pb: The GC rule to convert.
229+
230+
:rtype: :class:`GarbageCollectionRule` or :data:`NoneType <types.NoneType>`
231+
:returns: An instance of one of the native rules defined
232+
in :module:`column_family` or :data:`None` if no values were
233+
set on the protobuf passed in.
234+
:raises: :class:`ValueError <exceptions.ValueError>` if the rule name
235+
is unexpected.
236+
"""
237+
rule_name = gc_rule_pb.WhichOneof('rule')
238+
if rule_name is None:
239+
return None
240+
241+
if rule_name == 'max_num_versions':
242+
return MaxVersionsGCRule(gc_rule_pb.max_num_versions)
243+
elif rule_name == 'max_age':
244+
max_age = _duration_pb_to_timedelta(gc_rule_pb.max_age)
245+
return MaxAgeGCRule(max_age)
246+
elif rule_name == 'union':
247+
return GCRuleUnion([_gc_rule_from_pb(rule)
248+
for rule in gc_rule_pb.union.rules])
249+
elif rule_name == 'intersection':
250+
rules = [_gc_rule_from_pb(rule)
251+
for rule in gc_rule_pb.intersection.rules]
252+
return GCRuleIntersection(rules)
253+
else:
254+
raise ValueError('Unexpected rule name', rule_name)
Collapse file

‎gcloud/bigtable/test_column_family.py‎

Copy file name to clipboardExpand all lines: gcloud/bigtable/test_column_family.py
+95Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,26 @@ def test_with_negative_seconds(self):
6161
self.assertEqual(result.nanos, -(10**9 - 1000 * microseconds))
6262

6363

64+
class Test__duration_pb_to_timedelta(unittest2.TestCase):
65+
66+
def _callFUT(self, *args, **kwargs):
67+
from gcloud.bigtable.column_family import _duration_pb_to_timedelta
68+
return _duration_pb_to_timedelta(*args, **kwargs)
69+
70+
def test_it(self):
71+
import datetime
72+
from gcloud.bigtable._generated import duration_pb2
73+
74+
seconds = microseconds = 1
75+
duration_pb = duration_pb2.Duration(seconds=seconds,
76+
nanos=1000 * microseconds)
77+
timedelta_val = datetime.timedelta(seconds=seconds,
78+
microseconds=microseconds)
79+
result = self._callFUT(duration_pb)
80+
self.assertTrue(isinstance(result, datetime.timedelta))
81+
self.assertEqual(result, timedelta_val)
82+
83+
6484
class TestMaxVersionsGCRule(unittest2.TestCase):
6585

6686
def _getTargetClass(self):
@@ -365,3 +385,78 @@ def test___ne__(self):
365385
column_family1 = self._makeOne('column_family_id1', None)
366386
column_family2 = self._makeOne('column_family_id2', None)
367387
self.assertNotEqual(column_family1, column_family2)
388+
389+
390+
class Test__gc_rule_from_pb(unittest2.TestCase):
391+
392+
def _callFUT(self, *args, **kwargs):
393+
from gcloud.bigtable.column_family import _gc_rule_from_pb
394+
return _gc_rule_from_pb(*args, **kwargs)
395+
396+
def test_empty(self):
397+
from gcloud.bigtable._generated import (
398+
bigtable_table_data_pb2 as data_pb2)
399+
400+
gc_rule_pb = data_pb2.GcRule()
401+
self.assertEqual(self._callFUT(gc_rule_pb), None)
402+
403+
def test_max_num_versions(self):
404+
from gcloud.bigtable.column_family import MaxVersionsGCRule
405+
406+
orig_rule = MaxVersionsGCRule(1)
407+
gc_rule_pb = orig_rule.to_pb()
408+
result = self._callFUT(gc_rule_pb)
409+
self.assertTrue(isinstance(result, MaxVersionsGCRule))
410+
self.assertEqual(result, orig_rule)
411+
412+
def test_max_age(self):
413+
import datetime
414+
from gcloud.bigtable.column_family import MaxAgeGCRule
415+
416+
orig_rule = MaxAgeGCRule(datetime.timedelta(seconds=1))
417+
gc_rule_pb = orig_rule.to_pb()
418+
result = self._callFUT(gc_rule_pb)
419+
self.assertTrue(isinstance(result, MaxAgeGCRule))
420+
self.assertEqual(result, orig_rule)
421+
422+
def test_union(self):
423+
import datetime
424+
from gcloud.bigtable.column_family import GCRuleUnion
425+
from gcloud.bigtable.column_family import MaxAgeGCRule
426+
from gcloud.bigtable.column_family import MaxVersionsGCRule
427+
428+
rule1 = MaxVersionsGCRule(1)
429+
rule2 = MaxAgeGCRule(datetime.timedelta(seconds=1))
430+
orig_rule = GCRuleUnion([rule1, rule2])
431+
gc_rule_pb = orig_rule.to_pb()
432+
result = self._callFUT(gc_rule_pb)
433+
self.assertTrue(isinstance(result, GCRuleUnion))
434+
self.assertEqual(result, orig_rule)
435+
436+
def test_intersection(self):
437+
import datetime
438+
from gcloud.bigtable.column_family import GCRuleIntersection
439+
from gcloud.bigtable.column_family import MaxAgeGCRule
440+
from gcloud.bigtable.column_family import MaxVersionsGCRule
441+
442+
rule1 = MaxVersionsGCRule(1)
443+
rule2 = MaxAgeGCRule(datetime.timedelta(seconds=1))
444+
orig_rule = GCRuleIntersection([rule1, rule2])
445+
gc_rule_pb = orig_rule.to_pb()
446+
result = self._callFUT(gc_rule_pb)
447+
self.assertTrue(isinstance(result, GCRuleIntersection))
448+
self.assertEqual(result, orig_rule)
449+
450+
def test_unknown_field_name(self):
451+
class MockProto(object):
452+
453+
names = []
454+
455+
@classmethod
456+
def WhichOneof(cls, name):
457+
cls.names.append(name)
458+
return 'unknown'
459+
460+
self.assertEqual(MockProto.names, [])
461+
self.assertRaises(ValueError, self._callFUT, MockProto)
462+
self.assertEqual(MockProto.names, ['rule'])

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.