Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gcloud/storage/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
from gcloud.storage.api import get_all_buckets
from gcloud.storage.api import get_bucket
from gcloud.storage.api import lookup_bucket
from gcloud.storage.batch import Batch
from gcloud.storage.blob import Blob
from gcloud.storage.bucket import Bucket
from gcloud.storage.connection import Connection
Expand Down
39 changes: 29 additions & 10 deletions gcloud/storage/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from gcloud.exceptions import NotFound
from gcloud._helpers import get_default_project
from gcloud.storage._implicit_environ import get_default_connection
from gcloud.storage.batch import Batch
from gcloud.storage.bucket import Bucket
from gcloud.storage.iterator import Iterator

Expand Down Expand Up @@ -51,9 +52,7 @@ def lookup_bucket(bucket_name, connection=None):
:rtype: :class:`gcloud.storage.bucket.Bucket`
:returns: The bucket matching the name provided or None if not found.
"""
if connection is None:
connection = get_default_connection()

connection = _require_connection(connection)
try:
return get_bucket(bucket_name, connection=connection)
except NotFound:
Expand Down Expand Up @@ -84,8 +83,7 @@ def get_all_buckets(project=None, connection=None):
:rtype: iterable of :class:`gcloud.storage.bucket.Bucket` objects.
:returns: All buckets belonging to this project.
"""
if connection is None:
connection = get_default_connection()
connection = _require_connection(connection)
if project is None:
project = get_default_project()
extra_params = {'project': project}
Expand Down Expand Up @@ -122,9 +120,7 @@ def get_bucket(bucket_name, connection=None):
:returns: The bucket matching the name provided.
:raises: :class:`gcloud.exceptions.NotFound`
"""
if connection is None:
connection = get_default_connection()

connection = _require_connection(connection)
bucket = Bucket(bucket_name, connection=connection)
bucket.reload()
return bucket
Expand Down Expand Up @@ -160,8 +156,7 @@ def create_bucket(bucket_name, project=None, connection=None):
:raises: :class:`gcloud.exceptions.Conflict` if
there is a confict (bucket already exists, invalid name, etc.)
"""
if connection is None:
connection = get_default_connection()
connection = _require_connection(connection)
if project is None:
project = get_default_project()

Expand Down Expand Up @@ -201,3 +196,27 @@ def get_items_from_response(self, response):
bucket = Bucket(name, connection=self.connection)
bucket._properties = item
yield bucket


def _require_connection(connection=None):
"""Infer a connection from the environment, if not passed explicitly.

:type connection: :class:`gcloud.storage.connection.Connection`
:param connection: Optional.

:rtype: :class:`gcloud.storage.connection.Connection`
:returns: A connection based on the current environment.
:raises: :class:`EnvironmentError` if ``connection`` is ``None``, and
cannot be inferred from the environment.
"""
# NOTE: We use current Batch directly since it inherits from Connection.
if connection is None:
connection = Batch.current()

if connection is None:
connection = get_default_connection()

if connection is None:
raise EnvironmentError('Connection could not be inferred.')

return connection
5 changes: 5 additions & 0 deletions gcloud/storage/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ def finish(self):
self._responses = list(_unpack_batch_response(response, content))
return self._responses

@staticmethod
def current():
"""Return the topmost batch, or None."""
return _BATCHES.top

def __enter__(self):
_BATCHES.push(self)
return self
Expand Down
53 changes: 53 additions & 0 deletions gcloud/storage/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,44 @@ def test_get_items_from_response_non_empty(self):
self.assertEqual(bucket.name, BLOB_NAME)


class Test__require_connection(unittest2.TestCase):

def _callFUT(self, connection=None):
from gcloud.storage.api import _require_connection
return _require_connection(connection=connection)

def _monkey(self, connection):
from gcloud.storage._testing import _monkey_defaults
return _monkey_defaults(connection=connection)

def test_implicit_unset(self):
with self._monkey(None):
with self.assertRaises(EnvironmentError):
self._callFUT()

def test_implicit_unset_w_existing_batch(self):
CONNECTION = object()
with self._monkey(None):
with _NoCommitBatch(connection=CONNECTION):
self.assertEqual(self._callFUT(), CONNECTION)

def test_implicit_unset_passed_explicitly(self):
CONNECTION = object()
with self._monkey(None):
self.assertTrue(self._callFUT(CONNECTION) is CONNECTION)

def test_implicit_set(self):
IMPLICIT_CONNECTION = object()
with self._monkey(IMPLICIT_CONNECTION):
self.assertTrue(self._callFUT() is IMPLICIT_CONNECTION)

def test_implicit_set_passed_explicitly(self):
IMPLICIT_CONNECTION = object()
CONNECTION = object()
with self._monkey(IMPLICIT_CONNECTION):
self.assertTrue(self._callFUT(CONNECTION) is CONNECTION)


class Http(object):

_called_with = None
Expand All @@ -296,3 +334,18 @@ def __init__(self, headers, content):
def request(self, **kw):
self._called_with = kw
return self._response, self._content


class _NoCommitBatch(object):

def __init__(self, connection):
self._connection = connection

def __enter__(self):
from gcloud.storage.batch import _BATCHES
_BATCHES.push(self._connection)
return self._connection

def __exit__(self, *args):
from gcloud.storage.batch import _BATCHES
_BATCHES.pop()
3 changes: 1 addition & 2 deletions regression/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from gcloud import storage
from gcloud import _helpers
from gcloud.storage._helpers import _base64_md5hash
from gcloud.storage.batch import Batch


HTTP = httplib2.Http()
Expand Down Expand Up @@ -52,7 +51,7 @@ def setUp(self):
self.case_buckets_to_delete = []

def tearDown(self):
with Batch() as batch:
with storage.Batch() as batch:
for bucket_name in self.case_buckets_to_delete:
storage.Bucket(bucket_name, connection=batch).delete()

Expand Down