Skip to content

Commit 6636714

Browse files
committed
Implementing basic Page class to help with Iterator.
Intended to hold and slice up state that has already been retrieved from the server.
1 parent afcafd8 commit 6636714

File tree

4 files changed

+128
-4
lines changed

4 files changed

+128
-4
lines changed

core/google/cloud/iterator.py

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,70 @@ def get_items_from_response(self, response):
3939
requests)::
4040
4141
>>> for item in MyIterator(...):
42-
>>> print(item.name)
43-
>>> if not item.is_valid:
44-
>>> break
42+
... print(item.name)
43+
... if not item.is_valid:
44+
... break
4545
"""
4646

4747

4848
import six
4949

5050

51+
class Page(object):
52+
"""Single page of results in an iterator.
53+
54+
:type parent: :class:`Iterator`
55+
:param parent: The iterator that owns the current page.
56+
"""
57+
58+
def __init__(self, parent):
59+
self._parent = parent
60+
self._num_items = 0
61+
self._remaining = 0
62+
63+
@property
64+
def num_items(self):
65+
"""Total items in the page.
66+
67+
:rtype: int
68+
:returns: The number of items in this page of items.
69+
"""
70+
return self._num_items
71+
72+
@property
73+
def remaining(self):
74+
"""Remaining items in the page.
75+
76+
:rtype: int
77+
:returns: The number of items remaining this page.
78+
"""
79+
return self._remaining
80+
81+
def __iter__(self):
82+
"""The :class:`Page` is an iterator."""
83+
return self
84+
85+
def _next_item(self):
86+
"""Get the next item in the page.
87+
88+
This method (along with the constructor) is the workhorse
89+
of this class. Subclasses will need to implement this method.
90+
91+
It is separate from :meth:`next` since that method needs
92+
to be aliased as ``__next__`` in Python 3.
93+
94+
:raises NotImplementedError: Always
95+
"""
96+
raise NotImplementedError
97+
98+
def next(self):
99+
"""Get the next value in the iterator."""
100+
return self._next_item()
101+
102+
# Alias needed for Python 2/3 support.
103+
__next__ = next
104+
105+
51106
class Iterator(object):
52107
"""A generic class for iterating through Cloud JSON APIs list responses.
53108

core/unit_tests/test_iterator.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,69 @@
1515
import unittest
1616

1717

18+
class TestPage(unittest.TestCase):
19+
20+
def _getTargetClass(self):
21+
from google.cloud.iterator import Page
22+
return Page
23+
24+
def _makeOne(self, *args, **kw):
25+
return self._getTargetClass()(*args, **kw)
26+
27+
def test_constructor(self):
28+
parent = object()
29+
page = self._makeOne(parent)
30+
self.assertIs(page._parent, parent)
31+
self.assertEqual(page._num_items, 0)
32+
self.assertEqual(page._remaining, 0)
33+
34+
def test_num_items_property(self):
35+
page = self._makeOne(None)
36+
num_items = 42
37+
page._num_items = num_items
38+
self.assertEqual(page.num_items, num_items)
39+
40+
def test_remaining_property(self):
41+
page = self._makeOne(None)
42+
remaining = 1337
43+
page._remaining = remaining
44+
self.assertEqual(page.remaining, remaining)
45+
46+
def test___iter__(self):
47+
page = self._makeOne(None)
48+
self.assertIs(iter(page), page)
49+
50+
def test__next_item_virtual(self):
51+
page = self._makeOne(None)
52+
with self.assertRaises(NotImplementedError):
53+
page._next_item()
54+
55+
def test_iterator_calls__next_item(self):
56+
import six
57+
58+
klass = self._getTargetClass()
59+
60+
class CountItPage(klass):
61+
62+
calls = 0
63+
values = None
64+
65+
def _next_item(self):
66+
self.calls += 1
67+
return self.values.pop(0)
68+
69+
page = CountItPage(None)
70+
page.values = [10, 11, 12]
71+
72+
self.assertEqual(page.calls, 0)
73+
self.assertEqual(six.next(page), 10)
74+
self.assertEqual(page.calls, 1)
75+
self.assertEqual(six.next(page), 11)
76+
self.assertEqual(page.calls, 2)
77+
self.assertEqual(six.next(page), 12)
78+
self.assertEqual(page.calls, 3)
79+
80+
1881
class TestIterator(unittest.TestCase):
1982

2083
def _getTargetClass(self):

docs/google-cloud-api.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,10 @@ Environment Variables
3636
.. automodule:: google.cloud.environment_vars
3737
:members:
3838
:show-inheritance:
39+
40+
Base Iterator Class
41+
~~~~~~~~~~~~~~~~~~~
42+
43+
.. automodule:: google.cloud.iterator
44+
:members:
45+
:show-inheritance:

scripts/verify_included_modules.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
'google.cloud.datastore.__init__',
3737
'google.cloud.dns.__init__',
3838
'google.cloud.error_reporting.__init__',
39-
'google.cloud.iterator',
4039
'google.cloud.language.__init__',
4140
'google.cloud.logging.__init__',
4241
'google.cloud.logging.handlers.__init__',

0 commit comments

Comments
 (0)