Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing most remaining uses of self.connection in Bucket #843

Merged
merged 3 commits into from
May 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gcloud/storage/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def create_bucket(bucket_name, project=None, connection=None):
"""
connection = _require_connection(connection)
bucket = Bucket(bucket_name, connection=connection)
bucket.create(project)
bucket.create(project, connection=connection)
return bucket


Expand Down
98 changes: 77 additions & 21 deletions gcloud/storage/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from gcloud._helpers import get_default_project
from gcloud.exceptions import NotFound
from gcloud.storage._helpers import _PropertyMixin
from gcloud.storage._helpers import _require_connection
from gcloud.storage._helpers import _scalar_property
from gcloud.storage.acl import BucketACL
from gcloud.storage.acl import DefaultObjectACL
Expand Down Expand Up @@ -114,23 +115,29 @@ def __contains__(self, blob_name):
blob = Blob(blob_name, bucket=self)
return blob.exists()

def exists(self):
def exists(self, connection=None):
"""Determines whether or not this bucket exists.

: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: boolean
:returns: True if the bucket exists in Cloud Storage.
"""
connection = _require_connection(connection)
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)
connection.api_request(method='GET', path=self.path,
query_params=query_params)
return True
except NotFound:
return False

def create(self, project=None):
def create(self, project=None, connection=None):
"""Creates current bucket.

If the bucket already exists, will raise
Expand All @@ -142,19 +149,25 @@ def create(self, project=None):
:param project: Optional. The project to use when creating bucket.
If not provided, falls back to default.

: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.bucket.Bucket`
:returns: The newly created bucket.
:raises: :class:`EnvironmentError` if the project is not given and
can't be inferred.
"""
connection = _require_connection(connection)
if project is None:
project = get_default_project()
if project is None:
raise EnvironmentError('Project could not be inferred '
'from environment.')

query_params = {'project': project}
api_response = self.connection.api_request(
api_response = connection.api_request(
method='POST', path='/b', query_params=query_params,
data={'name': self.name})
self._set_properties(api_response)
Expand Down Expand Up @@ -198,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 @@ -214,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 @@ -291,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 @@ -310,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 @@ -326,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 @@ -353,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 @@ -375,22 +407,30 @@ 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)
else:
raise

def copy_blob(self, blob, destination_bucket, new_name=None):
@staticmethod
def copy_blob(blob, destination_bucket, new_name=None,
connection=None):
"""Copy the given blob to the given bucket, optionally with a new name.

:type blob: string or :class:`gcloud.storage.blob.Blob`
Expand All @@ -403,18 +443,24 @@ def copy_blob(self, blob, destination_bucket, new_name=None):
:type new_name: string
:param new_name: (optional) the new name for the copied file.

: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`
:returns: The new Blob.
"""
connection = _require_connection(connection)
if new_name is None:
new_name = blob.name
new_blob = Blob(bucket=destination_bucket, name=new_name)
api_path = blob.path + '/copyTo' + new_blob.path
copy_result = self.connection.api_request(method='POST', path=api_path)
copy_result = connection.api_request(method='POST', path=api_path)
new_blob._set_properties(copy_result)
return new_blob

def upload_file(self, filename, blob_name=None):
def upload_file(self, filename, blob_name=None, connection=None):
"""Shortcut method to upload a file into this bucket.

Use this method to quickly put a local file in Cloud Storage.
Expand Down Expand Up @@ -447,16 +493,21 @@ def upload_file(self, filename, blob_name=None):
of the bucket with the same name as on your local
file system.

: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:`Blob`
:returns: The updated Blob object.
"""
if blob_name is None:
blob_name = os.path.basename(filename)
blob = Blob(bucket=self, name=blob_name)
blob.upload_from_filename(filename)
blob.upload_from_filename(filename, connection=connection)
return blob

def upload_file_object(self, file_obj, blob_name=None):
def upload_file_object(self, file_obj, blob_name=None, connection=None):
"""Shortcut method to upload a file object into this bucket.

Use this method to quickly put a local file in Cloud Storage.
Expand Down Expand Up @@ -489,13 +540,18 @@ def upload_file_object(self, file_obj, blob_name=None):
of the bucket with the same name as on your local
file system.

: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:`Blob`
:returns: The updated Blob object.
"""
if blob_name is None:
blob_name = os.path.basename(file_obj.name)
blob = Blob(bucket=self, name=blob_name)
blob.upload_from_file(file_obj)
blob.upload_from_file(file_obj, connection=connection)
return blob

@property
Expand Down
Loading