Skip to content

Commit

Permalink
Putting optional connection on Bucket.get_blob and DELETE methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
dhermes committed Apr 28, 2015
1 parent a14f18a commit dd1ae8d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 29 deletions.
45 changes: 35 additions & 10 deletions gcloud/storage/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def path(self):

return self.path_helper(self.name)

def get_blob(self, blob_name):
def get_blob(self, blob_name, connection=None):
"""Get a blob object by name.
This will return None if the blob doesn't exist::
Expand All @@ -227,13 +227,19 @@ def get_blob(self, blob_name):
:type blob_name: string
:param blob_name: The name of the blob to retrieve.
:type connection: :class:`gcloud.storage.connection.Connection` or
``NoneType``
:param connection: Optional. The connection to use when sending
requests. If not provided, falls back to default.
:rtype: :class:`gcloud.storage.blob.Blob` or None
:returns: The blob object if it exists, otherwise None.
"""
connection = _require_connection(connection)
blob = Blob(bucket=self, name=blob_name)
try:
response = self.connection.api_request(method='GET',
path=blob.path)
response = connection.api_request(method='GET',
path=blob.path)
name = response.get('name') # Expect this to be blob_name
blob = Blob(name, bucket=self)
blob._set_properties(response)
Expand Down Expand Up @@ -304,7 +310,7 @@ def list_blobs(self, max_results=None, page_token=None, prefix=None,
result.next_page_token = page_token
return result

def delete(self, force=False):
def delete(self, force=False, connection=None):
"""Delete this bucket.
The bucket **must** be empty in order to submit a delete request. If
Expand All @@ -323,9 +329,15 @@ def delete(self, force=False):
:type force: boolean
:param force: If True, empties the bucket's objects then deletes it.
:type connection: :class:`gcloud.storage.connection.Connection` or
``NoneType``
:param connection: Optional. The connection to use when sending
requests. If not provided, falls back to default.
:raises: :class:`ValueError` if ``force`` is ``True`` and the bucket
contains more than 256 objects / blobs.
"""
connection = _require_connection(connection)
if force:
blobs = list(self.list_blobs(
max_results=self._MAX_OBJECTS_FOR_BUCKET_DELETE + 1))
Expand All @@ -339,11 +351,12 @@ def delete(self, force=False):
raise ValueError(message)

# Ignore 404 errors on delete.
self.delete_blobs(blobs, on_error=lambda blob: None)
self.delete_blobs(blobs, on_error=lambda blob: None,
connection=connection)

self.connection.api_request(method='DELETE', path=self.path)
connection.api_request(method='DELETE', path=self.path)

def delete_blob(self, blob_name):
def delete_blob(self, blob_name, connection=None):
"""Deletes a blob from the current bucket.
If the blob isn't found (backend 404), raises a
Expand All @@ -366,16 +379,22 @@ def delete_blob(self, blob_name):
:type blob_name: string
:param blob_name: A blob name to delete.
:type connection: :class:`gcloud.storage.connection.Connection` or
``NoneType``
:param connection: Optional. The connection to use when sending
requests. If not provided, falls back to default.
:raises: :class:`gcloud.exceptions.NotFound` (to suppress
the exception, call ``delete_blobs``, passing a no-op
``on_error`` callback, e.g.::
>>> bucket.delete_blobs([blob], on_error=lambda blob: None)
"""
connection = _require_connection(connection)
blob_path = Blob.path_helper(self.path, blob_name)
self.connection.api_request(method='DELETE', path=blob_path)
connection.api_request(method='DELETE', path=blob_path)

def delete_blobs(self, blobs, on_error=None):
def delete_blobs(self, blobs, on_error=None, connection=None):
"""Deletes a list of blobs from the current bucket.
Uses :func:`Bucket.delete_blob` to delete each individual blob.
Expand All @@ -388,15 +407,21 @@ def delete_blobs(self, blobs, on_error=None):
:class:`gcloud.exceptions.NotFound`;
otherwise, the exception is propagated.
:type connection: :class:`gcloud.storage.connection.Connection` or
``NoneType``
:param connection: Optional. The connection to use when sending
requests. If not provided, falls back to default.
:raises: :class:`gcloud.exceptions.NotFound` (if
`on_error` is not passed).
"""
connection = _require_connection(connection)
for blob in blobs:
try:
blob_name = blob
if not isinstance(blob_name, six.string_types):
blob_name = blob.name
self.delete_blob(blob_name)
self.delete_blob(blob_name, connection=connection)
except NotFound:
if on_error is not None:
on_error(blob)
Expand Down
45 changes: 26 additions & 19 deletions gcloud/storage/test_bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,9 @@ def test_get_blob_miss(self):
NAME = 'name'
NONESUCH = 'nonesuch'
connection = _Connection()
bucket = self._makeOne(NAME, connection)
self.assertTrue(bucket.get_blob(NONESUCH) is None)
bucket = self._makeOne(NAME)
result = bucket.get_blob(NONESUCH, connection=connection)
self.assertTrue(result is None)
kw, = connection._requested
self.assertEqual(kw['method'], 'GET')
self.assertEqual(kw['path'], '/b/%s/o/%s' % (NAME, NONESUCH))
Expand All @@ -265,8 +266,8 @@ def test_get_blob_hit(self):
NAME = 'name'
BLOB_NAME = 'blob-name'
connection = _Connection({'name': BLOB_NAME})
bucket = self._makeOne(NAME, connection)
blob = bucket.get_blob(BLOB_NAME)
bucket = self._makeOne(NAME)
blob = bucket.get_blob(BLOB_NAME, connection=connection)
self.assertTrue(blob.bucket is bucket)
self.assertEqual(blob.name, BLOB_NAME)
kw, = connection._requested
Expand Down Expand Up @@ -325,8 +326,8 @@ def test_delete_default_miss(self):
from gcloud.exceptions import NotFound
NAME = 'name'
connection = _Connection()
bucket = self._makeOne(NAME, connection)
self.assertRaises(NotFound, bucket.delete)
bucket = self._makeOne(NAME)
self.assertRaises(NotFound, bucket.delete, connection=connection)
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

Expand All @@ -336,7 +337,8 @@ def test_delete_explicit_hit(self):
connection = _Connection(GET_BLOBS_RESP)
connection._delete_bucket = True
bucket = self._makeOne(NAME, connection)
self.assertEqual(bucket.delete(force=True), None)
result = bucket.delete(force=True, connection=connection)
self.assertTrue(result is None)
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

Expand All @@ -355,7 +357,8 @@ def test_delete_explicit_force_delete_blobs(self):
DELETE_BLOB2_RESP)
connection._delete_bucket = True
bucket = self._makeOne(NAME, connection)
self.assertEqual(bucket.delete(force=True), None)
result = bucket.delete(force=True, connection=connection)
self.assertTrue(result is None)
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

