Skip to content

Commit 55c3324

Browse files
feat: api: paginate GET /extensions
1 parent c25d693 commit 55c3324

7 files changed

Lines changed: 118 additions & 30 deletions

File tree

.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 117
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e5524e6eeeedc614c05bf19896f1ce6c4f8a113de85c02952d6874d579651f70.yml
3-
openapi_spec_hash: 7815a189a50e6aa9e283213cc78d041c
4-
config_hash: 453b25a35834fd59a55a2315d1d50746
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9a76e7a837ac9ffbe0e9557d618ce9b676e052249e364e516c28ddb33b912019.yml
3+
openapi_spec_hash: c0e5412cc95139f11a8b8635559bb985
4+
config_hash: 098a7f3fd134c8e4cbd3a44750892a18

api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ from kernel.types import ExtensionListResponse, ExtensionUploadResponse
338338

339339
Methods:
340340

341-
- <code title="get /extensions">client.extensions.<a href="./src/kernel/resources/extensions.py">list</a>() -> <a href="./src/kernel/types/extension_list_response.py">ExtensionListResponse</a></code>
341+
- <code title="get /extensions">client.extensions.<a href="./src/kernel/resources/extensions.py">list</a>(\*\*<a href="src/kernel/types/extension_list_params.py">params</a>) -> <a href="./src/kernel/types/extension_list_response.py">SyncOffsetPagination[ExtensionListResponse]</a></code>
342342
- <code title="delete /extensions/{id_or_name}">client.extensions.<a href="./src/kernel/resources/extensions.py">delete</a>(id_or_name) -> None</code>
343343
- <code title="get /extensions/{id_or_name}">client.extensions.<a href="./src/kernel/resources/extensions.py">download</a>(id_or_name) -> BinaryAPIResponse</code>
344344
- <code title="get /extensions/from_chrome_store">client.extensions.<a href="./src/kernel/resources/extensions.py">download_from_chrome_store</a>(\*\*<a href="src/kernel/types/extension_download_from_chrome_store_params.py">params</a>) -> BinaryAPIResponse</code>

src/kernel/resources/extensions.py

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import httpx
99

10-
from ..types import extension_upload_params, extension_download_from_chrome_store_params
10+
from ..types import extension_list_params, extension_upload_params, extension_download_from_chrome_store_params
1111
from .._files import deepcopy_with_paths
1212
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, omit, not_given
1313
from .._utils import extract_files, path_template, maybe_transform, async_maybe_transform
@@ -27,7 +27,8 @@
2727
async_to_custom_raw_response_wrapper,
2828
async_to_custom_streamed_response_wrapper,
2929
)
30-
from .._base_client import make_request_options
30+
from ..pagination import SyncOffsetPagination, AsyncOffsetPagination
31+
from .._base_client import AsyncPaginator, make_request_options
3132
from ..types.extension_list_response import ExtensionListResponse
3233
from ..types.extension_upload_response import ExtensionUploadResponse
3334

@@ -59,20 +60,48 @@ def with_streaming_response(self) -> ExtensionsResourceWithStreamingResponse:
5960
def list(
6061
self,
6162
*,
63+
limit: int | Omit = omit,
64+
offset: int | Omit = omit,
6265
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
6366
# The extra values given here take precedence over values defined on the client or passed to this method.
6467
extra_headers: Headers | None = None,
6568
extra_query: Query | None = None,
6669
extra_body: Body | None = None,
6770
timeout: float | httpx.Timeout | None | NotGiven = not_given,
68-
) -> ExtensionListResponse:
69-
"""List extensions owned by the caller's organization."""
70-
return self._get(
71+
) -> SyncOffsetPagination[ExtensionListResponse]:
72+
"""
73+
List extensions owned by the caller's organization.
74+
75+
Args:
76+
limit: Limit the number of extensions to return.
77+
78+
offset: Offset the number of extensions to return.
79+
80+
extra_headers: Send extra headers
81+
82+
extra_query: Add additional query parameters to the request
83+
84+
extra_body: Add additional JSON properties to the request
85+
86+
timeout: Override the client-level default timeout for this request, in seconds
87+
"""
88+
return self._get_api_list(
7189
"/extensions",
90+
page=SyncOffsetPagination[ExtensionListResponse],
7291
options=make_request_options(
73-
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
92+
extra_headers=extra_headers,
93+
extra_query=extra_query,
94+
extra_body=extra_body,
95+
timeout=timeout,
96+
query=maybe_transform(
97+
{
98+
"limit": limit,
99+
"offset": offset,
100+
},
101+
extension_list_params.ExtensionListParams,
102+
),
74103
),
75-
cast_to=ExtensionListResponse,
104+
model=ExtensionListResponse,
76105
)
77106

