Skip to content

Commit 215b9f6

Browse files
committed
Implementing Bigtable Cluster.list_tables().
This uses the table stub instead of the cluster stub. This method is actually talking to a different service than every method until now. Also implementing Table.__eq__ so table comparison succeeds in unit tests.
1 parent c4ab6de commit 215b9f6

File tree

4 files changed

+125
-0
lines changed

4 files changed

+125
-0
lines changed

gcloud/bigtable/cluster.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from gcloud.bigtable._generated import bigtable_cluster_data_pb2 as data_pb2
2323
from gcloud.bigtable._generated import (
2424
bigtable_cluster_service_messages_pb2 as messages_pb2)
25+
from gcloud.bigtable._generated import (
26+
bigtable_table_service_messages_pb2 as table_messages_pb2)
2527
from gcloud.bigtable.table import Table
2628

2729

@@ -346,3 +348,27 @@ def delete(self):
346348
# We expect a `._generated.empty_pb2.Empty`
347349
self._client._cluster_stub.DeleteCluster(
348350
request_pb, self._client.timeout_seconds)
351+
352+
def list_tables(self):
353+
"""List the tables in this cluster.
354+
355+
:rtype: list of :class:`Table <gcloud.bigtable.table.Table>`
356+
:returns: The list of tables owned by the cluster.
357+
:raises: :class:`ValueError <exceptions.ValueError>` if one of the
358+
returned tables has a name that is not of the expected format.
359+
"""
360+
request_pb = table_messages_pb2.ListTablesRequest(name=self.name)
361+
# We expect a `table_messages_pb2.ListTablesResponse`
362+
table_list_pb = self._client._table_stub.ListTables(
363+
request_pb, self._client.timeout_seconds)
364+
365+
result = []
366+
for table_pb in table_list_pb.tables:
367+
table_prefix = self.name + '/tables/'
368+
if not table_pb.name.startswith(table_prefix):
369+
raise ValueError('Table name %s not of expected format' % (
370+
table_pb.name,))
371+
table_id = table_pb.name[len(table_prefix):]
372+
result.append(self.table(table_id))
373+
374+
return result

gcloud/bigtable/table.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,12 @@ def row(self, row_key):
5555
:returns: A row owned by this table.
5656
"""
5757
return Row(row_key, self)
58+
59+
def __eq__(self, other):
60+
if not isinstance(other, self.__class__):
61+
return False
62+
return (other.table_id == self.table_id and
63+
other._cluster == self._cluster)
64+
65+
def __ne__(self, other):
66+
return not self.__eq__(other)

gcloud/bigtable/test_cluster.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,71 @@ def test_delete(self):
333333
{},
334334
)])
335335

336+
def _list_tables_helper(self, table_id, table_name=None):
337+
from gcloud.bigtable._generated import (
338+
bigtable_table_data_pb2 as table_data_pb2)
339+
from gcloud.bigtable._generated import (
340+
bigtable_table_service_messages_pb2 as table_messages_pb2)
341+
from gcloud.bigtable._testing import _FakeStub
342+
343+
project = 'PROJECT'
344+
zone = 'zone'
345+
cluster_id = 'cluster-id'
346+
timeout_seconds = 45
347+
348+
client = _Client(project, timeout_seconds=timeout_seconds)
349+
cluster = self._makeOne(zone, cluster_id, client)
350+
351+
# Create request_
352+
cluster_name = ('projects/' + project + '/zones/' + zone +
353+
'/clusters/' + cluster_id)
354+
request_pb = table_messages_pb2.ListTablesRequest(name=cluster_name)
355+
356+
# Create response_pb
357+
table_name = table_name or (cluster_name + '/tables/' + table_id)
358+
response_pb = table_messages_pb2.ListTablesResponse(
359+
tables=[
360+
table_data_pb2.Table(name=table_name),
361+
],
362+
)
363+
364+
# Patch the stub used by the API method.
365+
client._table_stub = stub = _FakeStub(response_pb)
366+
367+
# Create expected_result.
368+
expected_table = cluster.table(table_id)
369+
expected_result = [expected_table]
370+
371+
# Perform the method and check the result.
372+
result = cluster.list_tables()
373+
374+
self.assertEqual(result, expected_result)
375+
self.assertEqual(stub.method_calls, [(
376+
'ListTables',
377+
(request_pb, timeout_seconds),
378+
{},
379+
)])
380+
381+
def test_list_tables(self):
382+
table_id = 'table_id'
383+
self._list_tables_helper(table_id)
384+
385+
def test_list_tables_failure_bad_split(self):
386+
with self.assertRaises(ValueError):
387+
self._list_tables_helper(None, table_name='wrong-format')
388+
389+
def test_list_tables_failure_name_bad_before(self):
390+
project = 'PROJECT'
391+
zone = 'zone'
392+
cluster_id = 'cluster-id'
393+
394+
table_id = 'table_id'
395+
bad_table_name = ('nonempty-section-before' +
396+
'projects/' + project + '/zones/' + zone +
397+
'/clusters/' + cluster_id + '/tables/' + table_id)
398+
with self.assertRaises(ValueError):
399+
self._list_tables_helper(table_id, table_name=bad_table_name)
400+
336401

337402
class Test__get_pb_property_value(unittest2.TestCase):
338403

gcloud/bigtable/test_table.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,28 @@ def test_row_factory(self):
5656
self.assertTrue(isinstance(row, Row))
5757
self.assertEqual(row._row_key, row_key)
5858
self.assertEqual(row._table, table)
59+
60+
def test___eq__(self):
61+
table_id = 'table_id'
62+
cluster = object()
63+
table1 = self._makeOne(table_id, cluster)
64+
table2 = self._makeOne(table_id, cluster)
65+
self.assertEqual(table1, table2)
66+
67+
def test___eq__type_differ(self):
68+
table1 = self._makeOne('table_id', None)
69+
table2 = object()
70+
self.assertNotEqual(table1, table2)
71+
72+
def test___ne__same_value(self):
73+
table_id = 'table_id'
74+
cluster = object()
75+
table1 = self._makeOne(table_id, cluster)
76+
table2 = self._makeOne(table_id, cluster)
77+
comparison_val = (table1 != table2)
78+
self.assertFalse(comparison_val)
79+
80+
def test___ne__(self):
81+
table1 = self._makeOne('table_id1', 'cluster1')
82+
table2 = self._makeOne('table_id2', 'cluster2')
83+
self.assertNotEqual(table1, table2)

0 commit comments

Comments
 (0)