Skip to content

Commit

Permalink
Merge pull request #269 from dhermes/fix-cyclic-imports-storage
Browse files Browse the repository at this point in the history
Resolving cyclic imports in storage package.
  • Loading branch information
dhermes committed Oct 21, 2014
2 parents 41f97e1 + 8de933f commit fab0237
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 141 deletions.
27 changes: 26 additions & 1 deletion gcloud/storage/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
from gcloud.storage import exceptions
from gcloud.storage.acl import BucketACL
from gcloud.storage.acl import DefaultObjectACL
from gcloud.storage.iterator import KeyIterator
from gcloud.storage.iterator import Iterator
from gcloud.storage.key import Key
from gcloud.storage.key import KeyIterator


class Bucket(object):
Expand Down Expand Up @@ -637,3 +638,27 @@ def make_public(self, recursive=False, future=False):
for key in self:
key.get_acl().all().grant_read()
key.save_acl()


class BucketIterator(Iterator):
"""An iterator listing all buckets.
You shouldn't have to use this directly,
but instead should use the helper methods
on :class:`gcloud.storage.connection.Connection` objects.
:type connection: :class:`gcloud.storage.connection.Connection`
:param connection: The connection to use for querying the list of buckets.
"""

def __init__(self, connection):
super(BucketIterator, self).__init__(connection=connection, path='/b')

def get_items_from_response(self, response):
"""Factory method which yields :class:`.Bucket` items from a response.
:type response: dict
:param response: The JSON API response for a page of buckets.
"""
for item in response.get('items', []):
yield Bucket.from_dict(item, connection=self.connection)
2 changes: 1 addition & 1 deletion gcloud/storage/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from gcloud import connection
from gcloud.storage import exceptions
from gcloud.storage.bucket import Bucket
from gcloud.storage.iterator import BucketIterator
from gcloud.storage.bucket import BucketIterator


def _utcnow(): # pragma: NO COVER testing replaces
Expand Down
54 changes: 0 additions & 54 deletions gcloud/storage/iterator.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,60 +134,6 @@ def get_items_from_response(self, response):
raise NotImplementedError


class BucketIterator(Iterator):
"""An iterator listing all buckets.
You shouldn't have to use this directly,
but instead should use the helper methods
on :class:`gcloud.storage.connection.Connection` objects.
:type connection: :class:`gcloud.storage.connection.Connection`
:param connection: The connection to use for querying the list of buckets.
"""

def __init__(self, connection):
super(BucketIterator, self).__init__(connection=connection, path='/b')

def get_items_from_response(self, response):
"""Factory method which yields :class:`.Bucket` items from a response.
:type response: dict
:param response: The JSON API response for a page of buckets.
"""

from gcloud.storage.bucket import Bucket
for item in response.get('items', []):
yield Bucket.from_dict(item, connection=self.connection)


class KeyIterator(Iterator):
"""An iterator listing keys.
You shouldn't have to use this directly,
but instead should use the helper methods
on :class:`gcloud.storage.key.Key` objects.
:type bucket: :class:`gcloud.storage.bucket.Bucket`
:param bucket: The bucket from which to list keys.
"""

def __init__(self, bucket):
self.bucket = bucket
super(KeyIterator, self).__init__(
connection=bucket.connection, path=bucket.path + '/o')

def get_items_from_response(self, response):
"""Factory method, yields :class:`.storage.key.Key` items from response.
:type response: dict
:param response: The JSON API response for a page of keys.
"""

from gcloud.storage.key import Key
for item in response.get('items', []):
yield Key.from_dict(item, bucket=self.bucket)


