diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 559b4513..51acdaa4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.36.1" + ".": "0.37.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index c875efdd..b154e7ae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ea5c9cb25c29fa5a8758bbf8732eb306783bb6f13b4df29bf1ad5ad3cb32da1e.yml -openapi_spec_hash: 597031840469b011f5cf22a4d8b9d750 -config_hash: 147340811dd6fbb9c2d80515a7e31f9a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fc4a441d80d9a26574ef8af390a0c76265f5d4190daf90a04b6b353b128bbd97.yml +openapi_spec_hash: 192987649d3797c3a80e6ef201667b64 +config_hash: 8af430e19f4af86c05f2987241cae72f diff --git a/CHANGELOG.md b/CHANGELOG.md index 915408df..f2e97b35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.37.0 (2026-02-23) + +Full Changelog: [v0.36.1...v0.37.0](https://github.com/kernel/kernel-python-sdk/compare/v0.36.1...v0.37.0) + +### Features + +* Neil/kernel 1017 profile pagination query parameter ([fc068ec](https://github.com/kernel/kernel-python-sdk/commit/fc068ec7dc7b4bbed0d11322f52b49065e7680fd)) + ## 0.36.1 (2026-02-21) Full Changelog: [v0.36.0...v0.36.1](https://github.com/kernel/kernel-python-sdk/compare/v0.36.0...v0.36.1) diff --git a/api.md b/api.md index 45197699..0cda6cac 100644 --- a/api.md +++ b/api.md @@ -221,17 +221,11 @@ Methods: # Profiles -Types: - -```python -from kernel.types import ProfileListResponse -``` - Methods: - client.profiles.create(\*\*params) -> Profile - client.profiles.retrieve(id_or_name) -> Profile -- client.profiles.list() -> ProfileListResponse +- client.profiles.list(\*\*params) -> SyncOffsetPagination[Profile] - client.profiles.delete(id_or_name) -> None - client.profiles.download(id_or_name) -> BinaryAPIResponse diff --git a/pyproject.toml b/pyproject.toml index f969dc23..b3ea5e98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.36.1" +version = "0.37.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_version.py b/src/kernel/_version.py index eca0c818..01a56b55 100644 --- a/src/kernel/_version.py +++ b/src/kernel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "kernel" -__version__ = "0.36.1" # x-release-please-version +__version__ = "0.37.0" # x-release-please-version diff --git a/src/kernel/resources/profiles.py b/src/kernel/resources/profiles.py index 86064d52..e9b124b5 100644 --- a/src/kernel/resources/profiles.py +++ b/src/kernel/resources/profiles.py @@ -4,7 +4,7 @@ import httpx -from ..types import profile_create_params +from ..types import profile_list_params, profile_create_params from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property @@ -23,9 +23,9 @@ async_to_custom_raw_response_wrapper, async_to_custom_streamed_response_wrapper, ) -from .._base_client import make_request_options +from ..pagination import SyncOffsetPagination, AsyncOffsetPagination +from .._base_client import AsyncPaginator, make_request_options from ..types.profile import Profile -from ..types.profile_list_response import ProfileListResponse __all__ = ["ProfilesResource", "AsyncProfilesResource"] @@ -121,20 +121,52 @@ def retrieve( def list( self, *, + limit: int | Omit = omit, + offset: int | Omit = omit, + query: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProfileListResponse: - """List profiles with optional filtering and pagination.""" - return self._get( + ) -> SyncOffsetPagination[Profile]: + """ + List profiles with optional filtering and pagination. + + Args: + limit: Limit the number of profiles to return. + + offset: Offset the number of profiles to return. + + query: Search profiles by name or ID. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( "/profiles", + page=SyncOffsetPagination[Profile], options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "offset": offset, + "query": query, + }, + profile_list_params.ProfileListParams, + ), ), - cast_to=ProfileListResponse, + model=Profile, ) def delete( @@ -296,23 +328,55 @@ async def retrieve( cast_to=Profile, ) - async def list( + def list( self, *, + limit: int | Omit = omit, + offset: int | Omit = omit, + query: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProfileListResponse: - """List profiles with optional filtering and pagination.""" - return await self._get( + ) -> AsyncPaginator[Profile, AsyncOffsetPagination[Profile]]: + """ + List profiles with optional filtering and pagination. + + Args: + limit: Limit the number of profiles to return. + + offset: Offset the number of profiles to return. + + query: Search profiles by name or ID. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( "/profiles", + page=AsyncOffsetPagination[Profile], options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "offset": offset, + "query": query, + }, + profile_list_params.ProfileListParams, + ), ), - cast_to=ProfileListResponse, + model=Profile, ) async def delete( diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py index 6340848f..2c3b4a8f 100644 --- a/src/kernel/types/__init__.py +++ b/src/kernel/types/__init__.py @@ -21,6 +21,7 @@ from .browser_list_params import BrowserListParams as BrowserListParams from .browser_persistence import BrowserPersistence as BrowserPersistence from .credential_provider import CredentialProvider as CredentialProvider +from .profile_list_params import ProfileListParams as ProfileListParams from .proxy_create_params import ProxyCreateParams as ProxyCreateParams from .proxy_list_response import ProxyListResponse as ProxyListResponse from .proxy_check_response import ProxyCheckResponse as ProxyCheckResponse @@ -29,7 +30,6 @@ from .browser_list_response import BrowserListResponse as BrowserListResponse from .browser_update_params import BrowserUpdateParams as BrowserUpdateParams from .profile_create_params import ProfileCreateParams as ProfileCreateParams -from .profile_list_response import ProfileListResponse as ProfileListResponse from .proxy_create_response import ProxyCreateResponse as ProxyCreateResponse from .credential_list_params import CredentialListParams as CredentialListParams from .deployment_list_params import DeploymentListParams as DeploymentListParams diff --git a/src/kernel/types/profile_list_params.py b/src/kernel/types/profile_list_params.py new file mode 100644 index 00000000..4218f5bc --- /dev/null +++ b/src/kernel/types/profile_list_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ProfileListParams"] + + +class ProfileListParams(TypedDict, total=False): + limit: int + """Limit the number of profiles to return.""" + + offset: int + """Offset the number of profiles to return.""" + + query: str + """Search profiles by name or ID.""" diff --git a/src/kernel/types/profile_list_response.py b/src/kernel/types/profile_list_response.py deleted file mode 100644 index 24b2744c..00000000 --- a/src/kernel/types/profile_list_response.py +++ /dev/null @@ -1,10 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List -from typing_extensions import TypeAlias - -from .profile import Profile - -__all__ = ["ProfileListResponse"] - -ProfileListResponse: TypeAlias = List[Profile] diff --git a/tests/api_resources/test_profiles.py b/tests/api_resources/test_profiles.py index 2024ec8a..296593ea 100644 --- a/tests/api_resources/test_profiles.py +++ b/tests/api_resources/test_profiles.py @@ -11,13 +11,14 @@ from kernel import Kernel, AsyncKernel from tests.utils import assert_matches_type -from kernel.types import Profile, ProfileListResponse +from kernel.types import Profile from kernel._response import ( BinaryAPIResponse, AsyncBinaryAPIResponse, StreamedBinaryAPIResponse, AsyncStreamedBinaryAPIResponse, ) +from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -107,7 +108,17 @@ def test_path_params_retrieve(self, client: Kernel) -> None: @parametrize def test_method_list(self, client: Kernel) -> None: profile = client.profiles.list() - assert_matches_type(ProfileListResponse, profile, path=["response"]) + assert_matches_type(SyncOffsetPagination[Profile], profile, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Kernel) -> None: + profile = client.profiles.list( + limit=1, + offset=0, + query="query", + ) + assert_matches_type(SyncOffsetPagination[Profile], profile, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -117,7 +128,7 @@ def test_raw_response_list(self, client: Kernel) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" profile = response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) + assert_matches_type(SyncOffsetPagination[Profile], profile, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -127,7 +138,7 @@ def test_streaming_response_list(self, client: Kernel) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" profile = response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) + assert_matches_type(SyncOffsetPagination[Profile], profile, path=["response"]) assert cast(Any, response.is_closed) is True @@ -311,7 +322,17 @@ async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None: @parametrize async def test_method_list(self, async_client: AsyncKernel) -> None: profile = await async_client.profiles.list() - assert_matches_type(ProfileListResponse, profile, path=["response"]) + assert_matches_type(AsyncOffsetPagination[Profile], profile, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> None: + profile = await async_client.profiles.list( + limit=1, + offset=0, + query="query", + ) + assert_matches_type(AsyncOffsetPagination[Profile], profile, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -321,7 +342,7 @@ async def test_raw_response_list(self, async_client: AsyncKernel) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" profile = await response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) + assert_matches_type(AsyncOffsetPagination[Profile], profile, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -331,7 +352,7 @@ async def test_streaming_response_list(self, async_client: AsyncKernel) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" profile = await response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) + assert_matches_type(AsyncOffsetPagination[Profile], profile, path=["response"]) assert cast(Any, response.is_closed) is True