Expand All @@ -367,7 +370,8 @@ def test_delete_explicit_force_miss_blobs(self):
connection = _Connection(GET_BLOBS_RESP)
connection._delete_bucket = True
bucket = self._makeOne(NAME, connection)
self.assertEqual(bucket.delete(force=True), None)
result = bucket.delete(force=True, connection=connection)
self.assertTrue(result is None)
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

Expand Down Expand Up @@ -395,8 +399,9 @@ def test_delete_blob_miss(self):
NAME = 'name'
NONESUCH = 'nonesuch'
connection = _Connection()
bucket = self._makeOne(NAME, connection)
self.assertRaises(NotFound, bucket.delete_blob, NONESUCH)
bucket = self._makeOne(NAME)
self.assertRaises(NotFound, bucket.delete_blob, NONESUCH,
connection=connection)
kw, = connection._requested
self.assertEqual(kw['method'], 'DELETE')
self.assertEqual(kw['path'], '/b/%s/o/%s' % (NAME, NONESUCH))
Expand All @@ -405,8 +410,8 @@ def test_delete_blob_hit(self):
NAME = 'name'
BLOB_NAME = 'blob-name'
connection = _Connection({})
bucket = self._makeOne(NAME, connection)
result = bucket.delete_blob(BLOB_NAME)
bucket = self._makeOne(NAME)
result = bucket.delete_blob(BLOB_NAME, connection=connection)
self.assertTrue(result is None)
kw, = connection._requested
self.assertEqual(kw['method'], 'DELETE')
Expand All @@ -423,8 +428,8 @@ def test_delete_blobs_hit(self):
NAME = 'name'
BLOB_NAME = 'blob-name'
connection = _Connection({})
bucket = self._makeOne(NAME, connection)
bucket.delete_blobs([BLOB_NAME])
bucket = self._makeOne(NAME)
bucket.delete_blobs([BLOB_NAME], connection=connection)
kw = connection._requested
self.assertEqual(len(kw), 1)
self.assertEqual(kw[0]['method'], 'DELETE')
Expand All @@ -436,8 +441,9 @@ def test_delete_blobs_miss_no_on_error(self):
BLOB_NAME = 'blob-name'
NONESUCH = 'nonesuch'
connection = _Connection({})
bucket = self._makeOne(NAME, connection)
self.assertRaises(NotFound, bucket.delete_blobs, [BLOB_NAME, NONESUCH])
bucket = self._makeOne(NAME)
self.assertRaises(NotFound, bucket.delete_blobs, [BLOB_NAME, NONESUCH],
connection=connection)
kw = connection._requested
self.assertEqual(len(kw), 2)
self.assertEqual(kw[0]['method'], 'DELETE')
Expand All @@ -450,9 +456,10 @@ def test_delete_blobs_miss_w_on_error(self):
BLOB_NAME = 'blob-name'
NONESUCH = 'nonesuch'
connection = _Connection({})
bucket = self._makeOne(NAME, connection)
bucket = self._makeOne(NAME)
errors = []
bucket.delete_blobs([BLOB_NAME, NONESUCH], errors.append)
bucket.delete_blobs([BLOB_NAME, NONESUCH], errors.append,
connection=connection)
self.assertEqual(errors, [NONESUCH])
kw = connection._requested
self.assertEqual(len(kw), 2)
Expand Down

0 comments on commit dd1ae8d

Please sign in to comment.