Skip to content

Commit 2547f84

Browse files
committed
Adding Bigtable factories and shell classes.
The Cluster, Table, Row and ColumnFamily classes (and modules) are introduced, but without any functionality except for other nested factories.
1 parent 509564d commit 2547f84

File tree

12 files changed

+495
-0
lines changed

12 files changed

+495
-0
lines changed

gcloud/_helpers.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import calendar
2020
import datetime
2121
import os
22+
import six
2223
import socket
2324

2425
try:
@@ -264,6 +265,37 @@ def _millis_from_datetime(value):
264265
return _millis(value)
265266

266267

268+
def _to_bytes(value, encoding='ascii'):
269+
"""Converts a string value to bytes, if necessary.
270+
271+
Unfortunately, ``six.b`` is insufficient for this task since in
272+
Python2 it does not modify ``unicode`` objects.
273+
274+
:type value: str / bytes or unicode
275+
:param value: The string/bytes value to be converted.
276+
277+
:type encoding: str
278+
:param encoding: The encoding to use to convert unicode to bytes. Defaults
279+
to "ascii", which will not allow any characters from
280+
ordinals larger than 127. Other useful values are
281+
"latin-1", which which will only allows byte ordinals
282+
(up to 255) and "utf-8", which will encode any unicode
283+
that needs to be.
284+
285+
:rtype: str / bytes
286+
:returns: The original value converted to bytes (if unicode) or as passed
287+
in if it started out as bytes.
288+
:raises: :class:`TypeError <exceptions.TypeError>` if the value
289+
could not be converted to bytes.
290+
"""
291+
result = (value.encode(encoding)
292+
if isinstance(value, six.text_type) else value)
293+
if isinstance(result, six.binary_type):
294+
return result
295+
else:
296+
raise TypeError('%r could not be converted to bytes' % (value,))
297+
298+
267299
try:
268300
from pytz import UTC # pylint: disable=unused-import
269301
except ImportError:

gcloud/bigtable/client.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from gcloud.bigtable._generated import bigtable_table_service_pb2
3535
from gcloud.bigtable._generated import operations_pb2
3636
from gcloud.bigtable._helpers import make_stub
37+
from gcloud.bigtable.cluster import Cluster
3738
from gcloud.client import _ClientFactoryMixin
3839
from gcloud.client import _ClientProjectMixin
3940
from gcloud.credentials import get_credentials
@@ -349,3 +350,28 @@ def stop(self):
349350
self._cluster_stub_internal = None
350351
self._operations_stub_internal = None
351352
self._table_stub_internal = None
353+
354+
def cluster(self, zone, cluster_id, display_name=None, serve_nodes=3):
355+
"""Factory to create a cluster associated with this client.
356+
357+
:type zone: str
358+
:param zone: The name of the zone where the cluster resides.
359+
360+
:type cluster_id: str
361+
:param cluster_id: The ID of the cluster.
362+
363+
:type display_name: str
364+
:param display_name: (Optional) The display name for the cluster in the
365+
Cloud Console UI. (Must be between 4 and 30
366+
characters.) If this value is not set in the
367+
constructor, will fall back to the cluster ID.
368+
369+
:type serve_nodes: int
370+
:param serve_nodes: (Optional) The number of nodes in the cluster.
371+
Defaults to 3.
372+
373+
:rtype: :class:`.Cluster`
374+
:returns: The cluster owned by this client.
375+
"""
376+
return Cluster(zone, cluster_id, self,
377+
display_name=display_name, serve_nodes=serve_nodes)

