From c94cdeeddbbd0322fc2a137cb18ba0e3037433e7 Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Fri, 10 Jul 2015 18:49:16 -0700 Subject: [PATCH] Updating Blob.download* methods to accept a client. Towards #952, removing connection from methods / constructors. Also adding a temporary Blob._client_or_connection method to allow switching from an explicit client to an implicit connection. --- gcloud/storage/blob.py | 56 ++++++++++++++++++++++--------------- gcloud/storage/test_blob.py | 9 ++++-- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/gcloud/storage/blob.py b/gcloud/storage/blob.py index 2eb4578a0f331..7fed504904b5a 100644 --- a/gcloud/storage/blob.py +++ b/gcloud/storage/blob.py @@ -200,6 +200,24 @@ def generate_signed_url(self, expiration, method='GET', api_access_endpoint=_API_ACCESS_ENDPOINT, expiration=expiration, method=method) + @staticmethod + def _client_or_connection(client): + """Temporary method to get a connection from a client. + + If the client is null, gets the connection from the environment. + + :type client: :class:`gcloud.storage.client.Client` or ``NoneType`` + :param client: Optional. The client to use. If not passed, falls back + to default connection. + + :rtype: :class:`gcloud.storage.connection.Connection` + :returns: The connection determined from the ``client`` or environment. + """ + if client is None: + return _require_connection() + else: + return client.connection + def exists(self, client=None): """Determines whether or not this blob exists. @@ -210,10 +228,7 @@ def exists(self, client=None): :rtype: boolean :returns: True if the blob exists in Cloud Storage. """ - if client is None: - connection = _require_connection() - else: - connection = client.connection + connection = self._client_or_connection(client) try: # We only need the status code (200 or not) so we seek to # minimize the returned payload. @@ -275,20 +290,19 @@ def delete(self, connection=None): connection = _require_connection(connection) return self.bucket.delete_blob(self.name, connection=connection) - def download_to_file(self, file_obj, connection=None): + def download_to_file(self, file_obj, client=None): """Download the contents of this blob into a file-like object. :type file_obj: file :param file_obj: A file handle to which to write the blob's data. - :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. + :type client: :class:`gcloud.storage.client.Client` or ``NoneType`` + :param client: Optional. The client to use. If not passed, falls back + to default connection. :raises: :class:`gcloud.exceptions.NotFound` """ - connection = _require_connection(connection) + connection = self._client_or_connection(client) download_url = self.media_link # Use apitools 'Download' facility. @@ -307,39 +321,37 @@ def download_to_file(self, file_obj, connection=None): download.StreamInChunks(callback=lambda *args: None, finish_callback=lambda *args: None) - def download_to_filename(self, filename, connection=None): + def download_to_filename(self, filename, client=None): """Download the contents of this blob into a named file. :type filename: string :param filename: A filename to be passed to ``open``. - :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. + :type client: :class:`gcloud.storage.client.Client` or ``NoneType`` + :param client: Optional. The client to use. If not passed, falls back + to default connection. :raises: :class:`gcloud.exceptions.NotFound` """ with open(filename, 'wb') as file_obj: - self.download_to_file(file_obj, connection=connection) + self.download_to_file(file_obj, client=client) mtime = time.mktime(self.updated.timetuple()) os.utime(file_obj.name, (mtime, mtime)) - def download_as_string(self, connection=None): + def download_as_string(self, client=None): """Download the contents of this blob as a string. - :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. + :type client: :class:`gcloud.storage.client.Client` or ``NoneType`` + :param client: Optional. The client to use. If not passed, falls back + to default connection. :rtype: bytes :returns: The data stored in this blob. :raises: :class:`gcloud.exceptions.NotFound` """ string_buffer = BytesIO() - self.download_to_file(string_buffer, connection=connection) + self.download_to_file(string_buffer, client=client) return string_buffer.getvalue() def upload_from_file(self, file_obj, rewind=False, size=None, diff --git a/gcloud/storage/test_blob.py b/gcloud/storage/test_blob.py index 133b294aa5cd0..26ca67a2ebb14 100644 --- a/gcloud/storage/test_blob.py +++ b/gcloud/storage/test_blob.py @@ -355,6 +355,7 @@ def _download_to_file_helper(self, chunk_size=None): (chunk1_response, b'abc'), (chunk2_response, b'def'), ) + client = _Client(connection) bucket = _Bucket() MEDIA_LINK = 'http://example.com/media/' properties = {'mediaLink': MEDIA_LINK} @@ -363,7 +364,7 @@ def _download_to_file_helper(self, chunk_size=None): blob._CHUNK_SIZE_MULTIPLE = 1 blob.chunk_size = chunk_size fh = BytesIO() - blob.download_to_file(fh, connection=connection) + blob.download_to_file(fh, client=client) self.assertEqual(fh.getvalue(), b'abcdef') def test_download_to_file_default(self): @@ -387,6 +388,7 @@ def test_download_to_filename(self): (chunk1_response, b'abc'), (chunk2_response, b'def'), ) + client = _Client(connection) bucket = _Bucket() MEDIA_LINK = 'http://example.com/media/' properties = {'mediaLink': MEDIA_LINK, @@ -395,7 +397,7 @@ def test_download_to_filename(self): blob._CHUNK_SIZE_MULTIPLE = 1 blob.chunk_size = 3 with NamedTemporaryFile() as f: - blob.download_to_filename(f.name, connection=connection) + blob.download_to_filename(f.name, client=client) f.flush() with open(f.name, 'rb') as g: wrote = g.read() @@ -416,13 +418,14 @@ def test_download_as_string(self): (chunk1_response, b'abc'), (chunk2_response, b'def'), ) + client = _Client(connection) bucket = _Bucket() MEDIA_LINK = 'http://example.com/media/' properties = {'mediaLink': MEDIA_LINK} blob = self._makeOne(BLOB_NAME, bucket=bucket, properties=properties) blob._CHUNK_SIZE_MULTIPLE = 1 blob.chunk_size = 3 - fetched = blob.download_as_string(connection=connection) + fetched = blob.download_as_string(client=client) self.assertEqual(fetched, b'abcdef') def test_upload_from_file_size_failure(self):