class KeyDataIterator(object):
"""An iterator listing data stored in a key.
Expand Down
27 changes: 27 additions & 0 deletions gcloud/storage/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from StringIO import StringIO

from gcloud.storage.acl import ObjectACL
from gcloud.storage.iterator import Iterator
from gcloud.storage.iterator import KeyDataIterator


Expand Down Expand Up @@ -459,3 +460,29 @@ def make_public(self):
self.get_acl().all().grant_read()
self.save_acl()
return self


class KeyIterator(Iterator):
"""An iterator listing keys.
You shouldn't have to use this directly,
but instead should use the helper methods
on :class:`gcloud.storage.key.Key` objects.
:type bucket: :class:`gcloud.storage.bucket.Bucket`
:param bucket: The bucket from which to list keys.
"""

def __init__(self, bucket):
self.bucket = bucket
super(KeyIterator, self).__init__(
connection=bucket.connection, path=bucket.path + '/o')

def get_items_from_response(self, response):
"""Factory method, yields :class:`.storage.key.Key` items from response.
:type response: dict
:param response: The JSON API response for a page of keys.
"""
for item in response.get('items', []):
yield Key.from_dict(item, bucket=self.bucket)
40 changes: 38 additions & 2 deletions gcloud/storage/test_bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ def test_make_public_w_future(self):
def test_make_public_recursive(self):
from gcloud.storage.acl import _ACLEntity
from gcloud._testing import _Monkey
from gcloud.storage import iterator
from gcloud.storage import key
from gcloud.storage import bucket as MUT
_saved = []

Expand All @@ -863,7 +863,7 @@ def grant_read(self):
def save_acl(self):
_saved.append((self._bucket, self._name, self._granted))

class _KeyIterator(iterator.KeyIterator):
class _KeyIterator(key.KeyIterator):
def get_items_from_response(self, response):
for item in response.get('items', []):
yield _Key(self.bucket, item['name'])
Expand Down Expand Up @@ -892,6 +892,42 @@ def get_items_from_response(self, response):
self.assertEqual(kw[1]['query_params'], None)


class TestBucketIterator(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.storage.bucket import BucketIterator
return BucketIterator

def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)

def test_ctor(self):
connection = _Connection()
iterator = self._makeOne(connection)
self.assertTrue(iterator.connection is connection)
self.assertEqual(iterator.path, '/b')
self.assertEqual(iterator.page_number, 0)
self.assertEqual(iterator.next_page_token, None)

def test_get_items_from_response_empty(self):
connection = _Connection()
iterator = self._makeOne(connection)
self.assertEqual(list(iterator.get_items_from_response({})), [])

def test_get_items_from_response_non_empty(self):
from gcloud.storage.bucket import Bucket
KEY = 'key'
response = {'items': [{'name': KEY}]}
connection = _Connection()
iterator = self._makeOne(connection)
buckets = list(iterator.get_items_from_response(response))
self.assertEqual(len(buckets), 1)
bucket = buckets[0]
self.assertTrue(isinstance(bucket, Bucket))
self.assertTrue(bucket.connection is connection)
self.assertEqual(bucket.name, KEY)


class _Connection(object):
_delete_ok = False

Expand Down
83 changes: 0 additions & 83 deletions gcloud/storage/test_iterator.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,82 +118,6 @@ def test_get_items_from_response_raises_NotImplementedError(self):
iterator.get_items_from_response, object())


class TestBucketIterator(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.storage.iterator import BucketIterator
return BucketIterator

def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)

def test_ctor(self):
connection = _Connection()
iterator = self._makeOne(connection)
self.assertTrue(iterator.connection is connection)
self.assertEqual(iterator.path, '/b')
self.assertEqual(iterator.page_number, 0)
self.assertEqual(iterator.next_page_token, None)

def test_get_items_from_response_empty(self):
connection = _Connection()
iterator = self._makeOne(connection)
self.assertEqual(list(iterator.get_items_from_response({})), [])

def test_get_items_from_response_non_empty(self):
from gcloud.storage.bucket import Bucket
KEY = 'key'
response = {'items': [{'name': KEY}]}
connection = _Connection()
iterator = self._makeOne(connection)
buckets = list(iterator.get_items_from_response(response))
self.assertEqual(len(buckets), 1)
bucket = buckets[0]
self.assertTrue(isinstance(bucket, Bucket))
self.assertTrue(bucket.connection is connection)
self.assertEqual(bucket.name, KEY)


class TestKeyIterator(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.storage.iterator import KeyIterator
return KeyIterator

def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)

def test_ctor(self):
connection = _Connection()
bucket = _Bucket(connection)
iterator = self._makeOne(bucket)
self.assertTrue(iterator.bucket is bucket)
self.assertTrue(iterator.connection is connection)
self.assertEqual(iterator.path, '%s/o' % bucket.path)
self.assertEqual(iterator.page_number, 0)
self.assertEqual(iterator.next_page_token, None)

def test_get_items_from_response_empty(self):
connection = _Connection()
bucket = _Bucket(connection)
iterator = self._makeOne(bucket)
self.assertEqual(list(iterator.get_items_from_response({})), [])

def test_get_items_from_response_non_empty(self):
from gcloud.storage.key import Key
KEY = 'key'
response = {'items': [{'name': KEY}]}
connection = _Connection()
bucket = _Bucket(connection)
iterator = self._makeOne(bucket)
keys = list(iterator.get_items_from_response(response))
self.assertEqual(len(keys), 1)
key = keys[0]
self.assertTrue(isinstance(key, Key))
self.assertTrue(key.connection is connection)
self.assertEqual(key.name, KEY)


class TestKeyDataIterator(unittest2.TestCase):

def _getTargetClass(self):
Expand Down Expand Up @@ -389,13 +313,6 @@ def build_api_url(self, path, query_params=None):
return urlunsplit(('http', 'example.com', path, qs, ''))


class _Bucket(object):
path = '/b/name'

def __init__(self, connection):
self.connection = connection


class _Key(object):
CHUNK_SIZE = 10
path = '/b/name/o/key'
Expand Down
40 changes: 40 additions & 0 deletions gcloud/storage/test_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,46 @@ def test_make_public(self):
self.assertEqual(kw[0]['query_params'], {'projection': 'full'})


class TestKeyIterator(unittest2.TestCase):

def _getTargetClass(self):
from gcloud.storage.key import KeyIterator
return KeyIterator

def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)

def test_ctor(self):
connection = _Connection()
bucket = _Bucket(connection)
iterator = self._makeOne(bucket)
self.assertTrue(iterator.bucket is bucket)
self.assertTrue(iterator.connection is connection)
self.assertEqual(iterator.path, '%s/o' % bucket.path)
self.assertEqual(iterator.page_number, 0)
self.assertEqual(iterator.next_page_token, None)

def test_get_items_from_response_empty(self):
connection = _Connection()
bucket = _Bucket(connection)
iterator = self._makeOne(bucket)
self.assertEqual(list(iterator.get_items_from_response({})), [])

def test_get_items_from_response_non_empty(self):
from gcloud.storage.key import Key
KEY = 'key'
response = {'items': [{'name': KEY}]}
connection = _Connection()
bucket = _Bucket(connection)
iterator = self._makeOne(bucket)
keys = list(iterator.get_items_from_response(response))
self.assertEqual(len(keys), 1)
key = keys[0]
self.assertTrue(isinstance(key, Key))
self.assertTrue(key.connection is connection)
self.assertEqual(key.name, KEY)


class _Connection(object):
API_BASE_URL = 'http://example.com'

Expand Down

0 comments on commit fab0237

Please sign in to comment.