Skip to content

Commit 55cfd5c

Browse files
committed
Rename key iterators to indicate they are implementation details of Key.
Rename 'key.KeyIterator' -> 'key._KeyIterator' Move / rename 'iterator.KeyDataIterator' -> 'key._KeyDataIterator'. Fixes #244.
1 parent d4c46af commit 55cfd5c

File tree

6 files changed

+288
-301
lines changed

6 files changed

+288
-301
lines changed

gcloud/storage/bucket.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from gcloud.storage.acl import DefaultObjectACL
88
from gcloud.storage.iterator import Iterator
99
from gcloud.storage.key import Key
10-
from gcloud.storage.key import KeyIterator
10+
from gcloud.storage.key import _KeyIterator
1111

1212

1313
class Bucket(object):
@@ -46,7 +46,7 @@ def __repr__(self):
4646
return '<Bucket: %s>' % self.name
4747

4848
def __iter__(self):
49-
return iter(KeyIterator(bucket=self))
49+
return iter(_KeyIterator(bucket=self))
5050

5151
def __contains__(self, key):
5252
return self.get_key(key) is not None

gcloud/storage/iterator.py

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ def get_items_from_response(self, response):
2828
>>> break
2929
"""
3030

31-
from gcloud.storage.exceptions import StorageError
32-
3331

3432
class Iterator(object):
3533
"""A generic class for iterating through Cloud Storage list responses.
@@ -113,97 +111,3 @@ def get_items_from_response(self, response):
113111
:returns: Items that the iterator should yield.
114112
"""
115113
raise NotImplementedError
116-
117-
118-
class KeyDataIterator(object):
119-
"""An iterator listing data stored in a key.
120-
121-
You shouldn't have to use this directly, but instead should use the
122-
helper methods on :class:`gcloud.storage.key.Key` objects.
123-
124-
:type key: :class:`gcloud.storage.key.Key`
125-
:param key: The key from which to list data..
126-
"""
127-
128-
def __init__(self, key):
129-
self.key = key
130-
# NOTE: These variables will be initialized by reset().
131-
self._bytes_written = None
132-
self._total_bytes = None
133-
self.reset()
134-
135-
def __iter__(self):
136-
while self.has_more_data():
137-
yield self.get_next_chunk()
138-
139-
def reset(self):
140-
"""Resets the iterator to the beginning."""
141-
self._bytes_written = 0
142-
self._total_bytes = None
143-
144-
def has_more_data(self):
145-
"""Determines whether or not this iterator has more data to read.
146-
147-
:rtype: bool
148-
:returns: Whether the iterator has more data or not.
149-
"""
150-
if self._bytes_written == 0:
151-
return True
152-
elif not self._total_bytes:
153-
# self._total_bytes **should** be set by this point.
154-
# If it isn't, something is wrong.
155-
raise ValueError('Size of object is unknown.')
156-
else:
157-
return self._bytes_written < self._total_bytes
158-
159-
def get_headers(self):
160-
"""Gets range header(s) for next chunk of data.
161-
162-
:rtype: dict
163-
:returns: A dictionary of query parameters.
164-
"""
165-
start = self._bytes_written
166-
end = self._bytes_written + self.key.CHUNK_SIZE - 1
167-
168-
if self._total_bytes and end > self._total_bytes:
169-
end = ''
170-
171-
return {'Range': 'bytes=%s-%s' % (start, end)}
172-
173-
def get_url(self):
174-
"""Gets URL to read next chunk of data.
175-
176-
:rtype: string
177-
:returns: A URL.
178-
"""
179-
return self.key.connection.build_api_url(
180-
path=self.key.path, query_params={'alt': 'media'})
181-
182-
def get_next_chunk(self):
183-
"""Gets the next chunk of data.
184-
185-
Uses CHUNK_SIZE to determine how much data to get.
186-
187-
:rtype: string
188-
:returns: The chunk of data read from the key.
189-
:raises: :class:`RuntimeError` if no more data or
190-
:class:`gcloud.storage.exceptions.StorageError` in the
191-
case of an unexpected response status code.
192-
"""
193-
if not self.has_more_data():
194-
raise RuntimeError('No more data in this iterator. Try resetting.')
195-
196-
response, content = self.key.connection.make_request(
197-
method='GET', url=self.get_url(), headers=self.get_headers())
198-
199-
if response.status in (200, 206):
200-
self._bytes_written += len(content)
201-
202-
if 'content-range' in response:
203-
content_range = response['content-range']
204-
self._total_bytes = int(content_range.rsplit('/', 1)[1])
205-
206-
return content
207-
208-
# Expected a 200 or a 206. Got something else, which is unknown.
209-
raise StorageError(response)

gcloud/storage/key.py

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from StringIO import StringIO
66

77
from gcloud.storage.acl import ObjectACL
8+
from gcloud.storage.exceptions import StorageError
89
from gcloud.storage.iterator import Iterator
9-
from gcloud.storage.iterator import KeyDataIterator
1010

1111

1212
class Key(object):
@@ -170,7 +170,7 @@ def get_contents_to_file(self, file_obj):
170170
171171
:raises: :class:`gcloud.storage.exceptions.NotFoundError`
172172
"""
173-
for chunk in KeyDataIterator(self):
173+
for chunk in _KeyDataIterator(self):
174174
file_obj.write(chunk)
175175

