From 43deb7fc11b4cdea239617bb8d5789de8f576d8d Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Fri, 13 Mar 2015 23:19:18 -0600 Subject: [PATCH] Using 'fields' in Blob.exists() to reduce payload size. --- gcloud/storage/blob.py | 11 ++++++++++- gcloud/storage/test_blob.py | 22 +++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/gcloud/storage/blob.py b/gcloud/storage/blob.py index 199744ab418e..d1146e8e5230 100644 --- a/gcloud/storage/blob.py +++ b/gcloud/storage/blob.py @@ -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 @@ -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. diff --git a/gcloud/storage/test_blob.py b/gcloud/storage/test_blob.py index 06e2551d72c6..4cee94ba9e8d 100644 --- a/gcloud/storage/test_blob.py +++ b/gcloud/storage/test_blob.py @@ -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 @@ -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 @@ -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): @@ -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,