This repository has been archived on 2022-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
python-usda/usda/pagination.py

175 lines
4.8 KiB
Python
Raw Permalink Normal View History

2018-07-12 06:44:47 +00:00
2018-07-13 11:14:23 +00:00
class RawPaginator(object):
2018-07-12 06:44:47 +00:00
"""
Generator to paginate over list results and return JSON data
"""
2018-07-13 11:14:23 +00:00
listkey = 'list'
2018-10-26 06:29:16 +00:00
"""
Key of the list description object in the response JSON.
See :class:`usda.pagination.RawNutrientReportPaginator`'s documentation
for more information.
:type: str
"""
2018-07-13 11:14:23 +00:00
itemkey = 'item'
2018-10-26 06:29:16 +00:00
"""
Key of the item list in the list description object of the response JSON.
See :class:`usda.pagination.RawNutrientReportPaginator`'s documentation
for more information.
:type: str
"""
2018-07-13 11:14:23 +00:00
2018-07-12 06:44:47 +00:00
def __init__(self, client, *request_args, **request_kwargs):
2018-10-26 06:29:16 +00:00
r"""
:param client: An API client to use for performing requests.
:type client: usda.base.DataGovClientBase
:param \*request_args: Arguments passed to the
:meth:`usda.base.DataGovClientBase.run_request` method.
:param \**request_kwargs: Keyword arguments passed to the
:meth:`usda.base.DataGovClientBase.run_request` method.
"""
2018-07-12 06:44:47 +00:00
self.client = client
2018-10-26 06:29:16 +00:00
"""
An API client to use for performing requests.
:type: usda.base.DataGovClientBase
"""
2018-07-12 06:44:47 +00:00
self.data = {}
2018-10-26 06:29:16 +00:00
"""
List description object returned from the last API request.
:type: dict
"""
2018-07-12 06:44:47 +00:00
self.request_args = request_args
2018-10-26 06:29:16 +00:00
"""
Arguments passed to the
:meth:`usda.base.DataGovClientBase.run_request` method.
:type: tuple
"""
2018-07-12 06:44:47 +00:00
self.request_kwargs = request_kwargs
2018-10-26 06:29:16 +00:00
"""
2018-10-26 13:51:34 +00:00
Keyword arguments passed to the
2018-10-26 06:29:16 +00:00
:meth:`usda.base.DataGovClientBase.run_request` method.
:type: dict(str, object)
"""
2019-04-26 06:22:52 +00:00
self.current_offset = request_kwargs.get('offset', 0)
2018-10-26 06:29:16 +00:00
"""
Offset of the current page; the first index of the item that is
returned in the current page.
:type: int
"""
2018-07-12 06:44:47 +00:00
self.max = request_kwargs.get('max', 30)
2018-10-26 06:29:16 +00:00
"""
The maximum number of items returned with each page.
:type: int
"""
2018-07-12 06:44:47 +00:00
def __iter__(self):
return self
def __next__(self):
2018-07-13 11:14:23 +00:00
if len(self.data.get(self.itemkey, [])) < 1:
if self.itemkey in self.data and \
self.current_offset >= self.data['end']:
2018-07-12 06:44:47 +00:00
raise StopIteration
self._fetch_next()
2018-07-13 11:14:23 +00:00
return self.data[self.itemkey].pop(0)
2018-07-12 06:44:47 +00:00
def _fetch_next(self):
self.request_kwargs['offset'] = self.current_offset
self.data = self.client.run_request(
2018-07-13 11:14:23 +00:00
*self.request_args, **self.request_kwargs)[self.listkey]
2018-07-12 06:44:47 +00:00
self.current_offset += self.max
2018-07-13 11:14:23 +00:00
class RawNutrientReportPaginator(RawPaginator):
2018-10-26 06:29:16 +00:00
"""
This class provides a way to handle Nutrient Reports; as those reports
are a list of food items containing specified nutrients, the endpoint is
paginated in a similar way as classic list endpoints.
Paginated responses are usually structured in the following way:
.. code:: json
{
"list": {
"start": "...",
"offset": "...",
"total": "...",
"item": []
}
}
``list`` holds all the list data; we call it the "list description object".
Inside this object, the ``item`` list is the list of items returned in
this page.
However, in Nutrient Reports, the paginated reponse uses ``report`` as the
list description object and ``foods`` as the food items list.
To solve this use case, this class changes the
:attr:`usda.pagination.RawPaginator.listkey` and
:attr:`usda.pagination.RawPaginator.itemkey` class attributes to make them
match those names.
"""
2018-07-13 11:14:23 +00:00
listkey = 'report'
2018-10-26 06:29:16 +00:00
"""
The nutrient report list description object's key.
:type: str
"""
2018-07-13 11:14:23 +00:00
itemkey = 'foods'
2018-10-26 06:29:16 +00:00
"""
The nutrient report list description object's item list's key.
"""
2018-07-13 11:14:23 +00:00
class ModelPaginator(object):
2018-07-12 06:44:47 +00:00
"""
2018-10-26 06:29:16 +00:00
Generator to paginate over list results and get custom models instead of
raw JSON data.
2018-07-12 06:44:47 +00:00
"""
def __init__(self, model, raw):
2018-10-26 06:29:16 +00:00
"""
:param model: Any class that implements a
``from_response_data(response_data)`` static method.
:param raw: A raw paginator to get raw JSON data from.
:type raw: usda.pagination.RawPaginator
"""
2018-07-13 11:14:23 +00:00
assert isinstance(raw, RawPaginator)
2018-07-12 06:44:47 +00:00
self.raw = raw
2018-10-26 06:29:16 +00:00
"""
A raw paginator used to fetch JSON data from.
:type: usda.pagination.RawPaginator
"""
self.model = model
"""
Any class that implements a ``from_response_data(response_data)``
static method and that will be used to return custom models.
"""
2018-07-12 06:44:47 +00:00
def __iter__(self):
return self
def __next__(self):
return self.model.from_response_data(next(self.raw))