Skip to content

Commit e25034d

Browse files
committed
Adding implicit connection fallback in Bucket.
1 parent 622d994 commit e25034d

File tree

5 files changed

+88
-4
lines changed

5 files changed

+88
-4
lines changed

gcloud/storage/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
from gcloud.storage.api import get_all_buckets
5252
from gcloud.storage.api import get_bucket
5353
from gcloud.storage.api import lookup_bucket
54+
from gcloud.storage.batch import Batch
5455
from gcloud.storage.blob import Blob
5556
from gcloud.storage.bucket import Bucket
5657
from gcloud.storage.connection import Connection

gcloud/storage/batch.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ def finish(self):
155155
self._responses = list(_unpack_batch_response(response, content))
156156
return self._responses
157157

158+
@staticmethod
159+
def current():
160+
"""Return the topmost batch, or None."""
161+
return _BATCHES.top
162+
158163
def __enter__(self):
159164
_BATCHES.push(self)
160165
return self

gcloud/storage/bucket.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
from gcloud.exceptions import NotFound
4040
from gcloud.storage._helpers import _PropertyMixin
4141
from gcloud.storage._helpers import _scalar_property
42+
from gcloud.storage import _implicit_environ
4243
from gcloud.storage.acl import BucketACL
4344
from gcloud.storage.acl import DefaultObjectACL
4445
from gcloud.storage.iterator import Iterator
46+
from gcloud.storage.batch import Batch
4547
from gcloud.storage.blob import Blob
4648

4749

@@ -146,7 +148,7 @@ def connection(self):
146148
:rtype: :class:`gcloud.storage.connection.Connection`
147149
:returns: The connection to use.
148150
"""
149-
return self._connection
151+
return _require_connection(self._connection)
150152

151153
@staticmethod
152154
def path_helper(bucket_name):
@@ -746,3 +748,27 @@ def make_public(self, recursive=False, future=False):
746748
for blob in self:
747749
blob.acl.all().grant_read()
748750
blob.save_acl()
751+
752+
753+
def _require_connection(connection=None):
754+
"""Infer a connection from the environment, if not passed explicitly.
755+
756+
:type connection: :class:`gcloud.storage.connection.Connection`
757+
:param connection: Optional.
758+
759+
:rtype: :class:`gcloud.storage.connection.Connection`
760+
:returns: A connection based on the current environment.
761+
:raises: :class:`EnvironmentError` if ``connection`` is ``None``, and
762+
cannot be inferred from the environment.
763+
"""
764+
# NOTE: We use current Batch directly since it inherits from Connection.
765+
if connection is None:
766+
connection = Batch.current()
767+
768+
if connection is None:
769+
connection = _implicit_environ.get_default_connection()
770+
771+
if connection is None:
772+
raise EnvironmentError('Connection could not be inferred.')
773+
774+
return connection

gcloud/storage/test_bucket.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def _makeOne(self, *args, **kw):
7171

7272
def test_ctor_defaults(self):
7373
bucket = self._makeOne()
74-
self.assertEqual(bucket.connection, None)
74+
self.assertEqual(bucket._connection, None)
7575
self.assertEqual(bucket.name, None)
7676
self.assertEqual(bucket._properties, {})
7777
self.assertTrue(bucket._acl is None)
@@ -1068,6 +1068,44 @@ def get_items_from_response(self, response):
10681068
self.assertEqual(kw[1]['query_params'], {})
10691069

10701070

1071+
class Test__require_connection(unittest2.TestCase):
1072+
1073+
def _callFUT(self, connection=None):
1074+
from gcloud.storage.bucket import _require_connection
1075+
return _require_connection(connection=connection)
1076+
1077+
def _monkey(self, connection):
1078+
from gcloud.storage._testing import _monkey_defaults
1079+
return _monkey_defaults(connection=connection)
1080+
1081+
def test_implicit_unset(self):
1082+
with self._monkey(None):
1083+
with self.assertRaises(EnvironmentError):
1084+
self._callFUT()
1085+
1086+
def test_implicit_unset_w_existing_batch(self):
1087+
CONNECTION = object()
1088+
with self._monkey(None):
1089+
with _NoCommitBatch(connection=CONNECTION):
1090+
self.assertEqual(self._callFUT(), CONNECTION)
1091+
1092+
def test_implicit_unset_passed_explicitly(self):
1093+
CONNECTION = object()
1094+
with self._monkey(None):
1095+
self.assertTrue(self._callFUT(CONNECTION) is CONNECTION)
1096+
1097+
def test_implicit_set(self):
1098+
IMPLICIT_CONNECTION = object()
1099+
with self._monkey(IMPLICIT_CONNECTION):
1100+
self.assertTrue(self._callFUT() is IMPLICIT_CONNECTION)
1101+
1102+
def test_implicit_set_passed_explicitly(self):
1103+
IMPLICIT_CONNECTION = object()
1104+
CONNECTION = object()
1105+
with self._monkey(IMPLICIT_CONNECTION):
1106+
self.assertTrue(self._callFUT(CONNECTION) is CONNECTION)
1107+
1108+
10711109
class _Connection(object):
10721110
_delete_bucket = False
10731111

@@ -1118,3 +1156,18 @@ class MockFile(io.StringIO):
11181156
def __init__(self, name, buffer_=None):
11191157
super(MockFile, self).__init__(buffer_)
11201158
self.name = name
1159+
1160+
1161+
class _NoCommitBatch(object):
1162+
1163+
def __init__(self, connection):
1164+
self._connection = connection
1165+
1166+
def __enter__(self):
1167+
from gcloud.storage.batch import _BATCHES
1168+
_BATCHES.push(self._connection)
1169+
return self._connection
1170+
1171+
def __exit__(self, *args):
1172+
from gcloud.storage.batch import _BATCHES
1173+
_BATCHES.pop()

regression/storage.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from gcloud import storage
2323
from gcloud import _helpers
2424
from gcloud.storage._helpers import _base64_md5hash
25-
from gcloud.storage.batch import Batch
2625

2726

2827
HTTP = httplib2.Http()
@@ -52,7 +51,7 @@ def setUp(self):
5251
self.case_buckets_to_delete = []
5352

5453
def tearDown(self):
55-
with Batch() as batch:
54+
with storage.Batch() as batch:
5655
for bucket_name in self.case_buckets_to_delete:
5756
storage.Bucket(bucket_name, connection=batch).delete()
5857

0 commit comments

Comments
 (0)