From 405338d23899f1511cfd0c4360faae3a26beee11 Mon Sep 17 00:00:00 2001 From: biryukov Date: Thu, 18 Jul 2024 22:41:22 +0300 Subject: [PATCH] fix pagination --- bitrix24/bitrix24.py | 17 +++++++++++++---- tests/test_pagination.py | 23 +++++++++++++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/bitrix24/bitrix24.py b/bitrix24/bitrix24.py index d09dbb5..d44be34 100644 --- a/bitrix24/bitrix24.py +++ b/bitrix24/bitrix24.py @@ -115,7 +115,7 @@ async def request(self, method: str, params: str = None) -> Dict[str, Any]: return response async def _call( - self, method: str, params: Dict[str, Any] = None, start: int = 0 + self, method: str, params: Dict[str, Any] = None, start: int = 0 ) -> Dict[str, Any]: """Async call a REST method with specified parameters. @@ -133,12 +133,21 @@ async def _call( res = await self.request(method, payload) if "next" in res and not start and self._fetch_all_pages: + if res["total"] % 50 == 0: + count_tasks = res["total"] // 50 - 1 + else: + count_tasks = res["total"] // 50 + tasks = [ - self._call(method, params, (s + 1) * 50) for s in range(res["total"] // 50 - 1) + self._call(method, params, (s + 1) * 50) for s in range(count_tasks) ] items = await asyncio.gather(*tasks) - result = list(itertools.chain(*items)) - return res["result"] + result + if type(res["result"]) is not dict: + return res["result"] + list(itertools.chain(*items)) + if items: + key = list(res["result"].keys())[0] + for item in items: + res["result"][key] += item[key] return res["result"] def callMethod(self, method: str, params: Dict[str, Any] = None, **kwargs) -> Dict[str, Any]: diff --git a/tests/test_pagination.py b/tests/test_pagination.py index 8c50347..386fffc 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -8,13 +8,13 @@ async def test_concurrent_requests(b24): with aioresponses() as m: m.get( "https://example.bitrix24.com/rest/1/123456789/crm.deal.list.json?start=0", - payload={"result": [{"ID": 1}], "next": 50, "total": 100}, + payload={"result": [{"ID": 1}], "next": 50, "total": 82}, status=200, repeat=True, ) m.get( "https://example.bitrix24.com/rest/1/123456789/crm.deal.list.json?start=50", - payload={"result": [{"ID": 2}], "total": 100}, + payload={"result": [{"ID": 2}], "total": 82}, status=200, repeat=True, ) @@ -22,6 +22,25 @@ async def test_concurrent_requests(b24): assert res == [{"ID": 1}, {"ID": 2}] +@pytest.mark.asyncio +async def test_concurrent_requests_nesting_level(b24): + with aioresponses() as m: + m.get( + "https://example.bitrix24.com/rest/1/123456789/tasks.task.list.json?start=0", + payload={"result": {"tasks": [{"ID": 1}]}, "next": 50, "total": 100}, + status=200, + repeat=True, + ) + m.get( + "https://example.bitrix24.com/rest/1/123456789/tasks.task.list.json?start=50", + payload={"result": {"tasks": [{"ID": 2}]}, "total": 100}, + status=200, + repeat=True, + ) + res = await b24.callMethod("tasks.task.list") + assert res == {"tasks": [{"ID": 1}, {"ID": 2}]} + + @pytest.mark.asyncio async def test_request_with_disabled_pagination(): b24 = Bitrix24("https://example.bitrix24.com/rest/1/123456789", fetch_all_pages=False)