Support listing non-paginated response bodies

We previously tried to discover whether or not a resource supported
pagination by making extra calls, and then another attempt was made to
separate the idea of paginated and unpaginated by making separate calls
and modifying Resource.page. We can instead pass in a pagination
parameter to list, defaulting to True, which remains the one call to
make in order to be yielded Resource objects.

Change-Id: Ie97ef5b43fcabef145ab2758082ae9f2f400a0ab
Related-Bug: 1410980
This commit is contained in:
Brian Curtin
2015-02-17 10:57:10 -06:00
parent 8379ad612e
commit d76624895c
2 changed files with 24 additions and 6 deletions

View File

@@ -706,8 +706,9 @@ class Resource(collections.MutableMapping):
self.delete_by_id(session, self.id, path_args=self)
@classmethod
def list(cls, session, limit=None, marker=None, path_args=None, **params):
"""Get a response that is a list of potentially paginated objects.
def list(cls, session, limit=None, marker=None, path_args=None,
paginated=False, **params):
"""Get a response that is a list of objects.
This method starts at ``limit`` and ``marker`` (both defaulting to
None), advances the marker to the last item received in each response,
@@ -726,6 +727,12 @@ class Resource(collections.MutableMapping):
:param dict path_args: A dictionary of arguments to construct
a compound URL.
See `How path_args are used`_ for details.
:param bool paginated: ``True`` if a GET to this resource returns
a paginated series of responses, or ``False``
if a GET returns only one page of data.
**When paginated is False only one
page of data will be returned regardless
of the API's support of pagination.**
:param dict params: Parameters to be passed into the underlying
:meth:`~openstack.session.Session.get` method.
@@ -759,7 +766,7 @@ class Resource(collections.MutableMapping):
yielded += 1
yield value
if limit and yielded < limit:
if not paginated or limit and yielded < limit:
more_data = False
@classmethod

View File

@@ -639,7 +639,8 @@ class ResourceTests(base.TestTransportBase):
json=json_body)
objs = resource_class.list(self.session, limit=1,
path_args=fake_arguments)
path_args=fake_arguments,
paginated=True)
objs = list(objs)
self.assertIn(marker, httpretty.last_request().path)
self.assertEqual(3, len(objs))
@@ -650,18 +651,28 @@ class ResourceTests(base.TestTransportBase):
self.assertEqual(fake_name, obj.name)
self.assertIsInstance(obj, FakeResource)
def test_list_bail_out(self):
def _test_list_call_count(self, paginated):
# Test that we've only made one call to receive all data
results = [fake_data.copy(), fake_data.copy(), fake_data.copy()]
body = mock.Mock(body={fake_resources: results})
attrs = {"get.return_value": body}
session = mock.Mock(**attrs)
list(FakeResource.list(session, limit=len(results) + 1,
path_args=fake_arguments))
path_args=fake_arguments,
paginated=paginated))
# Ensure we only made one call to complete this.
self.assertEqual(session.get.call_count, 1)
def test_list_bail_out(self):
# When we get less data than limit, make sure we made one call
self._test_list_call_count(True)
def test_list_nonpaginated(self):
# When we call with paginated=False, make sure we made one call
self._test_list_call_count(False)
def test_page(self):
session = mock.Mock()
session.get = mock.Mock()