Skip to content

Commit

Permalink
Merge pull request #731 from dhermes/blob-exists-use-fields
Browse files Browse the repository at this point in the history
Using 'fields' in Blob.exists() to reduce payload size.
  • Loading branch information
dhermes committed Mar 17, 2015
2 parents 6d147c8 + 43deb7f commit c490b68
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
11 changes: 10 additions & 1 deletion gcloud/storage/blob.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from _gcloud_vendor.apitools.base.py import transfer

from gcloud.credentials import generate_signed_url
from gcloud.exceptions import NotFound
from gcloud.storage._helpers import _PropertyMixin
from gcloud.storage._helpers import _scalar_property
from gcloud.storage import _implicit_environ
Expand Down Expand Up @@ -174,7 +175,15 @@ def exists(self):
:rtype: boolean
:returns: True if the blob exists in Cloud Storage.
"""
return self.bucket.get_blob(self.name) is not None
try:
# We only need the status code (200 or not) so we seek to
# minimize the returned payload.
query_params = {'fields': 'name'}
self.connection.api_request(method='GET', path=self.path,
query_params=query_params)
return True
except NotFound:
return False

def rename(self, new_name):
"""Renames this blob using copy and delete operations.
Expand Down
22 changes: 15 additions & 7 deletions gcloud/storage/test_blob.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,19 @@ def test_generate_signed_url_w_explicit_method(self):
self.assertEqual(SIGNER._signed, [(EXPECTED_ARGS, EXPECTED_KWARGS)])

def test_exists_miss(self):
from six.moves.http_client import NOT_FOUND
NONESUCH = 'nonesuch'
connection = _Connection()
not_found_response = {'status': NOT_FOUND}
connection = _Connection(not_found_response)
bucket = _Bucket(connection)
blob = self._makeOne(NONESUCH, bucket=bucket)
self.assertFalse(blob.exists())

def test_exists_hit(self):
from six.moves.http_client import OK
BLOB_NAME = 'blob-name'
connection = _Connection()
found_response = {'status': OK}
connection = _Connection(found_response)
bucket = _Bucket(connection)
blob = self._makeOne(BLOB_NAME, bucket=bucket)
bucket._blobs[BLOB_NAME] = 1
Expand All @@ -245,8 +249,10 @@ def test_rename(self):
self.assertTrue(NEW_NAME in bucket._blobs)

def test_delete(self):
from six.moves.http_client import NOT_FOUND
BLOB_NAME = 'blob-name'
connection = _Connection()
not_found_response = {'status': NOT_FOUND}
connection = _Connection(not_found_response)
bucket = _Bucket(connection)
blob = self._makeOne(BLOB_NAME, bucket=bucket)
bucket._blobs[BLOB_NAME] = 1
Expand Down Expand Up @@ -1000,7 +1006,12 @@ def __init__(self, *responses):
self.http = _HTTP(*responses)

def api_request(self, **kw):
return self._respond(**kw)
from six.moves.http_client import NOT_FOUND
from gcloud.exceptions import NotFound
result = self._respond(**kw)
if result.get('status') == NOT_FOUND:
raise NotFound(result)
return result

def build_api_url(self, path, query_params=None,
api_base_url=API_BASE_URL, upload=False):
Expand Down Expand Up @@ -1031,9 +1042,6 @@ def __init__(self, connection):
self._blobs = {}
self._deleted = []

def get_blob(self, blob_name):
return self._blobs.get(blob_name)

def copy_blob(self, blob, destination_bucket, new_name):
destination_bucket._blobs[new_name] = self._blobs[blob.name]
return blob.__class__(None, bucket=destination_bucket,
Expand Down

0 comments on commit c490b68

Please sign in to comment.