gcloud/bigtable/cluster.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright 2015 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""User friendly container for Google Cloud Bigtable Cluster."""
16+
17+
18+
from gcloud.bigtable.table import Table
19+
20+
21+
class Cluster(object):
22+
"""Representation of a Google Cloud Bigtable Cluster.
23+
24+
:type zone: str
25+
:param zone: The name of the zone where the cluster resides.
26+
27+
:type cluster_id: str
28+
:param cluster_id: The ID of the cluster.
29+
30+
:type client: :class:`.client.Client`
31+
:param client: The client that owns the cluster. Provides
32+
authorization and a project ID.
33+
34+
:type display_name: str
35+
:param display_name: (Optional) The display name for the cluster in the
36+
Cloud Console UI. (Must be between 4 and 30
37+
characters.) If this value is not set in the
38+
constructor, will fall back to the cluster ID.
39+
40+
:type serve_nodes: int
41+
:param serve_nodes: (Optional) The number of nodes in the cluster.
42+
Defaults to 3.
43+
"""
44+
45+
def __init__(self, zone, cluster_id, client,
46+
display_name=None, serve_nodes=3):
47+
self.zone = zone
48+
self.cluster_id = cluster_id
49+
self.display_name = display_name or cluster_id
50+
self.serve_nodes = serve_nodes
51+
self._client = client
52+
53+
def table(self, table_id):
54+
"""Factory to create a table associated with this cluster.
55+
56+
:type table_id: str
57+
:param table_id: The ID of the table.
58+
59+
:rtype: :class:`Table <gcloud.bigtable.table.Table>`
60+
:returns: The table owned by this cluster.
61+
"""
62+
return Table(table_id, self)

gcloud/bigtable/column_family.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2015 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""User friendly container for Google Cloud Bigtable Column Family."""
16+
17+
18+
class ColumnFamily(object):
19+
"""Representation of a Google Cloud Bigtable Column Family.
20+
21+
:type column_family_id: str
22+
:param column_family_id: The ID of the column family. Must be of the
23+
form ``[_a-zA-Z0-9][-_.a-zA-Z0-9]*``.
24+
25+
:type table: :class:`Table <gcloud_bigtable.table.Table>`
26+
:param table: The table that owns the column family.
27+
"""
28+
29+
def __init__(self, column_family_id, table):
30+
self.column_family_id = column_family_id
31+
self._table = table

gcloud/bigtable/row.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright 2015 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""User friendly container for Google Cloud Bigtable Row."""
16+
17+
18+
from gcloud._helpers import _to_bytes
19+
20+
21+
class Row(object):
22+
"""Representation of a Google Cloud Bigtable Row.
23+
24+
:type row_key: bytes
25+
:param row_key: The key for the current row.
26+
27+
:type table: :class:`Table <gcloud_bigtable.table.Table>`
28+
:param table: The table that owns the row.
29+
"""
30+
31+
def __init__(self, row_key, table):
32+
self._row_key = _to_bytes(row_key)
33+
self._table = table

gcloud/bigtable/table.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Copyright 2015 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""User friendly container for Google Cloud Bigtable Table."""
16+
17+
18+
from gcloud.bigtable.column_family import ColumnFamily
19+
from gcloud.bigtable.row import Row
20+
21+
22+
class Table(object):
23+
"""Representation of a Google Cloud Bigtable Table.
24+
25+
:type table_id: str
26+
:param table_id: The ID of the table.
27+
28+
:type cluster: :class:`.cluster.Cluster`
29+
:param cluster: The cluster that owns the table.
30+
"""
31+
32+
def __init__(self, table_id, cluster):
33+
self.table_id = table_id
34+
self._cluster = cluster
35+
36+
def column_family(self, column_family_id):
37+
"""Factory to create a column family associated with this table.
38+
39+
:type column_family_id: str
40+
:param column_family_id: The ID of the column family. Must be of the
41+
form ``[_a-zA-Z0-9][-_.a-zA-Z0-9]*``.
42+
43+
:rtype: :class:`.column_family.ColumnFamily`
44+
:returns: A column family owned by this table.
45+
"""
46+
return ColumnFamily(column_family_id, self)
47+
48+
def row(self, row_key):
49+
"""Factory to create a row associated with this table.
50+
51+
:type row_key: bytes
52+
:param row_key: The key for the row being created.
53+
54+
:rtype: :class:`.Row`
55+
:returns: A row owned by this table.
56+
"""
57+
return Row(row_key, self)

