diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 39c6d46d..62e0791f 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -2,6 +2,14 @@ Changelog ========= +2.3.7 (2024-12-06) +------------------------ + +* Fix for `#415 `_ + which caused an endless loop when making a request via `POST /listRecords`. + - `PR #416 `_, + `PR #417 `_ + 2.3.6 (2024-11-11) ------------------------ diff --git a/pyairtable/__init__.py b/pyairtable/__init__.py index 6437f636..bbb8fdab 100644 --- a/pyairtable/__init__.py +++ b/pyairtable/__init__.py @@ -1,4 +1,4 @@ -__version__ = "2.3.6" +__version__ = "2.3.7" from .api import Api, Base, Table from .api.enterprise import Enterprise diff --git a/pyairtable/api/api.py b/pyairtable/api/api.py index b6fb0c11..a4d98113 100644 --- a/pyairtable/api/api.py +++ b/pyairtable/api/api.py @@ -372,7 +372,7 @@ def _get_offset_field(response: Dict[str, Any]) -> Optional[str]: return if not (offset := _get_offset_field(response)): return - params = {**params, offset_field: offset} + options = {**options, offset_field: offset} def chunked(self, iterable: Sequence[T]) -> Iterator[Sequence[T]]: """ diff --git a/pyairtable/api/params.py b/pyairtable/api/params.py index 82e22938..8f0e029a 100644 --- a/pyairtable/api/params.py +++ b/pyairtable/api/params.py @@ -78,6 +78,9 @@ def field_names_to_sorting_dict(field_names: List[str]) -> List[Dict[str, str]]: # get webhook payloads "limit": "limit", "cursor": "cursor", + # get audit log events + "next": "next", + "previous": "previous", } diff --git a/tests/test_api_api.py b/tests/test_api_api.py index 6e5f32f7..22ceb952 100644 --- a/tests/test_api_api.py +++ b/tests/test_api_api.py @@ -116,6 +116,42 @@ def test_iterate_requests(api: Api, requests_mock): assert responses == [response["json"] for response in response_list] +def test_iterate_requests__post(api: Api, requests_mock): + url = "https://example.com" + # prepare a few pages of dummy responses + response_list = [ + {"json": {"page": 0, "offset": 1}}, + {"json": {"page": 1, "offset": 2}}, + {"json": {"page": 2}}, + ] + m = requests_mock.post(url, response_list=response_list) + # construct a request that will get converted from GET to POST + formula = "X" * (api.MAX_URL_LENGTH + 1) + pages = list( + api.iterate_requests( + "GET", + url=url, + fallback=("POST", url), + options={"formula": formula}, + ) + ) + # ensure we got the responses we expected + assert pages == [ + {"page": 0, "offset": 1}, + {"page": 1, "offset": 2}, + {"page": 2}, + ] + # ensure we made three POST requests + assert m.call_count == 3 + assert len(pages) == 3 + requests = [r.json() for r in m.request_history] + assert requests == [ + {"filterByFormula": formula}, + {"filterByFormula": formula, "offset": "1"}, + {"filterByFormula": formula, "offset": "2"}, + ] + + def test_iterate_requests__invalid_type(api: Api, requests_mock): url = "https://example.com" response_list = [{"json": {"page": n, "offset": n + 1}} for n in range(1, 3)]