Skip to content

Commit

Permalink
STORAGE: Removing Connection.delete_bucket.
Browse files Browse the repository at this point in the history
It was a simple one-liner only being used in one place.
  • Loading branch information
dhermes committed Mar 13, 2015
1 parent 341b479 commit dda6735
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 94 deletions.
10 changes: 5 additions & 5 deletions docs/_components/storage-getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,17 @@ bucket itself as an iterator::
Deleting a bucket
-----------------

You can delete a bucket using the :func:`delete_bucket
<gcloud.storage.connection.Connection.delete_bucket>` method::
You can delete a bucket using the
:meth:`delete <gcloud.storage.bucket.Bucket.delete>` method::

>>> connection.delete_bucket('my-bucket')
>>> bucket.delete()

Remember, the bucket you're deleting needs to be empty, otherwise you'll
get an error.
get an error (409 conflict).

If you have a full bucket, you can delete it this way::

>>> bucket = connection.delete_bucket('my-bucket', force=True)
>>> bucket.delete(force=True)

Listing available buckets
-------------------------
Expand Down
2 changes: 1 addition & 1 deletion gcloud/storage/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def delete(self, force=False):
# Ignore 404 errors on delete.
self.delete_blobs(blobs, on_error=lambda blob: None)

self.connection.delete_bucket(self.name)
self.connection.api_request(method='DELETE', path=self.path)

def delete_blob(self, blob):
"""Deletes a blob from the current bucket.
Expand Down
45 changes: 0 additions & 45 deletions gcloud/storage/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ class Connection(base_connection.Connection):
:class:`gcloud.storage.bucket.Bucket` and
:class:`gcloud.storage.blob.Blob`).
Methods for getting, creating and deleting individual buckets as well
as listing buckets associated with a project are defined here. This
corresponds to the "storage.buckets" resource in the API.
See :class:`gcloud.connection.Connection` for a full list of
parameters. This subclass differs only in needing a project
name (which you specify when creating a project in the Cloud
Expand All @@ -46,12 +42,6 @@ class Connection(base_connection.Connection):
>>> from gcloud import storage
>>> connection = storage.get_connection(project)
>>> bucket = connection.create_bucket('my-bucket-name')
You can then delete this bucket::
>>> bucket.delete()
>>> # or
>>> connection.delete_bucket(bucket.name)
"""

API_BASE_URL = base_connection.API_BASE_URL
Expand Down Expand Up @@ -280,38 +270,3 @@ def create_bucket(self, bucket_name):
response = self.api_request(method='POST', path='/b',
data={'name': bucket_name})
return Bucket(properties=response, connection=self)