gcloud/bigtable/test_client.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,26 @@ def test_stop_while_stopped(self):
474474
# Make sure the cluster stub did not change.
475475
self.assertEqual(client._cluster_stub_internal, cluster_stub)
476476

477+
def test_cluster_factory(self):
478+
from gcloud.bigtable.cluster import Cluster
479+
480+
credentials = _Credentials()
481+
project = 'PROJECT'
482+
client = self._makeOne(project=project, credentials=credentials)
483+
484+
zone = 'zone'
485+
cluster_id = 'cluster-id'
486+
display_name = 'display-name'
487+
serve_nodes = 42
488+
cluster = client.cluster(zone, cluster_id, display_name=display_name,
489+
serve_nodes=serve_nodes)
490+
self.assertTrue(isinstance(cluster, Cluster))
491+
self.assertEqual(cluster.zone, zone)
492+
self.assertEqual(cluster.cluster_id, cluster_id)
493+
self.assertEqual(cluster.display_name, display_name)
494+
self.assertEqual(cluster.serve_nodes, serve_nodes)
495+
self.assertTrue(cluster._client is client)
496+
477497

478498
class _Credentials(object):
479499

gcloud/bigtable/test_cluster.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Copyright 2015 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
import unittest2
17+
18+
19+
class TestCluster(unittest2.TestCase):
20+
21+
def _getTargetClass(self):
22+
from gcloud.bigtable.cluster import Cluster
23+
return Cluster
24+
25+
def _makeOne(self, *args, **kwargs):
26+
return self._getTargetClass()(*args, **kwargs)
27+
28+
def test_constructor_defaults(self):
29+
zone = 'zone'
30+
cluster_id = 'cluster-id'
31+
client = object()
32+
33+
cluster = self._makeOne(zone, cluster_id, client)
34+
self.assertEqual(cluster.zone, zone)
35+
self.assertEqual(cluster.cluster_id, cluster_id)
36+
self.assertEqual(cluster.display_name, cluster_id)
37+
self.assertEqual(cluster.serve_nodes, 3)
38+
self.assertTrue(cluster._client is client)
39+
40+
def test_constructor_non_default(self):
41+
zone = 'zone'
42+
cluster_id = 'cluster-id'
43+
display_name = 'display_name'
44+
serve_nodes = 8
45+
client = object()
46+
47+
cluster = self._makeOne(zone, cluster_id, client,
48+
display_name=display_name,
49+
serve_nodes=serve_nodes)
50+
self.assertEqual(cluster.zone, zone)
51+
self.assertEqual(cluster.cluster_id, cluster_id)
52+
self.assertEqual(cluster.display_name, display_name)
53+
self.assertEqual(cluster.serve_nodes, serve_nodes)
54+
self.assertTrue(cluster._client is client)
55+
56+
def test_table_factory(self):
57+
from gcloud.bigtable.table import Table
58+
59+
zone = 'zone'
60+
cluster_id = 'cluster-id'
61+
cluster = self._makeOne(zone, cluster_id, None)
62+
63+
table_id = 'table_id'
64+
table = cluster.table(table_id)
65+
self.assertTrue(isinstance(table, Table))
66+
self.assertEqual(table.table_id, table_id)
67+
self.assertEqual(table._cluster, cluster)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2015 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
import unittest2
17+
18+
19+
class TestColumnFamily(unittest2.TestCase):
20+
21+
def _getTargetClass(self):
22+
from gcloud.bigtable.column_family import ColumnFamily
23+
return ColumnFamily
24+
25+
def _makeOne(self, *args, **kwargs):
26+
return self._getTargetClass()(*args, **kwargs)
27+
28+
def test_constructor(self):
29+
column_family_id = u'column-family-id'
30+
table = object()
31+
column_family = self._makeOne(column_family_id, table)
32+
33+
self.assertEqual(column_family.column_family_id, column_family_id)
34+
self.assertTrue(column_family._table is table)

0 commit comments

Comments
 (0)