Skip to content

Commit 77cbba0

Browse files
committed
Removing cover.sh and folding into tox config.
This is to make the tox config friendlier to Windows and other non-bash shells. Towards #1123.
2 parents cec15ac + 9c18dad commit 77cbba0

File tree

6 files changed

+134
-36
lines changed

6 files changed

+134
-36
lines changed

gcloud/bigtable/client.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@
1919
In the hierarchy of API concepts
2020
2121
* a :class:`Client` owns a :class:`.Cluster`
22-
* a :class:`.Cluster` owns a :class:`Table <gcloud_bigtable.table.Table>`
23-
* a :class:`Table <gcloud_bigtable.table.Table>` owns a
22+
* a :class:`.Cluster` owns a :class:`Table <gcloud.bigtable.table.Table>`
23+
* a :class:`Table <gcloud.bigtable.table.Table>` owns a
2424
:class:`ColumnFamily <.column_family.ColumnFamily>`
25-
* a :class:`Table <gcloud_bigtable.table.Table>` owns a :class:`Row <.row.Row>`
25+
* a :class:`Table <gcloud.bigtable.table.Table>` owns a :class:`Row <.row.Row>`
2626
(and all the cells in the row)
2727
"""
2828

2929

3030
import copy
3131

32+
from gcloud.bigtable._generated import bigtable_cluster_data_pb2 as data_pb2
3233
from gcloud.bigtable._generated import bigtable_cluster_service_pb2
34+
from gcloud.bigtable._generated import (
35+
bigtable_cluster_service_messages_pb2 as messages_pb2)
3336
from gcloud.bigtable._generated import bigtable_service_pb2
3437
from gcloud.bigtable._generated import bigtable_table_service_pb2
3538
from gcloud.bigtable._generated import operations_pb2
@@ -192,7 +195,7 @@ def project_name(self):
192195
193196
The project name is of the form
194197
195-
``"projects/{project_id}"``
198+
``"projects/{project}"``
196199
197200
:rtype: str
198201
:returns: The project name to be used with the Cloud Bigtable Admin
@@ -375,3 +378,25 @@ def cluster(self, zone, cluster_id, display_name=None, serve_nodes=3):
375378
"""
376379
return Cluster(zone, cluster_id, self,
377380
display_name=display_name, serve_nodes=serve_nodes)
381+
382+
def list_zones(self):
383+
"""Lists zones associated with project.
384+
385+
:rtype: list
386+
:returns: The names (as :class:`str`) of the zones
387+
:raises: :class:`ValueError <exceptions.ValueError>` if one of the
388+
zones is not in ``OK`` state.
389+
"""
390+
request_pb = messages_pb2.ListZonesRequest(name=self.project_name)
391+
response = self._cluster_stub.ListZones.async(request_pb,
392+
self.timeout_seconds)
393+
# We expect a `.messages_pb2.ListZonesResponse`
394+
list_zones_response = response.result()
395+
396+
result = []
397+
for zone in list_zones_response.zones:
398+
if zone.status != data_pb2.Zone.OK:
399+
raise ValueError('Zone %s not in OK state' % (
400+
zone.display_name,))
401+
result.append(zone.display_name)
402+
return result

gcloud/bigtable/column_family.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class ColumnFamily(object):
2222
:param column_family_id: The ID of the column family. Must be of the
2323
form ``[_a-zA-Z0-9][-_.a-zA-Z0-9]*``.
2424
25-
:type table: :class:`Table <gcloud_bigtable.table.Table>`
25+
:type table: :class:`Table <gcloud.bigtable.table.Table>`
2626
:param table: The table that owns the column family.
2727
"""
2828

gcloud/bigtable/row.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class Row(object):
2424
:type row_key: bytes
2525
:param row_key: The key for the current row.
2626
27-
:type table: :class:`Table <gcloud_bigtable.table.Table>`
27+
:type table: :class:`Table <gcloud.bigtable.table.Table>`
2828
:param table: The table that owns the row.
2929
"""
3030

gcloud/bigtable/test_client.py

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,59 @@ def test_cluster_factory(self):
494494
self.assertEqual(cluster.serve_nodes, serve_nodes)
495495
self.assertTrue(cluster._client is client)
496496

