Skip to content

Commit 5f2329f

Browse files
feat(api): pagination properties added to response (has_more, next_offset)
1 parent f64f55b commit 5f2329f

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

.stats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 46
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cb38560915edce03abce2ae3ef5bc745489dbe9b6f80c2b4ff42edf8c2ff276d.yml
33
openapi_spec_hash: a869194d6c864ba28d79ec0105439c3e
4-
config_hash: 1f28d5c3c063f418ebd2799df1e4e781
4+
config_hash: ed56f95781ec9b2e73c97e1a66606071

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ first_page = await client.deployments.list(
182182
app_name="YOUR_APP",
183183
limit=2,
184184
)
185+
186+
print(
187+
f"the current start offset for this page: {first_page.next_offset}"
188+
) # => "the current start offset for this page: 1"
185189
for deployment in first_page.items:
186190
print(deployment.id)
187191

src/kernel/pagination.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from httpx import Response
77

8-
from ._utils import is_mapping
8+
from ._utils import is_mapping, maybe_coerce_boolean, maybe_coerce_integer
99
from ._models import BaseModel
1010
from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
1111

@@ -18,6 +18,8 @@
1818

1919
class 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

5062
class 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

Comments
 (0)