From cd7cb5d69077a02e2db7b6af58b76c0e351b208a Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Fri, 10 Jul 2015 17:48:08 -0700 Subject: [PATCH] Updating Blob.generate_signed_url to accept a client. Towards #952, removing connection from methods / constructors. --- gcloud/storage/blob.py | 17 ++++++++------ gcloud/storage/test_blob.py | 44 +++++++++++++++++++++---------------- system_tests/storage.py | 6 +++-- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/gcloud/storage/blob.py b/gcloud/storage/blob.py index 48dedf4093100..ad3970c6fa305 100644 --- a/gcloud/storage/blob.py +++ b/gcloud/storage/blob.py @@ -154,7 +154,7 @@ def public_url(self): quoted_name=quote(self.name, safe='')) def generate_signed_url(self, expiration, method='GET', - connection=None, credentials=None): + client=None, credentials=None): """Generates a signed URL for this blob. If you have a blob that you want to allow access to for a set @@ -171,10 +171,9 @@ def generate_signed_url(self, expiration, method='GET', :type method: string :param method: The HTTP verb that will be used when requesting the URL. - :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 the ``connection`` stored on the blob's bucket. :type credentials: :class:`oauth2client.client.OAuth2Credentials` or :class:`NoneType` @@ -183,14 +182,18 @@ def generate_signed_url(self, expiration, method='GET', :rtype: string :returns: A signed URL you can use to access the resource until expiration. + :raises: :class:`ValueError` if no credentials could be determined + from the arguments. """ resource = '/{bucket_name}/{quoted_name}'.format( bucket_name=self.bucket.name, quoted_name=quote(self.name, safe='')) if credentials is None: - connection = _require_connection(connection) - credentials = connection.credentials + if client is not None: + credentials = client.connection.credentials + else: + raise ValueError('Credentials could be determined.') return generate_signed_url( credentials, resource=resource, diff --git a/gcloud/storage/test_blob.py b/gcloud/storage/test_blob.py index 6203fb4be4b46..de8e4bb380442 100644 --- a/gcloud/storage/test_blob.py +++ b/gcloud/storage/test_blob.py @@ -146,37 +146,31 @@ def test_public_url_w_slash_in_name(self): blob.public_url, 'https://storage.googleapis.com/name/parent%2Fchild') - def _basic_generate_signed_url_helper(self, credentials=None): + def _basic_generate_signed_url_helper(self, credentials=None, + use_client=True): from gcloud._testing import _Monkey from gcloud.storage import blob as MUT BLOB_NAME = 'blob-name' EXPIRATION = '2014-10-16T20:34:37.000Z' connection = _Connection() + client = _Client(connection) bucket = _Bucket() blob = self._makeOne(BLOB_NAME, bucket=bucket) URI = ('http://example.com/abucket/a-blob-name?Signature=DEADBEEF' '&Expiration=2014-10-16T20:34:37.000Z') - _called_require = [] - - def mock_require(connection): - _called_require.append(connection) - return connection - SIGNER = _Signer() - with _Monkey(MUT, generate_signed_url=SIGNER, - _require_connection=mock_require): - signed_uri = blob.generate_signed_url(EXPIRATION, - connection=connection, - credentials=credentials) + with _Monkey(MUT, generate_signed_url=SIGNER): + if use_client: + signed_uri = blob.generate_signed_url(EXPIRATION, + client=client, + credentials=credentials) + else: + signed_uri = blob.generate_signed_url(EXPIRATION, + credentials=credentials) self.assertEqual(signed_uri, URI) - if credentials is None: - self.assertEqual(_called_require, [connection]) - else: - self.assertEqual(_called_require, []) - PATH = '/name/%s' % (BLOB_NAME,) if credentials is None: EXPECTED_ARGS = (_Connection.credentials,) @@ -190,6 +184,10 @@ def mock_require(connection): } self.assertEqual(SIGNER._signed, [(EXPECTED_ARGS, EXPECTED_KWARGS)]) + def test_generate_signed_url_w_no_creds(self): + with self.assertRaises(ValueError): + self._basic_generate_signed_url_helper(use_client=False) + def test_generate_signed_url_w_default_method(self): self._basic_generate_signed_url_helper() @@ -204,6 +202,7 @@ def test_generate_signed_url_w_slash_in_name(self): BLOB_NAME = 'parent/child' EXPIRATION = '2014-10-16T20:34:37.000Z' connection = _Connection() + client = _Client(connection) bucket = _Bucket() blob = self._makeOne(BLOB_NAME, bucket=bucket) URI = ('http://example.com/abucket/a-blob-name?Signature=DEADBEEF' @@ -212,7 +211,7 @@ def test_generate_signed_url_w_slash_in_name(self): SIGNER = _Signer() with _Monkey(MUT, generate_signed_url=SIGNER): signed_url = blob.generate_signed_url(EXPIRATION, - connection=connection) + client=client) self.assertEqual(signed_url, URI) EXPECTED_ARGS = (_Connection.credentials,) @@ -231,6 +230,7 @@ def test_generate_signed_url_w_explicit_method(self): BLOB_NAME = 'blob-name' EXPIRATION = '2014-10-16T20:34:37.000Z' connection = _Connection() + client = _Client(connection) bucket = _Bucket() blob = self._makeOne(BLOB_NAME, bucket=bucket) URI = ('http://example.com/abucket/a-blob-name?Signature=DEADBEEF' @@ -239,7 +239,7 @@ def test_generate_signed_url_w_explicit_method(self): SIGNER = _Signer() with _Monkey(MUT, generate_signed_url=SIGNER): signed_uri = blob.generate_signed_url(EXPIRATION, method='POST', - connection=connection) + client=client) self.assertEqual(signed_uri, URI) PATH = '/name/%s' % (BLOB_NAME,) @@ -1152,3 +1152,9 @@ def __call__(self, *args, **kwargs): self._signed.append((args, kwargs)) return ('http://example.com/abucket/a-blob-name?Signature=DEADBEEF' '&Expiration=%s' % kwargs.get('expiration')) + + +class _Client(object): + + def __init__(self, connection): + self.connection = connection diff --git a/system_tests/storage.py b/system_tests/storage.py index 96f6246e1f65d..b1d51791b439a 100644 --- a/system_tests/storage.py +++ b/system_tests/storage.py @@ -321,7 +321,8 @@ def tearDown(self): def test_create_signed_read_url(self): blob = storage.Blob(bucket=self.bucket, name='LogoToSign.jpg') expiration = int(time.time() + 5) - signed_url = blob.generate_signed_url(expiration, method='GET') + signed_url = blob.generate_signed_url(expiration, method='GET', + client=CLIENT) response, content = HTTP.request(signed_url, method='GET') self.assertEqual(response.status, 200) @@ -331,7 +332,8 @@ def test_create_signed_delete_url(self): blob = storage.Blob(bucket=self.bucket, name='LogoToSign.jpg') expiration = int(time.time() + 283473274) signed_delete_url = blob.generate_signed_url(expiration, - method='DELETE') + method='DELETE', + client=CLIENT) response, content = HTTP.request(signed_delete_url, method='DELETE') self.assertEqual(response.status, 204)