497+
def _list_zones_helper(self, zone_status):
498+
from gcloud.bigtable._generated import (
499+
bigtable_cluster_data_pb2 as data_pb2)
500+
from gcloud.bigtable._generated import (
501+
bigtable_cluster_service_messages_pb2 as messages_pb2)
502+
503+
credentials = _Credentials()
504+
project = 'PROJECT'
505+
timeout_seconds = 281330
506+
client = self._makeOne(project=project, credentials=credentials,
507+
admin=True, timeout_seconds=timeout_seconds)
508+
509+
# Create request_pb
510+
request_pb = messages_pb2.ListZonesRequest(
511+
name='projects/' + project,
512+
)
513+
514+
# Create response_pb
515+
zone1 = 'foo'
516+
zone2 = 'bar'
517+
response_pb = messages_pb2.ListZonesResponse(
518+
zones=[
519+
data_pb2.Zone(display_name=zone1, status=zone_status),
520+
data_pb2.Zone(display_name=zone2, status=zone_status),
521+
],
522+
)
523+
524+
# Patch the stub used by the API method.
525+
client._cluster_stub_internal = stub = _FakeStub(response_pb)
526+
527+
# Create expected_result.
528+
expected_result = [zone1, zone2]
529+
530+
# Perform the method and check the result.
531+
result = client.list_zones()
532+
self.assertEqual(result, expected_result)
533+
self.assertEqual(stub.method_calls, [(
534+
'ListZones',
535+
(request_pb, timeout_seconds),
536+
{},
537+
)])
538+
539+
def test_list_zones(self):
540+
from gcloud.bigtable._generated import (
541+
bigtable_cluster_data_pb2 as data_pb2)
542+
self._list_zones_helper(data_pb2.Zone.OK)
543+
544+
def test_list_zones_failure(self):
545+
from gcloud.bigtable._generated import (
546+
bigtable_cluster_data_pb2 as data_pb2)
547+
with self.assertRaises(ValueError):
548+
self._list_zones_helper(data_pb2.Zone.EMERGENCY_MAINENANCE)
549+
497550

498551
class _Credentials(object):
499552

@@ -511,8 +564,11 @@ def __eq__(self, other):
511564

512565

513566
class _FakeStub(object):
567+
"""Acts as a gPRC stub."""
514568

515-
def __init__(self):
569+
def __init__(self, *results):
570+
self.results = results
571+
self.method_calls = []
516572
self._entered = 0
517573
self._exited = []
518574

@@ -523,3 +579,38 @@ def __enter__(self):
523579
def __exit__(self, exc_type, exc_val, exc_tb):
524580
self._exited.append((exc_type, exc_val, exc_tb))
525581
return True
582+
583+
def __getattr__(self, name):
584+
# We need not worry about attributes set in constructor
585+
# since __getattribute__ will handle them.
586+
return _MethodMock(name, self)
587+
588+
589+
class _MethodMock(object):
590+
"""Mock for :class:`grpc.framework.alpha._reexport._UnaryUnarySyncAsync`.
591+
592+
May need to be callable and needs to (in our use) have an
593+
``async`` method.
594+
"""
595+
596+
def __init__(self, name, factory):
597+
self._name = name
598+
self._factory = factory
599+
600+
def async(self, *args, **kwargs):
601+
"""Async method meant to mock a gRPC stub request."""
602+
self._factory.method_calls.append((self._name, args, kwargs))
603+
curr_result, self._factory.results = (self._factory.results[0],
604+
self._factory.results[1:])
605+
return _AsyncResult(curr_result)
606+
607+
608+
class _AsyncResult(object):
609+
"""Result returned from a ``_MethodMock.async`` call."""
610+
611+
def __init__(self, result):
612+
self._result = result
613+
614+
def result(self):
615+
"""Result method on an asyc object."""
616+
return self._result

scripts/cover.sh

Lines changed: 0 additions & 27 deletions
This file was deleted.

tox.ini

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,29 @@ deps =
1313
protobuf>=3.0.0a3
1414
setenv =
1515
PYTHONPATH = {toxinidir}/_testing
16+
covercmd =
17+
nosetests \
18+
--ignore-files=run_system_test\.py \
19+
--with-coverage \
20+
--cover-package=gcloud \
21+
--cover-erase \
22+
--cover-tests \
23+
--cover-branches \
24+
--nocapture
1625

1726
[testenv:cover]
1827
basepython =
1928
python2.7
2029
commands =
21-
{toxinidir}/scripts/cover.sh --cover-min-percentage=100
30+
{[testenv]covercmd} --cover-min-percentage=100
2231
deps =
2332
{[testenv]deps}
2433
coverage
2534

2635
[testenv:coveralls]
2736
basepython = {[testenv:cover]basepython}
2837
commands =
29-
{toxinidir}/scripts/cover.sh
38+
{[testenv]covercmd}
3039
coveralls
3140
deps =
3241
{[testenv:cover]deps}

0 commit comments

Comments
 (0)