diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c7bc99a..fafebca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/kernel-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 @@ -38,7 +38,7 @@ jobs: run: ./scripts/lint build: - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') timeout-minutes: 10 name: build permissions: diff --git a/.gitignore b/.gitignore index 95ceb18..3824f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log _dev __pycache__ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cc51f6f..fc0d7ff 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.44.0" + ".": "0.45.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index be60802..8a5c9d0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb2ac8e0d3a1c08e8afcbcbad7cb733d0f84bd22a8d233c1ec3100a01ee078ae.yml -openapi_spec_hash: a83f7d1c422c85d6dc6158af7afe1d09 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aeb5ea5c2632fe7fd905d509bc6cbb06999d17c458ec44ffd713935ba5b848f9.yml +openapi_spec_hash: fef45a8569f1d3de04c86e95b1112665 config_hash: 16e4457a0bb26e98a335a1c2a572290a diff --git a/CHANGELOG.md b/CHANGELOG.md index a11503f..767a744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.45.0 (2026-03-27) + +Full Changelog: [v0.44.0...v0.45.0](https://github.com/kernel/kernel-python-sdk/compare/v0.44.0...v0.45.0) + +### Features + +* [kernel-1008] browser pools add custom policy ([09f8520](https://github.com/kernel/kernel-python-sdk/commit/09f85209bc3c646d8a2a1231ed3925cad830f3dc)) +* **internal:** implement indices array format for query and form serialization ([c798c39](https://github.com/kernel/kernel-python-sdk/commit/c798c39251def1447d61215c187f0e285f225f3d)) + + +### Chores + +* **ci:** skip lint on metadata-only changes ([f0815a8](https://github.com/kernel/kernel-python-sdk/commit/f0815a8d36799444220552cb599a19b79c9b5e12)) +* **internal:** update gitignore ([34b47ab](https://github.com/kernel/kernel-python-sdk/commit/34b47ab40aeb12ad9f78e923493caaca88a554b4)) + ## 0.44.0 (2026-03-20) Full Changelog: [v0.43.0...v0.44.0](https://github.com/kernel/kernel-python-sdk/compare/v0.43.0...v0.44.0) diff --git a/pyproject.toml b/pyproject.toml index 62ca833..b8b563e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.44.0" +version = "0.45.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_qs.py b/src/kernel/_qs.py index ada6fd3..de8c99b 100644 --- a/src/kernel/_qs.py +++ b/src/kernel/_qs.py @@ -101,7 +101,10 @@ def _stringify_item( items.extend(self._stringify_item(key, item, opts)) return items elif array_format == "indices": - raise NotImplementedError("The array indices format is not supported yet") + items = [] + for i, item in enumerate(value): + items.extend(self._stringify_item(f"{key}[{i}]", item, opts)) + return items elif array_format == "brackets": items = [] key = key + "[]" diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 2c4ce41..4483ae9 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.44.0" # x-release-please-version +__version__ = "0.45.0" # x-release-please-version diff --git a/src/kernel/resources/browser_pools.py b/src/kernel/resources/browser_pools.py index c0ce659..045737a 100644 --- a/src/kernel/resources/browser_pools.py +++ b/src/kernel/resources/browser_pools.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable +from typing import Dict, Iterable import httpx @@ -60,6 +60,7 @@ def create( self, *, size: int, + chrome_policy: Dict[str, object] | Omit = omit, extensions: Iterable[BrowserExtension] | Omit = omit, fill_rate_per_minute: int | Omit = omit, headless: bool | Omit = omit, @@ -85,6 +86,11 @@ def create( your organization's pooled sessions limit (the sum of all pool sizes cannot exceed your limit). + chrome_policy: Custom Chrome enterprise policy overrides applied to all browsers in this pool. + Keys are Chrome enterprise policy names; values must match their expected types. + Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + https://chromeenterprise.google/policies/ + extensions: List of browser extensions to load into the session. Provide each by id or name. fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10%. @@ -135,6 +141,7 @@ def create( body=maybe_transform( { "size": size, + "chrome_policy": chrome_policy, "extensions": extensions, "fill_rate_per_minute": fill_rate_per_minute, "headless": headless, @@ -192,6 +199,7 @@ def update( id_or_name: str, *, size: int, + chrome_policy: Dict[str, object] | Omit = omit, discard_all_idle: bool | Omit = omit, extensions: Iterable[BrowserExtension] | Omit = omit, fill_rate_per_minute: int | Omit = omit, @@ -218,6 +226,11 @@ def update( your organization's pooled sessions limit (the sum of all pool sizes cannot exceed your limit). + chrome_policy: Custom Chrome enterprise policy overrides applied to all browsers in this pool. + Keys are Chrome enterprise policy names; values must match their expected types. + Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + https://chromeenterprise.google/policies/ + discard_all_idle: Whether to discard all idle browsers and rebuild the pool immediately. Defaults to false. @@ -273,6 +286,7 @@ def update( body=maybe_transform( { "size": size, + "chrome_policy": chrome_policy, "discard_all_idle": discard_all_idle, "extensions": extensions, "fill_rate_per_minute": fill_rate_per_minute, @@ -508,6 +522,7 @@ async def create( self, *, size: int, + chrome_policy: Dict[str, object] | Omit = omit, extensions: Iterable[BrowserExtension] | Omit = omit, fill_rate_per_minute: int | Omit = omit, headless: bool | Omit = omit, @@ -533,6 +548,11 @@ async def create( your organization's pooled sessions limit (the sum of all pool sizes cannot exceed your limit). + chrome_policy: Custom Chrome enterprise policy overrides applied to all browsers in this pool. + Keys are Chrome enterprise policy names; values must match their expected types. + Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + https://chromeenterprise.google/policies/ + extensions: List of browser extensions to load into the session. Provide each by id or name. fill_rate_per_minute: Percentage of the pool to fill per minute. Defaults to 10%. @@ -583,6 +603,7 @@ async def create( body=await async_maybe_transform( { "size": size, + "chrome_policy": chrome_policy, "extensions": extensions, "fill_rate_per_minute": fill_rate_per_minute, "headless": headless, @@ -640,6 +661,7 @@ async def update( id_or_name: str, *, size: int, + chrome_policy: Dict[str, object] | Omit = omit, discard_all_idle: bool | Omit = omit, extensions: Iterable[BrowserExtension] | Omit = omit, fill_rate_per_minute: int | Omit = omit, @@ -666,6 +688,11 @@ async def update( your organization's pooled sessions limit (the sum of all pool sizes cannot exceed your limit). + chrome_policy: Custom Chrome enterprise policy overrides applied to all browsers in this pool. + Keys are Chrome enterprise policy names; values must match their expected types. + Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + https://chromeenterprise.google/policies/ + discard_all_idle: Whether to discard all idle browsers and rebuild the pool immediately. Defaults to false. @@ -721,6 +748,7 @@ async def update( body=await async_maybe_transform( { "size": size, + "chrome_policy": chrome_policy, "discard_all_idle": discard_all_idle, "extensions": extensions, "fill_rate_per_minute": fill_rate_per_minute, diff --git a/src/kernel/types/browser_pool.py b/src/kernel/types/browser_pool.py index c6286ac..8ca0dc4 100644 --- a/src/kernel/types/browser_pool.py +++ b/src/kernel/types/browser_pool.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from .._models import BaseModel @@ -21,6 +21,14 @@ class BrowserPoolConfig(BaseModel): sum of all pool sizes cannot exceed your limit). """ + chrome_policy: Optional[Dict[str, object]] = None + """Custom Chrome enterprise policy overrides applied to all browsers in this pool. + + Keys are Chrome enterprise policy names; values must match their expected types. + Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + https://chromeenterprise.google/policies/ + """ + extensions: Optional[List[BrowserExtension]] = None """List of browser extensions to load into the session. diff --git a/src/kernel/types/browser_pool_create_params.py b/src/kernel/types/browser_pool_create_params.py index 63ef712..ecfb888 100644 --- a/src/kernel/types/browser_pool_create_params.py +++ b/src/kernel/types/browser_pool_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable +from typing import Dict, Iterable from typing_extensions import Required, TypedDict from .shared_params.browser_profile import BrowserProfile @@ -20,6 +20,14 @@ class BrowserPoolCreateParams(TypedDict, total=False): sum of all pool sizes cannot exceed your limit). """ + chrome_policy: Dict[str, object] + """Custom Chrome enterprise policy overrides applied to all browsers in this pool. + + Keys are Chrome enterprise policy names; values must match their expected types. + Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + https://chromeenterprise.google/policies/ + """ + extensions: Iterable[BrowserExtension] """List of browser extensions to load into the session. diff --git a/src/kernel/types/browser_pool_update_params.py b/src/kernel/types/browser_pool_update_params.py index d1f003b..e34664a 100644 --- a/src/kernel/types/browser_pool_update_params.py +++ b/src/kernel/types/browser_pool_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable +from typing import Dict, Iterable from typing_extensions import Required, TypedDict from .shared_params.browser_profile import BrowserProfile @@ -20,6 +20,14 @@ class BrowserPoolUpdateParams(TypedDict, total=False): sum of all pool sizes cannot exceed your limit). """ + chrome_policy: Dict[str, object] + """Custom Chrome enterprise policy overrides applied to all browsers in this pool. + + Keys are Chrome enterprise policy names; values must match their expected types. + Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + https://chromeenterprise.google/policies/ + """ + discard_all_idle: bool """Whether to discard all idle browsers and rebuild the pool immediately. diff --git a/tests/api_resources/test_browser_pools.py b/tests/api_resources/test_browser_pools.py index c7e1a47..70c7ad8 100644 --- a/tests/api_resources/test_browser_pools.py +++ b/tests/api_resources/test_browser_pools.py @@ -34,6 +34,7 @@ def test_method_create(self, client: Kernel) -> None: def test_method_create_with_all_params(self, client: Kernel) -> None: browser_pool = client.browser_pools.create( size=10, + chrome_policy={"foo": "bar"}, extensions=[ { "id": "id", @@ -143,6 +144,7 @@ def test_method_update_with_all_params(self, client: Kernel) -> None: browser_pool = client.browser_pools.update( id_or_name="id_or_name", size=10, + chrome_policy={"foo": "bar"}, discard_all_idle=False, extensions=[ { @@ -454,6 +456,7 @@ async def test_method_create(self, async_client: AsyncKernel) -> None: async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> None: browser_pool = await async_client.browser_pools.create( size=10, + chrome_policy={"foo": "bar"}, extensions=[ { "id": "id", @@ -563,6 +566,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> browser_pool = await async_client.browser_pools.update( id_or_name="id_or_name", size=10, + chrome_policy={"foo": "bar"}, discard_all_idle=False, extensions=[ {