55
66from httpx import Response
77
8- from ._utils import is_mapping
8+ from ._utils import is_mapping , maybe_coerce_boolean , maybe_coerce_integer
99from ._models import BaseModel
1010from ._base_client import BasePage , PageInfo , BaseSyncPage , BaseAsyncPage
1111
1818
1919class SyncOffsetPagination (BaseSyncPage [_T ], BasePage [_T ], Generic [_T ]):
2020 items : List [_T ]
21+ has_more : Optional [bool ] = None
22+ next_offset : Optional [int ] = None
2123
2224 @override
2325 def _get_page_items (self ) -> List [_T ]:
@@ -26,14 +28,22 @@ def _get_page_items(self) -> List[_T]:
2628 return []
2729 return items
2830
31+ @override
32+ def has_next_page (self ) -> bool :
33+ has_more = self .has_more
34+ if has_more is not None and has_more is False :
35+ return False
36+
37+ return super ().has_next_page ()
38+
2939 @override
3040 def next_page_info (self ) -> Optional [PageInfo ]:
31- offset = self ._options . params . get ( "offset" ) or 0
32- if not isinstance ( offset , int ) :
33- raise ValueError ( f'Expected "offset" param to be an integer but got { offset } ' )
41+ next_offset = self .next_offset
42+ if next_offset is None :
43+ return None # type: ignore[unreachable]
3444
3545 length = len (self ._get_page_items ())
36- current_count = offset + length
46+ current_count = next_offset + length
3747
3848 return PageInfo (params = {"offset" : current_count })
3949
@@ -43,12 +53,16 @@ def build(cls: Type[_BaseModelT], *, response: Response, data: object) -> _BaseM
4353 None ,
4454 ** {
4555 ** (cast (Mapping [str , Any ], data ) if is_mapping (data ) else {"items" : data }),
56+ "has_more" : maybe_coerce_boolean (response .headers .get ("X-Has-More" )),
57+ "next_offset" : maybe_coerce_integer (response .headers .get ("X-Next-Offset" )),
4658 },
4759 )
4860
4961
5062class AsyncOffsetPagination (BaseAsyncPage [_T ], BasePage [_T ], Generic [_T ]):
5163 items : List [_T ]
64+ has_more : Optional [bool ] = None
65+ next_offset : Optional [int ] = None
5266
5367 @override
5468 def _get_page_items (self ) -> List [_T ]:
@@ -57,14 +71,22 @@ def _get_page_items(self) -> List[_T]:
5771 return []
5872 return items
5973
74+ @override
75+ def has_next_page (self ) -> bool :
76+ has_more = self .has_more
77+ if has_more is not None and has_more is False :
78+ return False
79+
80+ return super ().has_next_page ()
81+
6082 @override
6183 def next_page_info (self ) -> Optional [PageInfo ]:
62- offset = self ._options . params . get ( "offset" ) or 0
63- if not isinstance ( offset , int ) :
64- raise ValueError ( f'Expected "offset" param to be an integer but got { offset } ' )
84+ next_offset = self .next_offset
85+ if next_offset is None :
86+ return None # type: ignore[unreachable]
6587
6688 length = len (self ._get_page_items ())
67- current_count = offset + length
89+ current_count = next_offset + length
6890
6991 return PageInfo (params = {"offset" : current_count })
7092
@@ -74,5 +96,7 @@ def build(cls: Type[_BaseModelT], *, response: Response, data: object) -> _BaseM
7496 None ,
7597 ** {
7698 ** (cast (Mapping [str , Any ], data ) if is_mapping (data ) else {"items" : data }),
99+ "has_more" : maybe_coerce_boolean (response .headers .get ("X-Has-More" )),
100+ "next_offset" : maybe_coerce_integer (response .headers .get ("X-Next-Offset" )),
77101 },
78102 )
0 commit comments