def delete_bucket(self, bucket_name):
"""Delete a bucket.
You can use this method to delete a bucket by name.
>>> from gcloud import storage
>>> connection = storage.get_connection(project)
>>> connection.delete_bucket('my-bucket')
If the bucket doesn't exist, this will raise a
:class:`gcloud.exceptions.NotFound`::
>>> from gcloud.exceptions import NotFound
>>> try:
>>> connection.delete_bucket('my-bucket')
>>> except NotFound:
>>> print 'That bucket does not exist!'
If the bucket still has objects in it, this will raise a
:class:`gcloud.exceptions.Conflict`::
>>> from gcloud.exceptions import Conflict
>>> try:
>>> connection.delete_bucket('my-bucket')
>>> except Conflict:
>>> print 'That bucket is not empty!'
This implements "storage.buckets.delete".
:type bucket_name: string
:param bucket_name: The bucket name to delete.
"""
bucket_path = Bucket.path_helper(bucket_name)
self.api_request(method='DELETE', path=bucket_path)
3 changes: 0 additions & 3 deletions gcloud/storage/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,9 +386,6 @@ def api_request(self, method, path, query_params=None,
def create_bucket(self, name): # pragma: NO COVER
pass

def delete_bucket(self, name): # pragma: NO COVER
pass


class _Response(dict):

Expand Down
48 changes: 31 additions & 17 deletions gcloud/storage/test_bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,16 +331,18 @@ def test_delete_default_miss(self):
connection = _Connection()
bucket = self._makeOne(connection, NAME)
self.assertRaises(NotFound, bucket.delete)
self.assertEqual(connection._deleted, [NAME])
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

def test_delete_explicit_hit(self):
NAME = 'name'
GET_BLOBS_RESP = {'items': []}
connection = _Connection(GET_BLOBS_RESP)
connection._delete_ok = True
connection._delete_bucket = True
bucket = self._makeOne(connection, NAME)
self.assertEqual(bucket.delete(force=True), None)
self.assertEqual(connection._deleted, [NAME])
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

def test_delete_explicit_force_delete_blobs(self):
NAME = 'name'
Expand All @@ -355,21 +357,23 @@ def test_delete_explicit_force_delete_blobs(self):
DELETE_BLOB1_RESP = DELETE_BLOB2_RESP = {}
connection = _Connection(GET_BLOBS_RESP, DELETE_BLOB1_RESP,
DELETE_BLOB2_RESP)
connection._delete_ok = True
connection._delete_bucket = True
bucket = self._makeOne(connection, NAME)
self.assertEqual(bucket.delete(force=True), None)
self.assertEqual(connection._deleted, [NAME])
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

def test_delete_explicit_force_miss_blobs(self):
NAME = 'name'
BLOB_NAME = 'blob-name1'
GET_BLOBS_RESP = {'items': [{'name': BLOB_NAME}]}
# Note the connection does not have a response for the blob.
connection = _Connection(GET_BLOBS_RESP)
connection._delete_ok = True
connection._delete_bucket = True
bucket = self._makeOne(connection, NAME)
self.assertEqual(bucket.delete(force=True), None)
self.assertEqual(connection._deleted, [NAME])
expected_cw = [{'method': 'DELETE', 'path': bucket.path}]
self.assertEqual(connection._deleted_buckets, expected_cw)

def test_delete_explicit_too_many(self):
NAME = 'name'
Expand All @@ -382,12 +386,13 @@ def test_delete_explicit_too_many(self):
],
}
connection = _Connection(GET_BLOBS_RESP)
connection._delete_ok = True
connection._delete_bucket = True
bucket = self._makeOne(connection, NAME)

# Make the Bucket refuse to delete with 2 objects.
bucket._MAX_OBJECTS_FOR_BUCKET_DELETE = 1
self.assertRaises(ValueError, bucket.delete, force=True)
self.assertEqual(connection._deleted_buckets, [])

def test_delete_blob_miss(self):
from gcloud.exceptions import NotFound
Expand Down Expand Up @@ -1079,31 +1084,40 @@ def get_items_from_response(self, response):


class _Connection(object):
_delete_ok = False
_delete_bucket = False

def __init__(self, *responses):
self._responses = responses
self._requested = []
self._deleted = []
self._deleted_buckets = []

@staticmethod
def _is_bucket_path(path):
if not path.startswith('/b/'): # pragma: NO COVER
return False
# Now just ensure the path only has /b/ and one more segment.
return path.count('/') == 2

def api_request(self, **kw):
from gcloud.exceptions import NotFound
self._requested.append(kw)

method = kw.get('method')
path = kw.get('path', '')
if method == 'DELETE' and self._is_bucket_path(path):
self._deleted_buckets.append(kw)
if self._delete_bucket:
return
else:
raise NotFound('miss')

try:
response, self._responses = self._responses[0], self._responses[1:]
except:
raise NotFound('miss')
else:
return response

def delete_bucket(self, bucket):
from gcloud.exceptions import NotFound
self._deleted.append(bucket)
if not self._delete_ok:
raise NotFound('miss')
return True


class _Bucket(object):
path = '/b/name'
Expand Down
23 changes: 0 additions & 23 deletions gcloud/storage/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,29 +303,6 @@ def test_create_bucket_ok(self):
self.assertEqual(http._called_with['method'], 'POST')
self.assertEqual(http._called_with['uri'], URI)

def test_delete_bucket_defaults_miss(self):
_deleted_blobs = []

PROJECT = 'project'
BLOB_NAME = 'blob-name'
conn = self._makeOne(PROJECT)
URI = '/'.join([
conn.API_BASE_URL,
'storage',
conn.API_VERSION,
'b',
'%s?project=%s' % (BLOB_NAME, PROJECT),
])
http = conn._http = Http(
{'status': '200', 'content-type': 'application/json'},
'{}',
)

self.assertEqual(conn.delete_bucket(BLOB_NAME), None)
self.assertEqual(_deleted_blobs, [])
self.assertEqual(http._called_with['method'], 'DELETE')
self.assertEqual(http._called_with['uri'], URI)


class Http(object):

Expand Down

0 comments on commit dda6735

Please sign in to comment.