78107
def delete(
@@ -266,23 +295,51 @@ def with_streaming_response(self) -> AsyncExtensionsResourceWithStreamingRespons
266295
"""
267296
return AsyncExtensionsResourceWithStreamingResponse(self)
268297

269-
async def list(
298+
def list(
270299
self,
271300
*,
301+
limit: int | Omit = omit,
302+
offset: int | Omit = omit,
272303
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
273304
# The extra values given here take precedence over values defined on the client or passed to this method.
274305
extra_headers: Headers | None = None,
275306
extra_query: Query | None = None,
276307
extra_body: Body | None = None,
277308
timeout: float | httpx.Timeout | None | NotGiven = not_given,
278-
) -> ExtensionListResponse:
279-
"""List extensions owned by the caller's organization."""
280-
return await self._get(
309+
) -> AsyncPaginator[ExtensionListResponse, AsyncOffsetPagination[ExtensionListResponse]]:
310+
"""
311+
List extensions owned by the caller's organization.
312+
313+
Args:
314+
limit: Limit the number of extensions to return.
315+
316+
offset: Offset the number of extensions to return.
317+
318+
extra_headers: Send extra headers
319+
320+
extra_query: Add additional query parameters to the request
321+
322+
extra_body: Add additional JSON properties to the request
323+
324+
timeout: Override the client-level default timeout for this request, in seconds
325+
"""
326+
return self._get_api_list(
281327
"/extensions",
328+
page=AsyncOffsetPagination[ExtensionListResponse],
282329
options=make_request_options(
283-
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
330+
extra_headers=extra_headers,
331+
extra_query=extra_query,
332+
extra_body=extra_body,
333+
timeout=timeout,
334+
query=maybe_transform(
335+
{
336+
"limit": limit,
337+
"offset": offset,
338+
},
339+
extension_list_params.ExtensionListParams,
340+
),
284341
),
285-
cast_to=ExtensionListResponse,
342+
model=ExtensionListResponse,
286343
)
287344

288345
async def delete(

src/kernel/types/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from .browser_curl_response import BrowserCurlResponse as BrowserCurlResponse
4343
from .browser_list_response import BrowserListResponse as BrowserListResponse
4444
from .browser_update_params import BrowserUpdateParams as BrowserUpdateParams
45+
from .extension_list_params import ExtensionListParams as ExtensionListParams
4546
from .profile_create_params import ProfileCreateParams as ProfileCreateParams
4647
from .project_create_params import ProjectCreateParams as ProjectCreateParams
4748
from .project_update_params import ProjectUpdateParams as ProjectUpdateParams
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing_extensions import TypedDict
6+
7+
__all__ = ["ExtensionListParams"]
8+
9+
10+
class ExtensionListParams(TypedDict, total=False):
11+
limit: int
12+
"""Limit the number of extensions to return."""
13+
14+
offset: int
15+
"""Offset the number of extensions to return."""

src/kernel/types/extension_list_response.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

3-
from typing import List, Optional
3+
from typing import Optional
44
from datetime import datetime
5-
from typing_extensions import TypeAlias
65

76
from .._models import BaseModel
87

9-
__all__ = ["ExtensionListResponse", "ExtensionListResponseItem"]
8+
__all__ = ["ExtensionListResponse"]
109

1110

12-
class ExtensionListResponseItem(BaseModel):
11+
class ExtensionListResponse(BaseModel):
1312
"""A browser extension uploaded to Kernel."""
1413

1514
id: str
@@ -29,6 +28,3 @@ class ExtensionListResponseItem(BaseModel):
2928
3029
Must be unique within the project.
3130
"""
32-
33-
34-
ExtensionListResponse: TypeAlias = List[ExtensionListResponseItem]

tests/api_resources/test_extensions.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
StreamedBinaryAPIResponse,
2222
AsyncStreamedBinaryAPIResponse,
2323
)
24+
from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination
2425

2526
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
2627

@@ -32,7 +33,16 @@ class TestExtensions:
3233
@parametrize
3334
def test_method_list(self, client: Kernel) -> None:
3435
extension = client.extensions.list()
35-
assert_matches_type(ExtensionListResponse, extension, path=["response"])
36+
assert_matches_type(SyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
37+
38+
@pytest.mark.skip(reason="Mock server tests are disabled")
39+
@parametrize
40+
def test_method_list_with_all_params(self, client: Kernel) -> None:
41+
extension = client.extensions.list(
42+
limit=1,
43+
offset=0,
44+
)
45+
assert_matches_type(SyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
3646

3747
@pytest.mark.skip(reason="Mock server tests are disabled")
3848
@parametrize
@@ -42,7 +52,7 @@ def test_raw_response_list(self, client: Kernel) -> None:
4252
assert response.is_closed is True
4353
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
4454
extension = response.parse()
45-
assert_matches_type(ExtensionListResponse, extension, path=["response"])
55+
assert_matches_type(SyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
4656

4757
@pytest.mark.skip(reason="Mock server tests are disabled")
4858
@parametrize
@@ -52,7 +62,7 @@ def test_streaming_response_list(self, client: Kernel) -> None:
5262
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
5363

5464
extension = response.parse()
55-
assert_matches_type(ExtensionListResponse, extension, path=["response"])
65+
assert_matches_type(SyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
5666

5767
assert cast(Any, response.is_closed) is True
5868

@@ -256,7 +266,16 @@ class TestAsyncExtensions:
256266
@parametrize
257267
async def test_method_list(self, async_client: AsyncKernel) -> None:
258268
extension = await async_client.extensions.list()
259-
assert_matches_type(ExtensionListResponse, extension, path=["response"])
269+
assert_matches_type(AsyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
270+
271+
@pytest.mark.skip(reason="Mock server tests are disabled")
272+
@parametrize
273+
async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> None:
274+
extension = await async_client.extensions.list(
275+
limit=1,
276+
offset=0,
277+
)
278+
assert_matches_type(AsyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
260279

261280
@pytest.mark.skip(reason="Mock server tests are disabled")
262281
@parametrize
@@ -266,7 +285,7 @@ async def test_raw_response_list(self, async_client: AsyncKernel) -> None:
266285
assert response.is_closed is True
267286
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
268287
extension = await response.parse()
269-
assert_matches_type(ExtensionListResponse, extension, path=["response"])
288+
assert_matches_type(AsyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
270289

271290
@pytest.mark.skip(reason="Mock server tests are disabled")
272291
@parametrize
@@ -276,7 +295,7 @@ async def test_streaming_response_list(self, async_client: AsyncKernel) -> None:
276295
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
277296

278297
extension = await response.parse()
279-
assert_matches_type(ExtensionListResponse, extension, path=["response"])
298+
assert_matches_type(AsyncOffsetPagination[ExtensionListResponse], extension, path=["response"])
280299

281300
assert cast(Any, response.is_closed) is True
282301

0 commit comments

Comments
 (0)