176176
def get_contents_to_filename(self, filename):
@@ -433,7 +433,7 @@ def make_public(self):
433433
return self
434434

435435

436-
class KeyIterator(Iterator):
436+
class _KeyIterator(Iterator):
437437
"""An iterator listing keys.
438438
439439
You shouldn't have to use this directly, but instead should use the
@@ -444,7 +444,7 @@ class KeyIterator(Iterator):
444444
"""
445445
def __init__(self, bucket):
446446
self.bucket = bucket
447-
super(KeyIterator, self).__init__(
447+
super(_KeyIterator, self).__init__(
448448
connection=bucket.connection, path=bucket.path + '/o')
449449

450450
def get_items_from_response(self, response):
@@ -455,3 +455,97 @@ def get_items_from_response(self, response):
455455
"""
456456
for item in response.get('items', []):
457457
yield Key.from_dict(item, bucket=self.bucket)
458+
459+
460+
class _KeyDataIterator(object):
461+
"""An iterator listing data stored in a key.
462+
463+
You shouldn't have to use this directly, but instead should use the
464+
helper methods on :class:`gcloud.storage.key.Key` objects.
465+
466+
:type key: :class:`gcloud.storage.key.Key`
467+
:param key: The key from which to list data..
468+
"""
469+
470+
def __init__(self, key):
471+
self.key = key
472+
# NOTE: These variables will be initialized by reset().
473+
self._bytes_written = None
474+
self._total_bytes = None
475+
self.reset()
476+
477+
def __iter__(self):
478+
while self.has_more_data():
479+
yield self.get_next_chunk()
480+
481+
def reset(self):
482+
"""Resets the iterator to the beginning."""
483+
self._bytes_written = 0
484+
self._total_bytes = None
485+
486+
def has_more_data(self):
487+
"""Determines whether or not this iterator has more data to read.
488+
489+
:rtype: bool
490+
:returns: Whether the iterator has more data or not.
491+
"""
492+
if self._bytes_written == 0:
493+
return True
494+
elif not self._total_bytes:
495+
# self._total_bytes **should** be set by this point.
496+
# If it isn't, something is wrong.
497+
raise ValueError('Size of object is unknown.')
498+
else:
499+
return self._bytes_written < self._total_bytes
500+
501+
def get_headers(self):
502+
"""Gets range header(s) for next chunk of data.
503+
504+
:rtype: dict
505+
:returns: A dictionary of query parameters.
506+
"""
507+
start = self._bytes_written
508+
end = self._bytes_written + self.key.CHUNK_SIZE - 1
509+
510+
if self._total_bytes and end > self._total_bytes:
511+
end = ''
512+
513+
return {'Range': 'bytes=%s-%s' % (start, end)}
514+
515+
def get_url(self):
516+
"""Gets URL to read next chunk of data.
517+
518+
:rtype: string
519+
:returns: A URL.
520+
"""
521+
return self.key.connection.build_api_url(
522+
path=self.key.path, query_params={'alt': 'media'})
523+
524+
def get_next_chunk(self):
525+
"""Gets the next chunk of data.
526+
527+
Uses CHUNK_SIZE to determine how much data to get.
528+
529+
:rtype: string
530+
:returns: The chunk of data read from the key.
531+
:raises: :class:`RuntimeError` if no more data or
532+
:class:`gcloud.storage.exceptions.StorageError` in the
533+
case of an unexpected response status code.
534+
"""
535+
if not self.has_more_data():
536+
raise RuntimeError('No more data in this iterator. Try resetting.')
537+
538+
response, content = self.key.connection.make_request(
539+
method='GET', url=self.get_url(), headers=self.get_headers())
540+
541+
if response.status in (200, 206):
542+
self._bytes_written += len(content)
543+
544+
if 'content-range' in response:
545+
content_range = response['content-range']
546+
self._total_bytes = int(content_range.rsplit('/', 1)[1])
547+
548+
return content
549+
550+
# Expected a 200 or a 206. Got something else, which is unknown.
551+
raise StorageError(response)

gcloud/storage/test_bucket.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ def grant_read(self):
863863
def save_acl(self):
864864
_saved.append((self._bucket, self._name, self._granted))
865865

866-
class _KeyIterator(key.KeyIterator):
866+
class _KeyIterator(key._KeyIterator):
867867
def get_items_from_response(self, response):
868868
for item in response.get('items', []):
869869
yield _Key(self.bucket, item['name'])
@@ -875,7 +875,7 @@ def get_items_from_response(self, response):
875875
after = {'acl': permissive, 'defaultObjectAcl': []}
876876
connection = _Connection(after, {'items': [{'name': KEY}]})
877877
bucket = self._makeOne(connection, NAME, before)
878-
with _Monkey(MUT, KeyIterator=_KeyIterator):
878+
with _Monkey(MUT, _KeyIterator=_KeyIterator):
879879
bucket.make_public(recursive=True)
880880
self.assertEqual(bucket.metadata, after)
881881
self.assertEqual(list(bucket.acl), after['acl'])

0 commit comments

Comments
 (0)