From 45de860fb92aeeccf5ef44dcb2b5ab4a2b7a0592 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Sep 2025 02:47:20 +0000 Subject: [PATCH 1/6] chore(internal): update pydantic dependency --- requirements-dev.lock | 7 +++++-- requirements.lock | 7 +++++-- src/kernel/_models.py | 14 ++++++++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 56d0accb..249acb1e 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -88,9 +88,9 @@ pluggy==1.5.0 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.11.9 # via kernel -pydantic-core==2.27.1 +pydantic-core==2.33.2 # via pydantic pygments==2.18.0 # via rich @@ -126,6 +126,9 @@ typing-extensions==4.12.2 # via pydantic # via pydantic-core # via pyright + # via typing-inspection +typing-inspection==0.4.1 + # via pydantic virtualenv==20.24.5 # via nox yarl==1.20.0 diff --git a/requirements.lock b/requirements.lock index 61c4c7ac..49cc9054 100644 --- a/requirements.lock +++ b/requirements.lock @@ -55,9 +55,9 @@ multidict==6.4.4 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.11.9 # via kernel -pydantic-core==2.27.1 +pydantic-core==2.33.2 # via pydantic sniffio==1.3.0 # via anyio @@ -68,5 +68,8 @@ typing-extensions==4.12.2 # via multidict # via pydantic # via pydantic-core + # via typing-inspection +typing-inspection==0.4.1 + # via pydantic yarl==1.20.0 # via aiohttp diff --git a/src/kernel/_models.py b/src/kernel/_models.py index 3a6017ef..6a3cd1d2 100644 --- a/src/kernel/_models.py +++ b/src/kernel/_models.py @@ -256,7 +256,7 @@ def model_dump( mode: Literal["json", "python"] | str = "python", include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, @@ -264,6 +264,7 @@ def model_dump( warnings: bool | Literal["none", "warn", "error"] = True, context: dict[str, Any] | None = None, serialize_as_any: bool = False, + fallback: Callable[[Any], Any] | None = None, ) -> dict[str, Any]: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump @@ -295,10 +296,12 @@ def model_dump( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") dumped = super().dict( # pyright: ignore[reportDeprecated] include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, @@ -313,13 +316,14 @@ def model_dump_json( indent: int | None = None, include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, context: dict[str, Any] | None = None, + fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> str: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump_json @@ -348,11 +352,13 @@ def model_dump_json( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") return super().json( # type: ignore[reportDeprecated] indent=indent, include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, From 0b85104d500907e1f86ad633403fb4c27fb929c4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 02:55:46 +0000 Subject: [PATCH 2/6] chore(types): change optional parameter type from NotGiven to Omit --- src/kernel/__init__.py | 4 +- src/kernel/_base_client.py | 18 +++--- src/kernel/_client.py | 24 ++++---- src/kernel/_qs.py | 14 ++--- src/kernel/_types.py | 29 +++++---- src/kernel/_utils/_transform.py | 4 +- src/kernel/_utils/_utils.py | 8 +-- src/kernel/resources/apps.py | 14 ++--- src/kernel/resources/browsers/browsers.py | 46 +++++++------- src/kernel/resources/browsers/fs/fs.py | 66 ++++++++++---------- src/kernel/resources/browsers/fs/watch.py | 18 +++--- src/kernel/resources/browsers/logs.py | 18 +++--- src/kernel/resources/browsers/process.py | 74 +++++++++++------------ src/kernel/resources/browsers/replays.py | 26 ++++---- src/kernel/resources/deployments.py | 50 +++++++-------- src/kernel/resources/invocations.py | 34 +++++------ src/kernel/resources/profiles.py | 26 ++++---- tests/test_transform.py | 11 +++- 18 files changed, 250 insertions(+), 234 deletions(-) diff --git a/src/kernel/__init__.py b/src/kernel/__init__.py index 03cd75c7..333d7018 100644 --- a/src/kernel/__init__.py +++ b/src/kernel/__init__.py @@ -3,7 +3,7 @@ import typing as _t from . import types -from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given from ._utils import file_from_path from ._client import ( ENVIRONMENTS, @@ -61,7 +61,9 @@ "ProxiesTypes", "NotGiven", "NOT_GIVEN", + "not_given", "Omit", + "omit", "KernelError", "APIError", "APIStatusError", diff --git a/src/kernel/_base_client.py b/src/kernel/_base_client.py index 0d2ff453..756e21e7 100644 --- a/src/kernel/_base_client.py +++ b/src/kernel/_base_client.py @@ -42,7 +42,6 @@ from ._qs import Querystring from ._files import to_httpx_files, async_to_httpx_files from ._types import ( - NOT_GIVEN, Body, Omit, Query, @@ -57,6 +56,7 @@ RequestOptions, HttpxRequestFiles, ModelBuilderProtocol, + not_given, ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping from ._compat import PYDANTIC_V1, model_copy, model_dump @@ -145,9 +145,9 @@ def __init__( def __init__( self, *, - url: URL | NotGiven = NOT_GIVEN, - json: Body | NotGiven = NOT_GIVEN, - params: Query | NotGiven = NOT_GIVEN, + url: URL | NotGiven = not_given, + json: Body | NotGiven = not_given, + params: Query | NotGiven = not_given, ) -> None: self.url = url self.json = json @@ -595,7 +595,7 @@ def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalReques # we internally support defining a temporary header to override the # default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response` # see _response.py for implementation details - override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, NOT_GIVEN) + override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, not_given) if is_given(override_cast_to): options.headers = headers return cast(Type[ResponseT], override_cast_to) @@ -825,7 +825,7 @@ def __init__( version: str, base_url: str | URL, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1356,7 +1356,7 @@ def __init__( base_url: str | URL, _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1818,8 +1818,8 @@ def make_request_options( extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - post_parser: PostParser | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + post_parser: PostParser | NotGiven = not_given, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} diff --git a/src/kernel/_client.py b/src/kernel/_client.py index 3b4235cd..830aeb58 100644 --- a/src/kernel/_client.py +++ b/src/kernel/_client.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from typing import Any, Dict, Union, Mapping, cast +from typing import Any, Dict, Mapping, cast from typing_extensions import Self, Literal, override import httpx @@ -11,13 +11,13 @@ from . import _exceptions from ._qs import Querystring from ._types import ( - NOT_GIVEN, Omit, Timeout, NotGiven, Transport, ProxiesTypes, RequestOptions, + not_given, ) from ._utils import is_given, get_async_library from ._version import __version__ @@ -67,9 +67,9 @@ def __init__( self, *, api_key: str | None = None, - environment: Literal["production", "development"] | NotGiven = NOT_GIVEN, - base_url: str | httpx.URL | None | NotGiven = NOT_GIVEN, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + environment: Literal["production", "development"] | NotGiven = not_given, + base_url: str | httpx.URL | None | NotGiven = not_given, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -170,9 +170,9 @@ def copy( api_key: str | None = None, environment: Literal["production", "development"] | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -269,9 +269,9 @@ def __init__( self, *, api_key: str | None = None, - environment: Literal["production", "development"] | NotGiven = NOT_GIVEN, - base_url: str | httpx.URL | None | NotGiven = NOT_GIVEN, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + environment: Literal["production", "development"] | NotGiven = not_given, + base_url: str | httpx.URL | None | NotGiven = not_given, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -372,9 +372,9 @@ def copy( api_key: str | None = None, environment: Literal["production", "development"] | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, diff --git a/src/kernel/_qs.py b/src/kernel/_qs.py index 274320ca..ada6fd3f 100644 --- a/src/kernel/_qs.py +++ b/src/kernel/_qs.py @@ -4,7 +4,7 @@ from urllib.parse import parse_qs, urlencode from typing_extensions import Literal, get_args -from ._types import NOT_GIVEN, NotGiven, NotGivenOr +from ._types import NotGiven, not_given from ._utils import flatten _T = TypeVar("_T") @@ -41,8 +41,8 @@ def stringify( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> str: return urlencode( self.stringify_items( @@ -56,8 +56,8 @@ def stringify_items( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> list[tuple[str, str]]: opts = Options( qs=self, @@ -143,8 +143,8 @@ def __init__( self, qs: Querystring = _qs, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> None: self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format diff --git a/src/kernel/_types.py b/src/kernel/_types.py index 48bae95e..2c1d83b2 100644 --- a/src/kernel/_types.py +++ b/src/kernel/_types.py @@ -117,18 +117,21 @@ class RequestOptions(TypedDict, total=False): # Sentinel class used until PEP 0661 is accepted class NotGiven: """ - A sentinel singleton class used to distinguish omitted keyword arguments - from those passed in with the value None (which may have different behavior). + For parameters with a meaningful None value, we need to distinguish between + the user explicitly passing None, and the user not passing the parameter at + all. + + User code shouldn't need to use not_given directly. For example: ```py - def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ... + def create(timeout: Timeout | None | NotGiven = not_given): ... - get(timeout=1) # 1s timeout - get(timeout=None) # No timeout - get() # Default timeout behavior, which may not be statically known at the method definition. + create(timeout=1) # 1s timeout + create(timeout=None) # No timeout + create() # Default timeout behavior ``` """ @@ -140,13 +143,14 @@ def __repr__(self) -> str: return "NOT_GIVEN" -NotGivenOr = Union[_T, NotGiven] +not_given = NotGiven() +# for backwards compatibility: NOT_GIVEN = NotGiven() class Omit: - """In certain situations you need to be able to represent a case where a default value has - to be explicitly removed and `None` is not an appropriate substitute, for example: + """ + To explicitly omit something from being sent in a request, use `omit`. ```py # as the default `Content-Type` header is `application/json` that will be sent @@ -156,8 +160,8 @@ class Omit: # to look something like: 'multipart/form-data; boundary=0d8382fcf5f8c3be01ca2e11002d2983' client.post(..., headers={"Content-Type": "multipart/form-data"}) - # instead you can remove the default `application/json` header by passing Omit - client.post(..., headers={"Content-Type": Omit()}) + # instead you can remove the default `application/json` header by passing omit + client.post(..., headers={"Content-Type": omit}) ``` """ @@ -165,6 +169,9 @@ def __bool__(self) -> Literal[False]: return False +omit = Omit() + + @runtime_checkable class ModelBuilderProtocol(Protocol): @classmethod diff --git a/src/kernel/_utils/_transform.py b/src/kernel/_utils/_transform.py index c19124f0..52075492 100644 --- a/src/kernel/_utils/_transform.py +++ b/src/kernel/_utils/_transform.py @@ -268,7 +268,7 @@ def _transform_typeddict( annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): - # we don't need to include `NotGiven` values here as they'll + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue @@ -434,7 +434,7 @@ async def _async_transform_typeddict( annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): - # we don't need to include `NotGiven` values here as they'll + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue diff --git a/src/kernel/_utils/_utils.py b/src/kernel/_utils/_utils.py index f0818595..50d59269 100644 --- a/src/kernel/_utils/_utils.py +++ b/src/kernel/_utils/_utils.py @@ -21,7 +21,7 @@ import sniffio -from .._types import NotGiven, FileTypes, NotGivenOr, HeadersLike +from .._types import Omit, NotGiven, FileTypes, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -63,7 +63,7 @@ def _extract_items( try: key = path[index] except IndexError: - if isinstance(obj, NotGiven): + if not is_given(obj): # no value was provided - we can safely ignore return [] @@ -126,8 +126,8 @@ def _extract_items( return [] -def is_given(obj: NotGivenOr[_T]) -> TypeGuard[_T]: - return not isinstance(obj, NotGiven) +def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]: + return not isinstance(obj, NotGiven) and not isinstance(obj, Omit) # Type safe methods for narrowing types with TypeVars. diff --git a/src/kernel/resources/apps.py b/src/kernel/resources/apps.py index 652235e2..28117b98 100644 --- a/src/kernel/resources/apps.py +++ b/src/kernel/resources/apps.py @@ -5,7 +5,7 @@ import httpx from ..types import app_list_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -44,14 +44,14 @@ def with_streaming_response(self) -> AppsResourceWithStreamingResponse: def list( self, *, - app_name: str | NotGiven = NOT_GIVEN, - version: str | NotGiven = NOT_GIVEN, + app_name: str | Omit = omit, + version: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AppListResponse: """List applications. @@ -112,14 +112,14 @@ def with_streaming_response(self) -> AsyncAppsResourceWithStreamingResponse: async def list( self, *, - app_name: str | NotGiven = NOT_GIVEN, - version: str | NotGiven = NOT_GIVEN, + app_name: str | Omit = omit, + version: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AppListResponse: """List applications. diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py index 7394f21a..e871c215 100644 --- a/src/kernel/resources/browsers/browsers.py +++ b/src/kernel/resources/browsers/browsers.py @@ -37,7 +37,7 @@ ReplaysResourceWithStreamingResponse, AsyncReplaysResourceWithStreamingResponse, ) -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +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 from ..._resource import SyncAPIResource, AsyncAPIResource @@ -95,18 +95,18 @@ def with_streaming_response(self) -> BrowsersResourceWithStreamingResponse: def create( self, *, - headless: bool | NotGiven = NOT_GIVEN, - invocation_id: str | NotGiven = NOT_GIVEN, - persistence: BrowserPersistenceParam | NotGiven = NOT_GIVEN, - profile: browser_create_params.Profile | NotGiven = NOT_GIVEN, - stealth: bool | NotGiven = NOT_GIVEN, - timeout_seconds: int | NotGiven = NOT_GIVEN, + headless: bool | Omit = omit, + invocation_id: str | Omit = omit, + persistence: BrowserPersistenceParam | Omit = omit, + profile: browser_create_params.Profile | Omit = omit, + stealth: bool | Omit = omit, + timeout_seconds: int | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrowserCreateResponse: """ Create a new browser session from within an action. @@ -166,7 +166,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrowserRetrieveResponse: """ Get information about a browser session. @@ -198,7 +198,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrowserListResponse: """List active browser sessions""" return self._get( @@ -218,7 +218,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a persistent browser session by its persistent_id. @@ -256,7 +256,7 @@ def delete_by_id( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a browser session by ID @@ -321,18 +321,18 @@ def with_streaming_response(self) -> AsyncBrowsersResourceWithStreamingResponse: async def create( self, *, - headless: bool | NotGiven = NOT_GIVEN, - invocation_id: str | NotGiven = NOT_GIVEN, - persistence: BrowserPersistenceParam | NotGiven = NOT_GIVEN, - profile: browser_create_params.Profile | NotGiven = NOT_GIVEN, - stealth: bool | NotGiven = NOT_GIVEN, - timeout_seconds: int | NotGiven = NOT_GIVEN, + headless: bool | Omit = omit, + invocation_id: str | Omit = omit, + persistence: BrowserPersistenceParam | Omit = omit, + profile: browser_create_params.Profile | Omit = omit, + stealth: bool | Omit = omit, + timeout_seconds: int | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrowserCreateResponse: """ Create a new browser session from within an action. @@ -392,7 +392,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrowserRetrieveResponse: """ Get information about a browser session. @@ -424,7 +424,7 @@ async def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrowserListResponse: """List active browser sessions""" return await self._get( @@ -444,7 +444,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a persistent browser session by its persistent_id. @@ -484,7 +484,7 @@ async def delete_by_id( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a browser session by ID diff --git a/src/kernel/resources/browsers/fs/fs.py b/src/kernel/resources/browsers/fs/fs.py index cb7b3010..ff0cc48a 100644 --- a/src/kernel/resources/browsers/fs/fs.py +++ b/src/kernel/resources/browsers/fs/fs.py @@ -15,7 +15,7 @@ AsyncWatchResourceWithStreamingResponse, ) from ...._files import read_file_content, async_read_file_content -from ...._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes, FileContent +from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, FileContent, omit, not_given from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource @@ -83,13 +83,13 @@ def create_directory( id: str, *, path: str, - mode: str | NotGiven = NOT_GIVEN, + mode: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Create a new directory @@ -135,7 +135,7 @@ def delete_directory( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a directory @@ -173,7 +173,7 @@ def delete_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a file @@ -211,7 +211,7 @@ def download_dir_zip( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BinaryAPIResponse: """ Returns a ZIP file containing the contents of the specified directory. @@ -252,7 +252,7 @@ def file_info( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FFileInfoResponse: """ Get information about a file or directory @@ -292,7 +292,7 @@ def list_files( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FListFilesResponse: """ List files in a directory @@ -333,7 +333,7 @@ def move( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Move or rename a file or directory @@ -379,7 +379,7 @@ def read_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BinaryAPIResponse: """ Read file contents @@ -416,14 +416,14 @@ def set_file_permissions( *, mode: str, path: str, - group: str | NotGiven = NOT_GIVEN, - owner: str | NotGiven = NOT_GIVEN, + group: str | Omit = omit, + owner: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Set file or directory permissions/ownership @@ -475,7 +475,7 @@ def upload( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Allows uploading single or multiple files to the remote filesystem. @@ -519,7 +519,7 @@ def upload_zip( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Upload a zip file and extract its contents to the specified destination path. @@ -565,13 +565,13 @@ def write_file( contents: FileContent, *, path: str, - mode: str | NotGiven = NOT_GIVEN, + mode: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Write or create a file @@ -642,13 +642,13 @@ async def create_directory( id: str, *, path: str, - mode: str | NotGiven = NOT_GIVEN, + mode: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Create a new directory @@ -694,7 +694,7 @@ async def delete_directory( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a directory @@ -732,7 +732,7 @@ async def delete_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a file @@ -770,7 +770,7 @@ async def download_dir_zip( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncBinaryAPIResponse: """ Returns a ZIP file containing the contents of the specified directory. @@ -811,7 +811,7 @@ async def file_info( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FFileInfoResponse: """ Get information about a file or directory @@ -851,7 +851,7 @@ async def list_files( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FListFilesResponse: """ List files in a directory @@ -892,7 +892,7 @@ async def move( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Move or rename a file or directory @@ -938,7 +938,7 @@ async def read_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncBinaryAPIResponse: """ Read file contents @@ -975,14 +975,14 @@ async def set_file_permissions( *, mode: str, path: str, - group: str | NotGiven = NOT_GIVEN, - owner: str | NotGiven = NOT_GIVEN, + group: str | Omit = omit, + owner: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Set file or directory permissions/ownership @@ -1034,7 +1034,7 @@ async def upload( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Allows uploading single or multiple files to the remote filesystem. @@ -1078,7 +1078,7 @@ async def upload_zip( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Upload a zip file and extract its contents to the specified destination path. @@ -1124,13 +1124,13 @@ async def write_file( contents: FileContent, *, path: str, - mode: str | NotGiven = NOT_GIVEN, + mode: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Write or create a file diff --git a/src/kernel/resources/browsers/fs/watch.py b/src/kernel/resources/browsers/fs/watch.py index a35e0def..ad26f2ae 100644 --- a/src/kernel/resources/browsers/fs/watch.py +++ b/src/kernel/resources/browsers/fs/watch.py @@ -4,7 +4,7 @@ import httpx -from ...._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +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 from ...._resource import SyncAPIResource, AsyncAPIResource @@ -53,7 +53,7 @@ def events( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[WatchEventsResponse]: """ Stream filesystem events for a watch @@ -87,13 +87,13 @@ def start( id: str, *, path: str, - recursive: bool | NotGiven = NOT_GIVEN, + recursive: bool | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> WatchStartResponse: """ Watch a directory for changes @@ -138,7 +138,7 @@ def stop( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Stop watching a directory @@ -196,7 +196,7 @@ async def events( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[WatchEventsResponse]: """ Stream filesystem events for a watch @@ -230,13 +230,13 @@ async def start( id: str, *, path: str, - recursive: bool | NotGiven = NOT_GIVEN, + recursive: bool | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> WatchStartResponse: """ Watch a directory for changes @@ -281,7 +281,7 @@ async def stop( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Stop watching a directory diff --git a/src/kernel/resources/browsers/logs.py b/src/kernel/resources/browsers/logs.py index fbbe14a5..1fd291d4 100644 --- a/src/kernel/resources/browsers/logs.py +++ b/src/kernel/resources/browsers/logs.py @@ -6,7 +6,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -49,15 +49,15 @@ def stream( id: str, *, source: Literal["path", "supervisor"], - follow: bool | NotGiven = NOT_GIVEN, - path: str | NotGiven = NOT_GIVEN, - supervisor_process: str | NotGiven = NOT_GIVEN, + follow: bool | Omit = omit, + path: str | Omit = omit, + supervisor_process: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[LogEvent]: """ Stream log files on the browser instance via SSE @@ -126,15 +126,15 @@ async def stream( id: str, *, source: Literal["path", "supervisor"], - follow: bool | NotGiven = NOT_GIVEN, - path: str | NotGiven = NOT_GIVEN, - supervisor_process: str | NotGiven = NOT_GIVEN, + follow: bool | Omit = omit, + path: str | Omit = omit, + supervisor_process: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[LogEvent]: """ Stream log files on the browser instance via SSE diff --git a/src/kernel/resources/browsers/process.py b/src/kernel/resources/browsers/process.py index 9fd6dd6c..2bdaeebe 100644 --- a/src/kernel/resources/browsers/process.py +++ b/src/kernel/resources/browsers/process.py @@ -7,7 +7,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, SequenceNotStr +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -55,18 +55,18 @@ def exec( id: str, *, command: str, - args: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - as_root: bool | NotGiven = NOT_GIVEN, - as_user: Optional[str] | NotGiven = NOT_GIVEN, - cwd: Optional[str] | NotGiven = NOT_GIVEN, - env: Dict[str, str] | NotGiven = NOT_GIVEN, - timeout_sec: Optional[int] | NotGiven = NOT_GIVEN, + args: SequenceNotStr[str] | Omit = omit, + as_root: bool | Omit = omit, + as_user: Optional[str] | Omit = omit, + cwd: Optional[str] | Omit = omit, + env: Dict[str, str] | Omit = omit, + timeout_sec: Optional[int] | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessExecResponse: """ Execute a command synchronously @@ -127,7 +127,7 @@ def kill( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessKillResponse: """ Send signal to process @@ -161,18 +161,18 @@ def spawn( id: str, *, command: str, - args: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - as_root: bool | NotGiven = NOT_GIVEN, - as_user: Optional[str] | NotGiven = NOT_GIVEN, - cwd: Optional[str] | NotGiven = NOT_GIVEN, - env: Dict[str, str] | NotGiven = NOT_GIVEN, - timeout_sec: Optional[int] | NotGiven = NOT_GIVEN, + args: SequenceNotStr[str] | Omit = omit, + as_root: bool | Omit = omit, + as_user: Optional[str] | Omit = omit, + cwd: Optional[str] | Omit = omit, + env: Dict[str, str] | Omit = omit, + timeout_sec: Optional[int] | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessSpawnResponse: """ Execute a command asynchronously @@ -232,7 +232,7 @@ def status( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessStatusResponse: """ Get process status @@ -269,7 +269,7 @@ def stdin( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessStdinResponse: """ Write to process stdin @@ -308,7 +308,7 @@ def stdout_stream( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[ProcessStdoutStreamResponse]: """ Stream process stdout via SSE @@ -363,18 +363,18 @@ async def exec( id: str, *, command: str, - args: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - as_root: bool | NotGiven = NOT_GIVEN, - as_user: Optional[str] | NotGiven = NOT_GIVEN, - cwd: Optional[str] | NotGiven = NOT_GIVEN, - env: Dict[str, str] | NotGiven = NOT_GIVEN, - timeout_sec: Optional[int] | NotGiven = NOT_GIVEN, + args: SequenceNotStr[str] | Omit = omit, + as_root: bool | Omit = omit, + as_user: Optional[str] | Omit = omit, + cwd: Optional[str] | Omit = omit, + env: Dict[str, str] | Omit = omit, + timeout_sec: Optional[int] | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessExecResponse: """ Execute a command synchronously @@ -435,7 +435,7 @@ async def kill( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessKillResponse: """ Send signal to process @@ -469,18 +469,18 @@ async def spawn( id: str, *, command: str, - args: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - as_root: bool | NotGiven = NOT_GIVEN, - as_user: Optional[str] | NotGiven = NOT_GIVEN, - cwd: Optional[str] | NotGiven = NOT_GIVEN, - env: Dict[str, str] | NotGiven = NOT_GIVEN, - timeout_sec: Optional[int] | NotGiven = NOT_GIVEN, + args: SequenceNotStr[str] | Omit = omit, + as_root: bool | Omit = omit, + as_user: Optional[str] | Omit = omit, + cwd: Optional[str] | Omit = omit, + env: Dict[str, str] | Omit = omit, + timeout_sec: Optional[int] | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessSpawnResponse: """ Execute a command asynchronously @@ -540,7 +540,7 @@ async def status( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessStatusResponse: """ Get process status @@ -577,7 +577,7 @@ async def stdin( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProcessStdinResponse: """ Write to process stdin @@ -616,7 +616,7 @@ async def stdout_stream( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[ProcessStdoutStreamResponse]: """ Stream process stdout via SSE diff --git a/src/kernel/resources/browsers/replays.py b/src/kernel/resources/browsers/replays.py index b801e8f0..9f15554a 100644 --- a/src/kernel/resources/browsers/replays.py +++ b/src/kernel/resources/browsers/replays.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +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 from ..._resource import SyncAPIResource, AsyncAPIResource @@ -59,7 +59,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReplayListResponse: """ List all replays for the specified browser session. @@ -93,7 +93,7 @@ def download( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BinaryAPIResponse: """ Download or stream the specified replay recording. @@ -124,14 +124,14 @@ def start( self, id: str, *, - framerate: int | NotGiven = NOT_GIVEN, - max_duration_in_seconds: int | NotGiven = NOT_GIVEN, + framerate: int | Omit = omit, + max_duration_in_seconds: int | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReplayStartResponse: """ Start recording the browser session and return a replay ID. @@ -176,7 +176,7 @@ def stop( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Stop the specified replay recording and persist the video. @@ -233,7 +233,7 @@ async def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReplayListResponse: """ List all replays for the specified browser session. @@ -267,7 +267,7 @@ async def download( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncBinaryAPIResponse: """ Download or stream the specified replay recording. @@ -298,14 +298,14 @@ async def start( self, id: str, *, - framerate: int | NotGiven = NOT_GIVEN, - max_duration_in_seconds: int | NotGiven = NOT_GIVEN, + framerate: int | Omit = omit, + max_duration_in_seconds: int | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReplayStartResponse: """ Start recording the browser session and return a replay ID. @@ -350,7 +350,7 @@ async def stop( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Stop the specified replay recording and persist the video. diff --git a/src/kernel/resources/deployments.py b/src/kernel/resources/deployments.py index 5c7715de..15812440 100644 --- a/src/kernel/resources/deployments.py +++ b/src/kernel/resources/deployments.py @@ -8,7 +8,7 @@ import httpx from ..types import deployment_list_params, deployment_create_params, deployment_follow_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes +from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -54,16 +54,16 @@ def create( *, entrypoint_rel_path: str, file: FileTypes, - env_vars: Dict[str, str] | NotGiven = NOT_GIVEN, - force: bool | NotGiven = NOT_GIVEN, - region: Literal["aws.us-east-1a"] | NotGiven = NOT_GIVEN, - version: str | NotGiven = NOT_GIVEN, + env_vars: Dict[str, str] | Omit = omit, + force: bool | Omit = omit, + region: Literal["aws.us-east-1a"] | Omit = omit, + version: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeploymentCreateResponse: """ Create a new deployment. @@ -124,7 +124,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeploymentRetrieveResponse: """ Get information about a deployment's status. @@ -151,15 +151,15 @@ def retrieve( def list( self, *, - app_name: str | NotGiven = NOT_GIVEN, - limit: int | NotGiven = NOT_GIVEN, - offset: int | NotGiven = NOT_GIVEN, + app_name: str | Omit = omit, + limit: int | Omit = omit, + offset: int | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncOffsetPagination[DeploymentListResponse]: """List deployments. @@ -204,13 +204,13 @@ def follow( self, id: str, *, - since: str | NotGiven = NOT_GIVEN, + since: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[DeploymentFollowResponse]: """ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and @@ -273,16 +273,16 @@ async def create( *, entrypoint_rel_path: str, file: FileTypes, - env_vars: Dict[str, str] | NotGiven = NOT_GIVEN, - force: bool | NotGiven = NOT_GIVEN, - region: Literal["aws.us-east-1a"] | NotGiven = NOT_GIVEN, - version: str | NotGiven = NOT_GIVEN, + env_vars: Dict[str, str] | Omit = omit, + force: bool | Omit = omit, + region: Literal["aws.us-east-1a"] | Omit = omit, + version: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeploymentCreateResponse: """ Create a new deployment. @@ -343,7 +343,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeploymentRetrieveResponse: """ Get information about a deployment's status. @@ -370,15 +370,15 @@ async def retrieve( def list( self, *, - app_name: str | NotGiven = NOT_GIVEN, - limit: int | NotGiven = NOT_GIVEN, - offset: int | NotGiven = NOT_GIVEN, + app_name: str | Omit = omit, + limit: int | Omit = omit, + offset: int | 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[DeploymentListResponse, AsyncOffsetPagination[DeploymentListResponse]]: """List deployments. @@ -423,13 +423,13 @@ async def follow( self, id: str, *, - since: str | NotGiven = NOT_GIVEN, + since: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[DeploymentFollowResponse]: """ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and diff --git a/src/kernel/resources/invocations.py b/src/kernel/resources/invocations.py index 3de46d0b..2a3848a0 100644 --- a/src/kernel/resources/invocations.py +++ b/src/kernel/resources/invocations.py @@ -8,7 +8,7 @@ import httpx from ..types import invocation_create_params, invocation_update_params -from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +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 from .._resource import SyncAPIResource, AsyncAPIResource @@ -54,14 +54,14 @@ def create( action_name: str, app_name: str, version: str, - async_: bool | NotGiven = NOT_GIVEN, - payload: str | NotGiven = NOT_GIVEN, + async_: bool | Omit = omit, + payload: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationCreateResponse: """ Invoke an action. @@ -113,7 +113,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationRetrieveResponse: """ Get details about an invocation's status and output. @@ -142,13 +142,13 @@ def update( id: str, *, status: Literal["succeeded", "failed"], - output: str | NotGiven = NOT_GIVEN, + output: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationUpdateResponse: """ Update an invocation's status or output. @@ -192,7 +192,7 @@ def delete_browsers( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete all browser sessions created within the specified invocation. @@ -226,7 +226,7 @@ def follow( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[InvocationFollowResponse]: """ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and @@ -284,14 +284,14 @@ async def create( action_name: str, app_name: str, version: str, - async_: bool | NotGiven = NOT_GIVEN, - payload: str | NotGiven = NOT_GIVEN, + async_: bool | Omit = omit, + payload: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationCreateResponse: """ Invoke an action. @@ -343,7 +343,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationRetrieveResponse: """ Get details about an invocation's status and output. @@ -372,13 +372,13 @@ async def update( id: str, *, status: Literal["succeeded", "failed"], - output: str | NotGiven = NOT_GIVEN, + output: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationUpdateResponse: """ Update an invocation's status or output. @@ -422,7 +422,7 @@ async def delete_browsers( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete all browser sessions created within the specified invocation. @@ -456,7 +456,7 @@ async def follow( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[InvocationFollowResponse]: """ Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and diff --git a/src/kernel/resources/profiles.py b/src/kernel/resources/profiles.py index 0818cdc9..8d51da38 100644 --- a/src/kernel/resources/profiles.py +++ b/src/kernel/resources/profiles.py @@ -5,7 +5,7 @@ import httpx from ..types import profile_create_params -from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +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 from .._resource import SyncAPIResource, AsyncAPIResource @@ -53,13 +53,13 @@ def with_streaming_response(self) -> ProfilesResourceWithStreamingResponse: def create( self, *, - name: str | NotGiven = NOT_GIVEN, + name: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Profile: """ Create a browser profile that can be used to load state into future browser @@ -94,7 +94,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Profile: """ Retrieve details for a single profile by its ID or name. @@ -126,7 +126,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProfileListResponse: """List profiles with optional filtering and pagination.""" return self._get( @@ -146,7 +146,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a profile by its ID or by its name. @@ -180,7 +180,7 @@ def download( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BinaryAPIResponse: """Download the profile. @@ -231,13 +231,13 @@ def with_streaming_response(self) -> AsyncProfilesResourceWithStreamingResponse: async def create( self, *, - name: str | NotGiven = NOT_GIVEN, + name: 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, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Profile: """ Create a browser profile that can be used to load state into future browser @@ -272,7 +272,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Profile: """ Retrieve details for a single profile by its ID or name. @@ -304,7 +304,7 @@ async def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProfileListResponse: """List profiles with optional filtering and pagination.""" return await self._get( @@ -324,7 +324,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a profile by its ID or by its name. @@ -358,7 +358,7 @@ async def download( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncBinaryAPIResponse: """Download the profile. diff --git a/tests/test_transform.py b/tests/test_transform.py index 5f7ab31c..68ca9b26 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,7 +8,7 @@ import pytest -from kernel._types import NOT_GIVEN, Base64FileInput +from kernel._types import Base64FileInput, omit, not_given from kernel._utils import ( PropertyInfo, transform as _transform, @@ -450,4 +450,11 @@ async def test_transform_skipping(use_async: bool) -> None: @pytest.mark.asyncio async def test_strips_notgiven(use_async: bool) -> None: assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} - assert await transform({"foo_bar": NOT_GIVEN}, Foo1, use_async) == {} + assert await transform({"foo_bar": not_given}, Foo1, use_async) == {} + + +@parametrize +@pytest.mark.asyncio +async def test_strips_omit(use_async: bool) -> None: + assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} + assert await transform({"foo_bar": omit}, Foo1, use_async) == {} From e7e72e6642f7587af34f51608d3bde4112d1e711 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 03:02:13 +0000 Subject: [PATCH 3/6] chore: do not install brew dependencies in ./scripts/bootstrap by default --- scripts/bootstrap | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index e84fe62c..b430fee3 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if ! command -v rye >/dev/null 2>&1 && [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi From 2ecd936567bb98eda0edab68fb970668548bbc00 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 02:34:39 +0000 Subject: [PATCH 4/6] chore: improve example values --- tests/api_resources/test_browsers.py | 24 ++++++++++++------------ tests/api_resources/test_invocations.py | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/api_resources/test_browsers.py b/tests/api_resources/test_browsers.py index be4344f4..f463cf65 100644 --- a/tests/api_resources/test_browsers.py +++ b/tests/api_resources/test_browsers.py @@ -70,7 +70,7 @@ def test_streaming_response_create(self, client: Kernel) -> None: @parametrize def test_method_retrieve(self, client: Kernel) -> None: browser = client.browsers.retrieve( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert_matches_type(BrowserRetrieveResponse, browser, path=["response"]) @@ -78,7 +78,7 @@ def test_method_retrieve(self, client: Kernel) -> None: @parametrize def test_raw_response_retrieve(self, client: Kernel) -> None: response = client.browsers.with_raw_response.retrieve( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert response.is_closed is True @@ -90,7 +90,7 @@ def test_raw_response_retrieve(self, client: Kernel) -> None: @parametrize def test_streaming_response_retrieve(self, client: Kernel) -> None: with client.browsers.with_streaming_response.retrieve( - "id", + "htzv5orfit78e1m2biiifpbv", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -174,7 +174,7 @@ def test_streaming_response_delete(self, client: Kernel) -> None: @parametrize def test_method_delete_by_id(self, client: Kernel) -> None: browser = client.browsers.delete_by_id( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert browser is None @@ -182,7 +182,7 @@ def test_method_delete_by_id(self, client: Kernel) -> None: @parametrize def test_raw_response_delete_by_id(self, client: Kernel) -> None: response = client.browsers.with_raw_response.delete_by_id( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert response.is_closed is True @@ -194,7 +194,7 @@ def test_raw_response_delete_by_id(self, client: Kernel) -> None: @parametrize def test_streaming_response_delete_by_id(self, client: Kernel) -> None: with client.browsers.with_streaming_response.delete_by_id( - "id", + "htzv5orfit78e1m2biiifpbv", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -267,7 +267,7 @@ async def test_streaming_response_create(self, async_client: AsyncKernel) -> Non @parametrize async def test_method_retrieve(self, async_client: AsyncKernel) -> None: browser = await async_client.browsers.retrieve( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert_matches_type(BrowserRetrieveResponse, browser, path=["response"]) @@ -275,7 +275,7 @@ async def test_method_retrieve(self, async_client: AsyncKernel) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: response = await async_client.browsers.with_raw_response.retrieve( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert response.is_closed is True @@ -287,7 +287,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None: async with async_client.browsers.with_streaming_response.retrieve( - "id", + "htzv5orfit78e1m2biiifpbv", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -371,7 +371,7 @@ async def test_streaming_response_delete(self, async_client: AsyncKernel) -> Non @parametrize async def test_method_delete_by_id(self, async_client: AsyncKernel) -> None: browser = await async_client.browsers.delete_by_id( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert browser is None @@ -379,7 +379,7 @@ async def test_method_delete_by_id(self, async_client: AsyncKernel) -> None: @parametrize async def test_raw_response_delete_by_id(self, async_client: AsyncKernel) -> None: response = await async_client.browsers.with_raw_response.delete_by_id( - "id", + "htzv5orfit78e1m2biiifpbv", ) assert response.is_closed is True @@ -391,7 +391,7 @@ async def test_raw_response_delete_by_id(self, async_client: AsyncKernel) -> Non @parametrize async def test_streaming_response_delete_by_id(self, async_client: AsyncKernel) -> None: async with async_client.browsers.with_streaming_response.delete_by_id( - "id", + "htzv5orfit78e1m2biiifpbv", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_invocations.py b/tests/api_resources/test_invocations.py index 852f7f94..38734f85 100644 --- a/tests/api_resources/test_invocations.py +++ b/tests/api_resources/test_invocations.py @@ -77,7 +77,7 @@ def test_streaming_response_create(self, client: Kernel) -> None: @parametrize def test_method_retrieve(self, client: Kernel) -> None: invocation = client.invocations.retrieve( - "id", + "rr33xuugxj9h0bkf1rdt2bet", ) assert_matches_type(InvocationRetrieveResponse, invocation, path=["response"]) @@ -85,7 +85,7 @@ def test_method_retrieve(self, client: Kernel) -> None: @parametrize def test_raw_response_retrieve(self, client: Kernel) -> None: response = client.invocations.with_raw_response.retrieve( - "id", + "rr33xuugxj9h0bkf1rdt2bet", ) assert response.is_closed is True @@ -97,7 +97,7 @@ def test_raw_response_retrieve(self, client: Kernel) -> None: @parametrize def test_streaming_response_retrieve(self, client: Kernel) -> None: with client.invocations.with_streaming_response.retrieve( - "id", + "rr33xuugxj9h0bkf1rdt2bet", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -316,7 +316,7 @@ async def test_streaming_response_create(self, async_client: AsyncKernel) -> Non @parametrize async def test_method_retrieve(self, async_client: AsyncKernel) -> None: invocation = await async_client.invocations.retrieve( - "id", + "rr33xuugxj9h0bkf1rdt2bet", ) assert_matches_type(InvocationRetrieveResponse, invocation, path=["response"]) @@ -324,7 +324,7 @@ async def test_method_retrieve(self, async_client: AsyncKernel) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: response = await async_client.invocations.with_raw_response.retrieve( - "id", + "rr33xuugxj9h0bkf1rdt2bet", ) assert response.is_closed is True @@ -336,7 +336,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None: async with async_client.invocations.with_streaming_response.retrieve( - "id", + "rr33xuugxj9h0bkf1rdt2bet", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" From 9c8ccbfb59c6e7f9c5b649193ab10580d1d750e9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 17:27:56 +0000 Subject: [PATCH 5/6] feat: Add stainless CI --- .stats.yml | 8 +- api.md | 15 + src/kernel/_client.py | 10 +- src/kernel/resources/__init__.py | 14 + src/kernel/resources/browsers/browsers.py | 20 +- src/kernel/resources/invocations.py | 12 +- src/kernel/resources/proxies.py | 409 ++++++++++++++++++++ src/kernel/types/__init__.py | 4 + src/kernel/types/browser_create_params.py | 11 +- src/kernel/types/proxy_create_params.py | 175 +++++++++ src/kernel/types/proxy_create_response.py | 179 +++++++++ src/kernel/types/proxy_list_response.py | 183 +++++++++ src/kernel/types/proxy_retrieve_response.py | 179 +++++++++ tests/api_resources/test_browsers.py | 6 +- tests/api_resources/test_proxies.py | 336 ++++++++++++++++ 15 files changed, 1547 insertions(+), 14 deletions(-) create mode 100644 src/kernel/resources/proxies.py create mode 100644 src/kernel/types/proxy_create_params.py create mode 100644 src/kernel/types/proxy_create_response.py create mode 100644 src/kernel/types/proxy_list_response.py create mode 100644 src/kernel/types/proxy_retrieve_response.py create mode 100644 tests/api_resources/test_proxies.py diff --git a/.stats.yml b/.stats.yml index 7fb3d31e..385372f3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 46 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cb38560915edce03abce2ae3ef5bc745489dbe9b6f80c2b4ff42edf8c2ff276d.yml -openapi_spec_hash: a869194d6c864ba28d79ec0105439c3e -config_hash: ed56f95781ec9b2e73c97e1a66606071 +configured_endpoints: 50 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d3a597bbbb25c131e2c06eb9b47d70932d14a97a6f916677a195a128e196f4db.yml +openapi_spec_hash: c967b384624017eed0abff1b53a74530 +config_hash: 0d150b61cae2dc57d3648ceae7784966 diff --git a/api.md b/api.md index 56d852bc..21ccdb73 100644 --- a/api.md +++ b/api.md @@ -178,3 +178,18 @@ Methods: - client.profiles.list() -> ProfileListResponse - client.profiles.delete(id_or_name) -> None - client.profiles.download(id_or_name) -> BinaryAPIResponse + +# Proxies + +Types: + +```python +from kernel.types import ProxyCreateResponse, ProxyRetrieveResponse, ProxyListResponse +``` + +Methods: + +- client.proxies.create(\*\*params) -> ProxyCreateResponse +- client.proxies.retrieve(id) -> ProxyRetrieveResponse +- client.proxies.list() -> ProxyListResponse +- client.proxies.delete(id) -> None diff --git a/src/kernel/_client.py b/src/kernel/_client.py index 830aeb58..2821af63 100644 --- a/src/kernel/_client.py +++ b/src/kernel/_client.py @@ -21,7 +21,7 @@ ) from ._utils import is_given, get_async_library from ._version import __version__ -from .resources import apps, profiles, deployments, invocations +from .resources import apps, proxies, profiles, deployments, invocations from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import KernelError, APIStatusError from ._base_client import ( @@ -55,6 +55,7 @@ class Kernel(SyncAPIClient): invocations: invocations.InvocationsResource browsers: browsers.BrowsersResource profiles: profiles.ProfilesResource + proxies: proxies.ProxiesResource with_raw_response: KernelWithRawResponse with_streaming_response: KernelWithStreamedResponse @@ -141,6 +142,7 @@ def __init__( self.invocations = invocations.InvocationsResource(self) self.browsers = browsers.BrowsersResource(self) self.profiles = profiles.ProfilesResource(self) + self.proxies = proxies.ProxiesResource(self) self.with_raw_response = KernelWithRawResponse(self) self.with_streaming_response = KernelWithStreamedResponse(self) @@ -257,6 +259,7 @@ class AsyncKernel(AsyncAPIClient): invocations: invocations.AsyncInvocationsResource browsers: browsers.AsyncBrowsersResource profiles: profiles.AsyncProfilesResource + proxies: proxies.AsyncProxiesResource with_raw_response: AsyncKernelWithRawResponse with_streaming_response: AsyncKernelWithStreamedResponse @@ -343,6 +346,7 @@ def __init__( self.invocations = invocations.AsyncInvocationsResource(self) self.browsers = browsers.AsyncBrowsersResource(self) self.profiles = profiles.AsyncProfilesResource(self) + self.proxies = proxies.AsyncProxiesResource(self) self.with_raw_response = AsyncKernelWithRawResponse(self) self.with_streaming_response = AsyncKernelWithStreamedResponse(self) @@ -460,6 +464,7 @@ def __init__(self, client: Kernel) -> None: self.invocations = invocations.InvocationsResourceWithRawResponse(client.invocations) self.browsers = browsers.BrowsersResourceWithRawResponse(client.browsers) self.profiles = profiles.ProfilesResourceWithRawResponse(client.profiles) + self.proxies = proxies.ProxiesResourceWithRawResponse(client.proxies) class AsyncKernelWithRawResponse: @@ -469,6 +474,7 @@ def __init__(self, client: AsyncKernel) -> None: self.invocations = invocations.AsyncInvocationsResourceWithRawResponse(client.invocations) self.browsers = browsers.AsyncBrowsersResourceWithRawResponse(client.browsers) self.profiles = profiles.AsyncProfilesResourceWithRawResponse(client.profiles) + self.proxies = proxies.AsyncProxiesResourceWithRawResponse(client.proxies) class KernelWithStreamedResponse: @@ -478,6 +484,7 @@ def __init__(self, client: Kernel) -> None: self.invocations = invocations.InvocationsResourceWithStreamingResponse(client.invocations) self.browsers = browsers.BrowsersResourceWithStreamingResponse(client.browsers) self.profiles = profiles.ProfilesResourceWithStreamingResponse(client.profiles) + self.proxies = proxies.ProxiesResourceWithStreamingResponse(client.proxies) class AsyncKernelWithStreamedResponse: @@ -487,6 +494,7 @@ def __init__(self, client: AsyncKernel) -> None: self.invocations = invocations.AsyncInvocationsResourceWithStreamingResponse(client.invocations) self.browsers = browsers.AsyncBrowsersResourceWithStreamingResponse(client.browsers) self.profiles = profiles.AsyncProfilesResourceWithStreamingResponse(client.profiles) + self.proxies = proxies.AsyncProxiesResourceWithStreamingResponse(client.proxies) Client = Kernel diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py index 964da373..23b6b077 100644 --- a/src/kernel/resources/__init__.py +++ b/src/kernel/resources/__init__.py @@ -8,6 +8,14 @@ AppsResourceWithStreamingResponse, AsyncAppsResourceWithStreamingResponse, ) +from .proxies import ( + ProxiesResource, + AsyncProxiesResource, + ProxiesResourceWithRawResponse, + AsyncProxiesResourceWithRawResponse, + ProxiesResourceWithStreamingResponse, + AsyncProxiesResourceWithStreamingResponse, +) from .browsers import ( BrowsersResource, AsyncBrowsersResource, @@ -72,4 +80,10 @@ "AsyncProfilesResourceWithRawResponse", "ProfilesResourceWithStreamingResponse", "AsyncProfilesResourceWithStreamingResponse", + "ProxiesResource", + "AsyncProxiesResource", + "ProxiesResourceWithRawResponse", + "AsyncProxiesResourceWithRawResponse", + "ProxiesResourceWithStreamingResponse", + "AsyncProxiesResourceWithStreamingResponse", ] diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py index e871c215..145d0831 100644 --- a/src/kernel/resources/browsers/browsers.py +++ b/src/kernel/resources/browsers/browsers.py @@ -99,6 +99,7 @@ def create( invocation_id: str | Omit = omit, persistence: BrowserPersistenceParam | Omit = omit, profile: browser_create_params.Profile | Omit = omit, + proxy_id: str | Omit = omit, stealth: bool | Omit = omit, timeout_seconds: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -123,12 +124,18 @@ def create( specified, the matching profile will be loaded into the browser session. Profiles must be created beforehand. + proxy_id: Optional proxy to associate to the browser session. Must reference a proxy + belonging to the caller's org. + stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. timeout_seconds: The number of seconds of inactivity before the browser session is terminated. Only applicable to non-persistent browsers. Activity includes CDP connections - and live view connections. Defaults to 60 seconds. + and live view connections. Defaults to 60 seconds. Minimum allowed is 10 + seconds. Maximum allowed is 86400 (24 hours). We check for inactivity every 5 + seconds, so the actual timeout behavior you will see is +/- 5 seconds around the + specified value. extra_headers: Send extra headers @@ -146,6 +153,7 @@ def create( "invocation_id": invocation_id, "persistence": persistence, "profile": profile, + "proxy_id": proxy_id, "stealth": stealth, "timeout_seconds": timeout_seconds, }, @@ -325,6 +333,7 @@ async def create( invocation_id: str | Omit = omit, persistence: BrowserPersistenceParam | Omit = omit, profile: browser_create_params.Profile | Omit = omit, + proxy_id: str | Omit = omit, stealth: bool | Omit = omit, timeout_seconds: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -349,12 +358,18 @@ async def create( specified, the matching profile will be loaded into the browser session. Profiles must be created beforehand. + proxy_id: Optional proxy to associate to the browser session. Must reference a proxy + belonging to the caller's org. + stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. timeout_seconds: The number of seconds of inactivity before the browser session is terminated. Only applicable to non-persistent browsers. Activity includes CDP connections - and live view connections. Defaults to 60 seconds. + and live view connections. Defaults to 60 seconds. Minimum allowed is 10 + seconds. Maximum allowed is 86400 (24 hours). We check for inactivity every 5 + seconds, so the actual timeout behavior you will see is +/- 5 seconds around the + specified value. extra_headers: Send extra headers @@ -372,6 +387,7 @@ async def create( "invocation_id": invocation_id, "persistence": persistence, "profile": profile, + "proxy_id": proxy_id, "stealth": stealth, "timeout_seconds": timeout_seconds, }, diff --git a/src/kernel/resources/invocations.py b/src/kernel/resources/invocations.py index 2a3848a0..8b5c1bc4 100644 --- a/src/kernel/resources/invocations.py +++ b/src/kernel/resources/invocations.py @@ -150,8 +150,10 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationUpdateResponse: - """ - Update an invocation's status or output. + """Update an invocation's status or output. + + This can used to cancel an invocation + by setting the status to "failed". Args: status: New status for the invocation. @@ -380,8 +382,10 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvocationUpdateResponse: - """ - Update an invocation's status or output. + """Update an invocation's status or output. + + This can used to cancel an invocation + by setting the status to "failed". Args: status: New status for the invocation. diff --git a/src/kernel/resources/proxies.py b/src/kernel/resources/proxies.py new file mode 100644 index 00000000..886c423b --- /dev/null +++ b/src/kernel/resources/proxies.py @@ -0,0 +1,409 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from ..types import proxy_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 +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.proxy_list_response import ProxyListResponse +from ..types.proxy_create_response import ProxyCreateResponse +from ..types.proxy_retrieve_response import ProxyRetrieveResponse + +__all__ = ["ProxiesResource", "AsyncProxiesResource"] + + +class ProxiesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ProxiesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers + """ + return ProxiesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ProxiesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response + """ + return ProxiesResourceWithStreamingResponse(self) + + def create( + self, + *, + type: Literal["datacenter", "isp", "residential", "mobile", "custom"], + config: proxy_create_params.Config | Omit = omit, + name: 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, + ) -> ProxyCreateResponse: + """ + Create a new proxy configuration for the caller's organization. + + Args: + type: Proxy type to use. In terms of quality for avoiding bot-detection, from best to + worst: `mobile` > `residential` > `isp` > `datacenter`. + + config: Configuration specific to the selected proxy `type`. + + name: Readable name of the proxy. + + 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._post( + "/proxies", + body=maybe_transform( + { + "type": type, + "config": config, + "name": name, + }, + proxy_create_params.ProxyCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyCreateResponse, + ) + + def retrieve( + self, + id: str, + *, + # 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, + ) -> ProxyRetrieveResponse: + """ + Retrieve a proxy belonging to the caller's organization by ID. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + f"/proxies/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyRetrieveResponse, + ) + + def list( + self, + *, + # 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, + ) -> ProxyListResponse: + """List proxies owned by the caller's organization.""" + return self._get( + "/proxies", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyListResponse, + ) + + def delete( + self, + id: str, + *, + # 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, + ) -> None: + """Soft delete a proxy. + + Sessions referencing it are not modified. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/proxies/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncProxiesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncProxiesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/onkernel/kernel-python-sdk#accessing-raw-response-data-eg-headers + """ + return AsyncProxiesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncProxiesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/onkernel/kernel-python-sdk#with_streaming_response + """ + return AsyncProxiesResourceWithStreamingResponse(self) + + async def create( + self, + *, + type: Literal["datacenter", "isp", "residential", "mobile", "custom"], + config: proxy_create_params.Config | Omit = omit, + name: 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, + ) -> ProxyCreateResponse: + """ + Create a new proxy configuration for the caller's organization. + + Args: + type: Proxy type to use. In terms of quality for avoiding bot-detection, from best to + worst: `mobile` > `residential` > `isp` > `datacenter`. + + config: Configuration specific to the selected proxy `type`. + + name: Readable name of the proxy. + + 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 await self._post( + "/proxies", + body=await async_maybe_transform( + { + "type": type, + "config": config, + "name": name, + }, + proxy_create_params.ProxyCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyCreateResponse, + ) + + async def retrieve( + self, + id: str, + *, + # 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, + ) -> ProxyRetrieveResponse: + """ + Retrieve a proxy belonging to the caller's organization by ID. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + f"/proxies/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyRetrieveResponse, + ) + + async def list( + self, + *, + # 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, + ) -> ProxyListResponse: + """List proxies owned by the caller's organization.""" + return await self._get( + "/proxies", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyListResponse, + ) + + async def delete( + self, + id: str, + *, + # 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, + ) -> None: + """Soft delete a proxy. + + Sessions referencing it are not modified. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/proxies/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class ProxiesResourceWithRawResponse: + def __init__(self, proxies: ProxiesResource) -> None: + self._proxies = proxies + + self.create = to_raw_response_wrapper( + proxies.create, + ) + self.retrieve = to_raw_response_wrapper( + proxies.retrieve, + ) + self.list = to_raw_response_wrapper( + proxies.list, + ) + self.delete = to_raw_response_wrapper( + proxies.delete, + ) + + +class AsyncProxiesResourceWithRawResponse: + def __init__(self, proxies: AsyncProxiesResource) -> None: + self._proxies = proxies + + self.create = async_to_raw_response_wrapper( + proxies.create, + ) + self.retrieve = async_to_raw_response_wrapper( + proxies.retrieve, + ) + self.list = async_to_raw_response_wrapper( + proxies.list, + ) + self.delete = async_to_raw_response_wrapper( + proxies.delete, + ) + + +class ProxiesResourceWithStreamingResponse: + def __init__(self, proxies: ProxiesResource) -> None: + self._proxies = proxies + + self.create = to_streamed_response_wrapper( + proxies.create, + ) + self.retrieve = to_streamed_response_wrapper( + proxies.retrieve, + ) + self.list = to_streamed_response_wrapper( + proxies.list, + ) + self.delete = to_streamed_response_wrapper( + proxies.delete, + ) + + +class AsyncProxiesResourceWithStreamingResponse: + def __init__(self, proxies: AsyncProxiesResource) -> None: + self._proxies = proxies + + self.create = async_to_streamed_response_wrapper( + proxies.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + proxies.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + proxies.list, + ) + self.delete = async_to_streamed_response_wrapper( + proxies.delete, + ) diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py index 3c17469d..e571af62 100644 --- a/src/kernel/types/__init__.py +++ b/src/kernel/types/__init__.py @@ -14,15 +14,19 @@ from .app_list_params import AppListParams as AppListParams from .app_list_response import AppListResponse as AppListResponse from .browser_persistence import BrowserPersistence as BrowserPersistence +from .proxy_create_params import ProxyCreateParams as ProxyCreateParams +from .proxy_list_response import ProxyListResponse as ProxyListResponse from .browser_create_params import BrowserCreateParams as BrowserCreateParams from .browser_delete_params import BrowserDeleteParams as BrowserDeleteParams from .browser_list_response import BrowserListResponse as BrowserListResponse 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 .deployment_list_params import DeploymentListParams as DeploymentListParams from .deployment_state_event import DeploymentStateEvent as DeploymentStateEvent from .invocation_state_event import InvocationStateEvent as InvocationStateEvent from .browser_create_response import BrowserCreateResponse as BrowserCreateResponse +from .proxy_retrieve_response import ProxyRetrieveResponse as ProxyRetrieveResponse from .deployment_create_params import DeploymentCreateParams as DeploymentCreateParams from .deployment_follow_params import DeploymentFollowParams as DeploymentFollowParams from .deployment_list_response import DeploymentListResponse as DeploymentListResponse diff --git a/src/kernel/types/browser_create_params.py b/src/kernel/types/browser_create_params.py index b9bb3303..ed65be6f 100644 --- a/src/kernel/types/browser_create_params.py +++ b/src/kernel/types/browser_create_params.py @@ -29,6 +29,12 @@ class BrowserCreateParams(TypedDict, total=False): into the browser session. Profiles must be created beforehand. """ + proxy_id: str + """Optional proxy to associate to the browser session. + + Must reference a proxy belonging to the caller's org. + """ + stealth: bool """ If true, launches the browser in stealth mode to reduce detection by anti-bot @@ -39,7 +45,10 @@ class BrowserCreateParams(TypedDict, total=False): """The number of seconds of inactivity before the browser session is terminated. Only applicable to non-persistent browsers. Activity includes CDP connections - and live view connections. Defaults to 60 seconds. + and live view connections. Defaults to 60 seconds. Minimum allowed is 10 + seconds. Maximum allowed is 86400 (24 hours). We check for inactivity every 5 + seconds, so the actual timeout behavior you will see is +/- 5 seconds around the + specified value. """ diff --git a/src/kernel/types/proxy_create_params.py b/src/kernel/types/proxy_create_params.py new file mode 100644 index 00000000..7af31f4a --- /dev/null +++ b/src/kernel/types/proxy_create_params.py @@ -0,0 +1,175 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +__all__ = [ + "ProxyCreateParams", + "Config", + "ConfigDatacenterProxyConfig", + "ConfigIspProxyConfig", + "ConfigResidentialProxyConfig", + "ConfigMobileProxyConfig", + "ConfigCreateCustomProxyConfig", +] + + +class ProxyCreateParams(TypedDict, total=False): + type: Required[Literal["datacenter", "isp", "residential", "mobile", "custom"]] + """Proxy type to use. + + In terms of quality for avoiding bot-detection, from best to worst: `mobile` > + `residential` > `isp` > `datacenter`. + """ + + config: Config + """Configuration specific to the selected proxy `type`.""" + + name: str + """Readable name of the proxy.""" + + +class ConfigDatacenterProxyConfig(TypedDict, total=False): + country: Required[str] + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ConfigIspProxyConfig(TypedDict, total=False): + country: Required[str] + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ConfigResidentialProxyConfig(TypedDict, total=False): + asn: str + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + city: str + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: str + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + os: Literal["windows", "macos", "android"] + """Operating system of the residential device.""" + + state: str + """Two-letter state code.""" + + zip: str + """US ZIP code.""" + + +class ConfigMobileProxyConfig(TypedDict, total=False): + asn: str + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + carrier: Literal[ + "a1", + "aircel", + "airtel", + "att", + "celcom", + "chinamobile", + "claro", + "comcast", + "cox", + "digi", + "dt", + "docomo", + "dtac", + "etisalat", + "idea", + "kyivstar", + "meo", + "megafon", + "mtn", + "mtnza", + "mts", + "optus", + "orange", + "qwest", + "reliance_jio", + "robi", + "sprint", + "telefonica", + "telstra", + "tmobile", + "tigo", + "tim", + "verizon", + "vimpelcom", + "vodacomza", + "vodafone", + "vivo", + "zain", + "vivabo", + "telenormyanmar", + "kcelljsc", + "swisscom", + "singtel", + "asiacell", + "windit", + "cellc", + "ooredoo", + "drei", + "umobile", + "cableone", + "proximus", + "tele2", + "mobitel", + "o2", + "bouygues", + "free", + "sfr", + "digicel", + ] + """Mobile carrier.""" + + city: str + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: str + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + state: str + """Two-letter state code.""" + + zip: str + """US ZIP code.""" + + +class ConfigCreateCustomProxyConfig(TypedDict, total=False): + host: Required[str] + """Proxy host address or IP.""" + + port: Required[int] + """Proxy port.""" + + password: str + """Password for proxy authentication.""" + + username: str + """Username for proxy authentication.""" + + +Config: TypeAlias = Union[ + ConfigDatacenterProxyConfig, + ConfigIspProxyConfig, + ConfigResidentialProxyConfig, + ConfigMobileProxyConfig, + ConfigCreateCustomProxyConfig, +] diff --git a/src/kernel/types/proxy_create_response.py b/src/kernel/types/proxy_create_response.py new file mode 100644 index 00000000..42be61d1 --- /dev/null +++ b/src/kernel/types/proxy_create_response.py @@ -0,0 +1,179 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from typing_extensions import Literal, TypeAlias + +from .._models import BaseModel + +__all__ = [ + "ProxyCreateResponse", + "Config", + "ConfigDatacenterProxyConfig", + "ConfigIspProxyConfig", + "ConfigResidentialProxyConfig", + "ConfigMobileProxyConfig", + "ConfigCustomProxyConfig", +] + + +class ConfigDatacenterProxyConfig(BaseModel): + country: str + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ConfigIspProxyConfig(BaseModel): + country: str + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ConfigResidentialProxyConfig(BaseModel): + asn: Optional[str] = None + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + city: Optional[str] = None + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: Optional[str] = None + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + os: Optional[Literal["windows", "macos", "android"]] = None + """Operating system of the residential device.""" + + state: Optional[str] = None + """Two-letter state code.""" + + zip: Optional[str] = None + """US ZIP code.""" + + +class ConfigMobileProxyConfig(BaseModel): + asn: Optional[str] = None + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + carrier: Optional[ + Literal[ + "a1", + "aircel", + "airtel", + "att", + "celcom", + "chinamobile", + "claro", + "comcast", + "cox", + "digi", + "dt", + "docomo", + "dtac", + "etisalat", + "idea", + "kyivstar", + "meo", + "megafon", + "mtn", + "mtnza", + "mts", + "optus", + "orange", + "qwest", + "reliance_jio", + "robi", + "sprint", + "telefonica", + "telstra", + "tmobile", + "tigo", + "tim", + "verizon", + "vimpelcom", + "vodacomza", + "vodafone", + "vivo", + "zain", + "vivabo", + "telenormyanmar", + "kcelljsc", + "swisscom", + "singtel", + "asiacell", + "windit", + "cellc", + "ooredoo", + "drei", + "umobile", + "cableone", + "proximus", + "tele2", + "mobitel", + "o2", + "bouygues", + "free", + "sfr", + "digicel", + ] + ] = None + """Mobile carrier.""" + + city: Optional[str] = None + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: Optional[str] = None + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + state: Optional[str] = None + """Two-letter state code.""" + + zip: Optional[str] = None + """US ZIP code.""" + + +class ConfigCustomProxyConfig(BaseModel): + host: str + """Proxy host address or IP.""" + + port: int + """Proxy port.""" + + has_password: Optional[bool] = None + """Whether the proxy has a password.""" + + username: Optional[str] = None + """Username for proxy authentication.""" + + +Config: TypeAlias = Union[ + ConfigDatacenterProxyConfig, + ConfigIspProxyConfig, + ConfigResidentialProxyConfig, + ConfigMobileProxyConfig, + ConfigCustomProxyConfig, +] + + +class ProxyCreateResponse(BaseModel): + type: Literal["datacenter", "isp", "residential", "mobile", "custom"] + """Proxy type to use. + + In terms of quality for avoiding bot-detection, from best to worst: `mobile` > + `residential` > `isp` > `datacenter`. + """ + + id: Optional[str] = None + + config: Optional[Config] = None + """Configuration specific to the selected proxy `type`.""" + + name: Optional[str] = None + """Readable name of the proxy.""" diff --git a/src/kernel/types/proxy_list_response.py b/src/kernel/types/proxy_list_response.py new file mode 100644 index 00000000..99367c84 --- /dev/null +++ b/src/kernel/types/proxy_list_response.py @@ -0,0 +1,183 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from .._models import BaseModel + +__all__ = [ + "ProxyListResponse", + "ProxyListResponseItem", + "ProxyListResponseItemConfig", + "ProxyListResponseItemConfigDatacenterProxyConfig", + "ProxyListResponseItemConfigIspProxyConfig", + "ProxyListResponseItemConfigResidentialProxyConfig", + "ProxyListResponseItemConfigMobileProxyConfig", + "ProxyListResponseItemConfigCustomProxyConfig", +] + + +class ProxyListResponseItemConfigDatacenterProxyConfig(BaseModel): + country: str + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ProxyListResponseItemConfigIspProxyConfig(BaseModel): + country: str + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ProxyListResponseItemConfigResidentialProxyConfig(BaseModel): + asn: Optional[str] = None + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + city: Optional[str] = None + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: Optional[str] = None + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + os: Optional[Literal["windows", "macos", "android"]] = None + """Operating system of the residential device.""" + + state: Optional[str] = None + """Two-letter state code.""" + + zip: Optional[str] = None + """US ZIP code.""" + + +class ProxyListResponseItemConfigMobileProxyConfig(BaseModel): + asn: Optional[str] = None + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + carrier: Optional[ + Literal[ + "a1", + "aircel", + "airtel", + "att", + "celcom", + "chinamobile", + "claro", + "comcast", + "cox", + "digi", + "dt", + "docomo", + "dtac", + "etisalat", + "idea", + "kyivstar", + "meo", + "megafon", + "mtn", + "mtnza", + "mts", + "optus", + "orange", + "qwest", + "reliance_jio", + "robi", + "sprint", + "telefonica", + "telstra", + "tmobile", + "tigo", + "tim", + "verizon", + "vimpelcom", + "vodacomza", + "vodafone", + "vivo", + "zain", + "vivabo", + "telenormyanmar", + "kcelljsc", + "swisscom", + "singtel", + "asiacell", + "windit", + "cellc", + "ooredoo", + "drei", + "umobile", + "cableone", + "proximus", + "tele2", + "mobitel", + "o2", + "bouygues", + "free", + "sfr", + "digicel", + ] + ] = None + """Mobile carrier.""" + + city: Optional[str] = None + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: Optional[str] = None + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + state: Optional[str] = None + """Two-letter state code.""" + + zip: Optional[str] = None + """US ZIP code.""" + + +class ProxyListResponseItemConfigCustomProxyConfig(BaseModel): + host: str + """Proxy host address or IP.""" + + port: int + """Proxy port.""" + + has_password: Optional[bool] = None + """Whether the proxy has a password.""" + + username: Optional[str] = None + """Username for proxy authentication.""" + + +ProxyListResponseItemConfig: TypeAlias = Union[ + ProxyListResponseItemConfigDatacenterProxyConfig, + ProxyListResponseItemConfigIspProxyConfig, + ProxyListResponseItemConfigResidentialProxyConfig, + ProxyListResponseItemConfigMobileProxyConfig, + ProxyListResponseItemConfigCustomProxyConfig, +] + + +class ProxyListResponseItem(BaseModel): + type: Literal["datacenter", "isp", "residential", "mobile", "custom"] + """Proxy type to use. + + In terms of quality for avoiding bot-detection, from best to worst: `mobile` > + `residential` > `isp` > `datacenter`. + """ + + id: Optional[str] = None + + config: Optional[ProxyListResponseItemConfig] = None + """Configuration specific to the selected proxy `type`.""" + + name: Optional[str] = None + """Readable name of the proxy.""" + + +ProxyListResponse: TypeAlias = List[ProxyListResponseItem] diff --git a/src/kernel/types/proxy_retrieve_response.py b/src/kernel/types/proxy_retrieve_response.py new file mode 100644 index 00000000..cb4b4649 --- /dev/null +++ b/src/kernel/types/proxy_retrieve_response.py @@ -0,0 +1,179 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from typing_extensions import Literal, TypeAlias + +from .._models import BaseModel + +__all__ = [ + "ProxyRetrieveResponse", + "Config", + "ConfigDatacenterProxyConfig", + "ConfigIspProxyConfig", + "ConfigResidentialProxyConfig", + "ConfigMobileProxyConfig", + "ConfigCustomProxyConfig", +] + + +class ConfigDatacenterProxyConfig(BaseModel): + country: str + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ConfigIspProxyConfig(BaseModel): + country: str + """ISO 3166 country code or EU for the proxy exit node.""" + + +class ConfigResidentialProxyConfig(BaseModel): + asn: Optional[str] = None + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + city: Optional[str] = None + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: Optional[str] = None + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + os: Optional[Literal["windows", "macos", "android"]] = None + """Operating system of the residential device.""" + + state: Optional[str] = None + """Two-letter state code.""" + + zip: Optional[str] = None + """US ZIP code.""" + + +class ConfigMobileProxyConfig(BaseModel): + asn: Optional[str] = None + """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html""" + + carrier: Optional[ + Literal[ + "a1", + "aircel", + "airtel", + "att", + "celcom", + "chinamobile", + "claro", + "comcast", + "cox", + "digi", + "dt", + "docomo", + "dtac", + "etisalat", + "idea", + "kyivstar", + "meo", + "megafon", + "mtn", + "mtnza", + "mts", + "optus", + "orange", + "qwest", + "reliance_jio", + "robi", + "sprint", + "telefonica", + "telstra", + "tmobile", + "tigo", + "tim", + "verizon", + "vimpelcom", + "vodacomza", + "vodafone", + "vivo", + "zain", + "vivabo", + "telenormyanmar", + "kcelljsc", + "swisscom", + "singtel", + "asiacell", + "windit", + "cellc", + "ooredoo", + "drei", + "umobile", + "cableone", + "proximus", + "tele2", + "mobitel", + "o2", + "bouygues", + "free", + "sfr", + "digicel", + ] + ] = None + """Mobile carrier.""" + + city: Optional[str] = None + """City name (no spaces, e.g. + + `sanfrancisco`). If provided, `country` must also be provided. + """ + + country: Optional[str] = None + """ISO 3166 country code or EU for the proxy exit node. + + Required if `city` is provided. + """ + + state: Optional[str] = None + """Two-letter state code.""" + + zip: Optional[str] = None + """US ZIP code.""" + + +class ConfigCustomProxyConfig(BaseModel): + host: str + """Proxy host address or IP.""" + + port: int + """Proxy port.""" + + has_password: Optional[bool] = None + """Whether the proxy has a password.""" + + username: Optional[str] = None + """Username for proxy authentication.""" + + +Config: TypeAlias = Union[ + ConfigDatacenterProxyConfig, + ConfigIspProxyConfig, + ConfigResidentialProxyConfig, + ConfigMobileProxyConfig, + ConfigCustomProxyConfig, +] + + +class ProxyRetrieveResponse(BaseModel): + type: Literal["datacenter", "isp", "residential", "mobile", "custom"] + """Proxy type to use. + + In terms of quality for avoiding bot-detection, from best to worst: `mobile` > + `residential` > `isp` > `datacenter`. + """ + + id: Optional[str] = None + + config: Optional[Config] = None + """Configuration specific to the selected proxy `type`.""" + + name: Optional[str] = None + """Readable name of the proxy.""" diff --git a/tests/api_resources/test_browsers.py b/tests/api_resources/test_browsers.py index f463cf65..349d74b4 100644 --- a/tests/api_resources/test_browsers.py +++ b/tests/api_resources/test_browsers.py @@ -39,8 +39,9 @@ def test_method_create_with_all_params(self, client: Kernel) -> None: "name": "name", "save_changes": True, }, + proxy_id="proxy_id", stealth=True, - timeout_seconds=0, + timeout_seconds=10, ) assert_matches_type(BrowserCreateResponse, browser, path=["response"]) @@ -236,8 +237,9 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> "name": "name", "save_changes": True, }, + proxy_id="proxy_id", stealth=True, - timeout_seconds=0, + timeout_seconds=10, ) assert_matches_type(BrowserCreateResponse, browser, path=["response"]) diff --git a/tests/api_resources/test_proxies.py b/tests/api_resources/test_proxies.py new file mode 100644 index 00000000..de295bfa --- /dev/null +++ b/tests/api_resources/test_proxies.py @@ -0,0 +1,336 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from kernel import Kernel, AsyncKernel +from tests.utils import assert_matches_type +from kernel.types import ProxyListResponse, ProxyCreateResponse, ProxyRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestProxies: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: Kernel) -> None: + proxy = client.proxies.create( + type="datacenter", + ) + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: Kernel) -> None: + proxy = client.proxies.create( + type="datacenter", + config={"country": "US"}, + name="name", + ) + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: Kernel) -> None: + response = client.proxies.with_raw_response.create( + type="datacenter", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = response.parse() + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Kernel) -> None: + with client.proxies.with_streaming_response.create( + type="datacenter", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = response.parse() + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: Kernel) -> None: + proxy = client.proxies.retrieve( + "id", + ) + assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Kernel) -> None: + response = client.proxies.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = response.parse() + assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Kernel) -> None: + with client.proxies.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = response.parse() + assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.proxies.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: Kernel) -> None: + proxy = client.proxies.list() + assert_matches_type(ProxyListResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: Kernel) -> None: + response = client.proxies.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = response.parse() + assert_matches_type(ProxyListResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Kernel) -> None: + with client.proxies.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = response.parse() + assert_matches_type(ProxyListResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: Kernel) -> None: + proxy = client.proxies.delete( + "id", + ) + assert proxy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Kernel) -> None: + response = client.proxies.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = response.parse() + assert proxy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Kernel) -> None: + with client.proxies.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = response.parse() + assert proxy is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.proxies.with_raw_response.delete( + "", + ) + + +class TestAsyncProxies: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncKernel) -> None: + proxy = await async_client.proxies.create( + type="datacenter", + ) + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> None: + proxy = await async_client.proxies.create( + type="datacenter", + config={"country": "US"}, + name="name", + ) + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncKernel) -> None: + response = await async_client.proxies.with_raw_response.create( + type="datacenter", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = await response.parse() + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncKernel) -> None: + async with async_client.proxies.with_streaming_response.create( + type="datacenter", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = await response.parse() + assert_matches_type(ProxyCreateResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncKernel) -> None: + proxy = await async_client.proxies.retrieve( + "id", + ) + assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: + response = await async_client.proxies.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = await response.parse() + assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None: + async with async_client.proxies.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = await response.parse() + assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.proxies.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncKernel) -> None: + proxy = await async_client.proxies.list() + assert_matches_type(ProxyListResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncKernel) -> None: + response = await async_client.proxies.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = await response.parse() + assert_matches_type(ProxyListResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncKernel) -> None: + async with async_client.proxies.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = await response.parse() + assert_matches_type(ProxyListResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncKernel) -> None: + proxy = await async_client.proxies.delete( + "id", + ) + assert proxy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncKernel) -> None: + response = await async_client.proxies.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = await response.parse() + assert proxy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncKernel) -> None: + async with async_client.proxies.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = await response.parse() + assert proxy is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.proxies.with_raw_response.delete( + "", + ) From 1965b3b7d60d4c24bd994bbbb5721c804c59235a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 17:38:42 +0000 Subject: [PATCH 6/6] release: 0.11.2 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 16 ++++++++++++++++ pyproject.toml | 2 +- src/kernel/_version.py | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e82003f4..95e4ab67 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.1" + ".": "0.11.2" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d1ad48f..5772793b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 0.11.2 (2025-09-24) + +Full Changelog: [v0.11.1...v0.11.2](https://github.com/onkernel/kernel-python-sdk/compare/v0.11.1...v0.11.2) + +### Features + +* Add stainless CI ([9c8ccbf](https://github.com/onkernel/kernel-python-sdk/commit/9c8ccbfb59c6e7f9c5b649193ab10580d1d750e9)) + + +### Chores + +* do not install brew dependencies in ./scripts/bootstrap by default ([e7e72e6](https://github.com/onkernel/kernel-python-sdk/commit/e7e72e6642f7587af34f51608d3bde4112d1e711)) +* improve example values ([2ecd936](https://github.com/onkernel/kernel-python-sdk/commit/2ecd936567bb98eda0edab68fb970668548bbc00)) +* **internal:** update pydantic dependency ([45de860](https://github.com/onkernel/kernel-python-sdk/commit/45de860fb92aeeccf5ef44dcb2b5ab4a2b7a0592)) +* **types:** change optional parameter type from NotGiven to Omit ([0b85104](https://github.com/onkernel/kernel-python-sdk/commit/0b85104d500907e1f86ad633403fb4c27fb929c4)) + ## 0.11.1 (2025-09-06) Full Changelog: [v0.11.0...v0.11.1](https://github.com/onkernel/kernel-python-sdk/compare/v0.11.0...v0.11.1) diff --git a/pyproject.toml b/pyproject.toml index 5533264c..f6c58357 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.11.1" +version = "0.11.2" 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 0e02001c..a0cd88ab 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.11.1" # x-release-please-version +__version__ = "0.11.2" # x-release-please-version