From 118bb662f8f08c33cdd0a4d4c637b6a3ec91e0ff Mon Sep 17 00:00:00 2001 From: fderuiter <127706008+fderuiter@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:41:04 +0000 Subject: [PATCH 1/2] feat(core): harden paginator against invalid pagination fields - Update `BasePaginator._next_page` to validate that the `pagination` field in the API response is a dictionary. - Raise `TypeError` with a descriptive message if `pagination` is present but invalid (e.g., a string), preventing `AttributeError` crashes. - Add regression test `test_paginator_raises_type_error_on_invalid_pagination_field` in `tests/unit/test_paginator_robustness.py`. This change ensures the paginator fails gracefully with a meaningful error when the API returns an unexpected structure, aiding in debugging and preventing runtime crashes. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- imednet/core/paginator.py | 7 ++++++- tests/unit/test_paginator_robustness.py | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/imednet/core/paginator.py b/imednet/core/paginator.py index cefbd9bd..76914d03 100644 --- a/imednet/core/paginator.py +++ b/imednet/core/paginator.py @@ -47,7 +47,12 @@ def _extract_items(self, payload: Dict[str, Any]) -> list[Any]: return items def _next_page(self, payload: Dict[str, Any], page: int) -> Optional[int]: - pagination = payload.get("pagination") or {} + pagination = payload.get("pagination") + if pagination is not None and not isinstance(pagination, dict): + raise TypeError( + f"Response field 'pagination' must be a dictionary, got {type(pagination).__name__}" + ) + pagination = pagination or {} total_pages = pagination.get("totalPages") if total_pages is None or page >= total_pages - 1: return None diff --git a/tests/unit/test_paginator_robustness.py b/tests/unit/test_paginator_robustness.py index cea02859..75141abc 100644 --- a/tests/unit/test_paginator_robustness.py +++ b/tests/unit/test_paginator_robustness.py @@ -50,3 +50,20 @@ def test_paginator_raises_type_error_on_invalid_data_key(): with pytest.raises(TypeError, match="Expected a list of items"): list(paginator) + + +def test_paginator_raises_type_error_on_invalid_pagination_field(): + """ + Test that the Paginator raises a helpful TypeError when the pagination key in the response + is not a dictionary. + """ + # unexpected: 'pagination' is a string, not a dict + client = MockClient({ + "data": [{"id": 1}], + "pagination": "invalid_structure" + }) + paginator = Paginator(client, "/path") + + # Before the fix, this raises AttributeError because it tries to call .get() on a string + with pytest.raises(TypeError, match="Response field 'pagination' must be a dictionary"): + list(paginator) From 5a8204b5d7a810a45511c4538ee4fc3e0d3c9697 Mon Sep 17 00:00:00 2001 From: fderuiter <127706008+fderuiter@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:45:51 +0000 Subject: [PATCH 2/2] style: apply black formatting to test_paginator_robustness.py - Format `tests/unit/test_paginator_robustness.py` to comply with the project's `black` and `isort` configuration. - Fixes CI failure in 'Quality & Security' workflow. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- tests/unit/test_paginator_robustness.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/unit/test_paginator_robustness.py b/tests/unit/test_paginator_robustness.py index 75141abc..40922934 100644 --- a/tests/unit/test_paginator_robustness.py +++ b/tests/unit/test_paginator_robustness.py @@ -58,10 +58,7 @@ def test_paginator_raises_type_error_on_invalid_pagination_field(): is not a dictionary. """ # unexpected: 'pagination' is a string, not a dict - client = MockClient({ - "data": [{"id": 1}], - "pagination": "invalid_structure" - }) + client = MockClient({"data": [{"id": 1}], "pagination": "invalid_structure"}) paginator = Paginator(client, "/path") # Before the fix, this raises AttributeError because it tries to call .get() on a string