diff options
author | Jenkins <jenkins@review.openstack.org> | 2016-01-07 03:59:43 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2016-01-07 03:59:43 +0000 |
commit | f15918318c8b9f645ebc0b5fe672d10fce3e4d03 (patch) | |
tree | 84f3a90fcb5232a379c7d96d6f7736bbfa768168 | |
parent | 411ab2ef2d82fda170bac9b1ef74ed5706d4be77 (diff) | |
parent | c28d40814962b3a8ccb81e5e7d7f832c8f0a3c9a (diff) | |
download | python-keystoneclient-f15918318c8b9f645ebc0b5fe672d10fce3e4d03.tar.gz |
Merge "Support `truncated` flag returned by keystone"
-rw-r--r-- | keystoneclient/base.py | 22 | ||||
-rw-r--r-- | keystoneclient/tests/unit/v3/utils.py | 41 |
2 files changed, 55 insertions, 8 deletions
diff --git a/keystoneclient/base.py b/keystoneclient/base.py index e10d888..4dd16d7 100644 --- a/keystoneclient/base.py +++ b/keystoneclient/base.py @@ -20,6 +20,7 @@ Base utilities to build API operation managers and objects on top of. """ import abc +import collections import copy import functools import warnings @@ -76,6 +77,23 @@ def filter_kwargs(f): return func +class KeystoneReturnedList(collections.Sequence): + """A list of entities with additional attributes.""" + + def __init__(self, collection, truncated=False): + self.collection = collection + self.truncated = truncated + + def __getitem__(self, i): + return self.collection[i] + + def __len__(self): + return len(self.collection) + + def sort(self, *args, **kwargs): + return self.collection.sort(*args, **kwargs) + + class Manager(object): """Basic manager type providing common operations. @@ -127,6 +145,7 @@ class Manager(object): obj_class = self.resource_class data = body[response_key] + truncated = body.get('truncated', False) # NOTE(ja): keystone returns values as list as {'values': [ ... ]} # unlike other services which just return the list... try: @@ -134,7 +153,8 @@ class Manager(object): except (KeyError, TypeError): pass - return [obj_class(self, res, loaded=True) for res in data if res] + objects = [obj_class(self, res, loaded=True) for res in data if res] + return KeystoneReturnedList(objects, truncated=truncated) def _get(self, url, response_key, **kwargs): """Get an object from collection. diff --git a/keystoneclient/tests/unit/v3/utils.py b/keystoneclient/tests/unit/v3/utils.py index 2a02b49..d573608 100644 --- a/keystoneclient/tests/unit/v3/utils.py +++ b/keystoneclient/tests/unit/v3/utils.py @@ -196,11 +196,16 @@ class CrudTests(object): kwargs.setdefault(uuid.uuid4().hex, uuid.uuid4().hex) return kwargs - def encode(self, entity): + def encode(self, entity, truncated=None): + encoded = {} + if truncated is not None: + encoded['truncated'] = truncated if isinstance(entity, dict): - return {self.key: entity} + encoded[self.key] = entity + return encoded if isinstance(entity, list): - return {self.collection_key: entity} + encoded[self.collection_key] = entity + return encoded raise NotImplementedError('Are you sure you want to encode that?') def stub_entity(self, method, parts=None, entity=None, id=None, **kwargs): @@ -291,14 +296,22 @@ class CrudTests(object): self.assertRaises(TypeError, self.manager.list, **filter_kwargs) - def test_list(self, ref_list=None, expected_path=None, - expected_query=None, **filter_kwargs): + def _test_list(self, ref_list=None, expected_path=None, + expected_query=None, truncated=None, **filter_kwargs): ref_list = ref_list or [self.new_ref(), self.new_ref()] expected_path = self._get_expected_path(expected_path) - self.requests_mock.get(urlparse.urljoin(self.TEST_URL, expected_path), - json=self.encode(ref_list)) + # We want to catch all cases: when `truncated` is not returned by the + # server, when it's False and when it's True. + # Attribute `truncated` of the returned list-like object should exist + # in all these cases. It should be False if the server returned a list + # without the flag. + expected_truncated = False + if truncated: + expected_truncated = truncated + self.requests_mock.get(urlparse.urljoin(self.TEST_URL, expected_path), + json=self.encode(ref_list, truncated=truncated)) returned_list = self.manager.list(**filter_kwargs) self.assertEqual(len(ref_list), len(returned_list)) [self.assertIsInstance(r, self.model) for r in returned_list] @@ -317,6 +330,20 @@ class CrudTests(object): for key in qs_args: self.assertIn(key, qs_args_expected) + self.assertEqual(expected_truncated, returned_list.truncated) + + def test_list(self, ref_list=None, expected_path=None, + expected_query=None, **filter_kwargs): + # test simple list, without any truncation + self._test_list(ref_list, expected_path, expected_query, + **filter_kwargs) + # test when a server returned a list with truncated=False + self._test_list(ref_list, expected_path, expected_query, + truncated=False, **filter_kwargs) + # test when a server returned a list with truncated=True + self._test_list(ref_list, expected_path, expected_query, + truncated=True, **filter_kwargs) + def test_list_params(self): ref_list = [self.new_ref()] filter_kwargs = {uuid.uuid4().hex: uuid.uuid4().hex} |