From 07b55e4a4b65b403b3b6f69b95b221e2020cf30b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 05:32:21 +0000 Subject: [PATCH 1/3] chore(internal): fix ruff target version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5927c84..a4c4b29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -159,7 +159,7 @@ reportPrivateUsage = false [tool.ruff] line-length = 120 output-format = "grouped" -target-version = "py37" +target-version = "py38" [tool.ruff.format] docstring-code-format = true From 14667cdfd06540585ffac570b8963b322cf9ef23 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 21:27:53 +0000 Subject: [PATCH 2/3] feat(api): browser instance file i/o --- .stats.yml | 8 +- api.md | 34 + src/kernel/resources/browsers/__init__.py | 14 + src/kernel/resources/browsers/browsers.py | 32 + src/kernel/resources/browsers/fs/__init__.py | 33 + src/kernel/resources/browsers/fs/fs.py | 1049 +++++++++++++++++ src/kernel/resources/browsers/fs/watch.py | 369 ++++++ src/kernel/types/browsers/__init__.py | 11 + .../browsers/f_create_directory_params.py | 15 + .../browsers/f_delete_directory_params.py | 12 + .../types/browsers/f_delete_file_params.py | 12 + .../types/browsers/f_file_info_params.py | 12 + .../types/browsers/f_file_info_response.py | 27 + .../types/browsers/f_list_files_params.py | 12 + .../types/browsers/f_list_files_response.py | 32 + src/kernel/types/browsers/f_move_params.py | 15 + .../types/browsers/f_read_file_params.py | 12 + .../browsers/f_set_file_permissions_params.py | 21 + .../types/browsers/f_write_file_params.py | 15 + src/kernel/types/browsers/fs/__init__.py | 7 + .../browsers/fs/watch_events_response.py | 22 + .../types/browsers/fs/watch_start_params.py | 15 + .../types/browsers/fs/watch_start_response.py | 12 + tests/api_resources/browsers/fs/__init__.py | 1 + tests/api_resources/browsers/fs/test_watch.py | 358 ++++++ tests/api_resources/browsers/test_fs.py | 977 +++++++++++++++ 26 files changed, 3123 insertions(+), 4 deletions(-) create mode 100644 src/kernel/resources/browsers/fs/__init__.py create mode 100644 src/kernel/resources/browsers/fs/fs.py create mode 100644 src/kernel/resources/browsers/fs/watch.py create mode 100644 src/kernel/types/browsers/f_create_directory_params.py create mode 100644 src/kernel/types/browsers/f_delete_directory_params.py create mode 100644 src/kernel/types/browsers/f_delete_file_params.py create mode 100644 src/kernel/types/browsers/f_file_info_params.py create mode 100644 src/kernel/types/browsers/f_file_info_response.py create mode 100644 src/kernel/types/browsers/f_list_files_params.py create mode 100644 src/kernel/types/browsers/f_list_files_response.py create mode 100644 src/kernel/types/browsers/f_move_params.py create mode 100644 src/kernel/types/browsers/f_read_file_params.py create mode 100644 src/kernel/types/browsers/f_set_file_permissions_params.py create mode 100644 src/kernel/types/browsers/f_write_file_params.py create mode 100644 src/kernel/types/browsers/fs/__init__.py create mode 100644 src/kernel/types/browsers/fs/watch_events_response.py create mode 100644 src/kernel/types/browsers/fs/watch_start_params.py create mode 100644 src/kernel/types/browsers/fs/watch_start_response.py create mode 100644 tests/api_resources/browsers/fs/__init__.py create mode 100644 tests/api_resources/browsers/fs/test_watch.py create mode 100644 tests/api_resources/browsers/test_fs.py diff --git a/.stats.yml b/.stats.yml index fbe1e82..062204b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-9f2d347a4bcb03aed092ba4495aac090c3d988e9a99af091ee35c09994adad8b.yml -openapi_spec_hash: 73b92bd5503ab6c64dc26da31cca36e2 -config_hash: 65328ff206b8c0168c915914506d9dba +configured_endpoints: 31 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e907afeabfeea49dedd783112ac3fd29267bc86f3d594f89ba9a2abf2bcbc9d8.yml +openapi_spec_hash: 060ca6288c1a09b6d1bdf207a0011165 +config_hash: f67e4b33b2fb30c1405ee2fff8096320 diff --git a/api.md b/api.md index 434ace2..f03855d 100644 --- a/api.md +++ b/api.md @@ -94,3 +94,37 @@ Methods: - client.browsers.replays.download(replay_id, \*, id) -> BinaryAPIResponse - client.browsers.replays.start(id, \*\*params) -> ReplayStartResponse - client.browsers.replays.stop(replay_id, \*, id) -> None + +## Fs + +Types: + +```python +from kernel.types.browsers import FFileInfoResponse, FListFilesResponse +``` + +Methods: + +- client.browsers.fs.create_directory(id, \*\*params) -> None +- client.browsers.fs.delete_directory(id, \*\*params) -> None +- client.browsers.fs.delete_file(id, \*\*params) -> None +- client.browsers.fs.file_info(id, \*\*params) -> FFileInfoResponse +- client.browsers.fs.list_files(id, \*\*params) -> FListFilesResponse +- client.browsers.fs.move(id, \*\*params) -> None +- client.browsers.fs.read_file(id, \*\*params) -> BinaryAPIResponse +- client.browsers.fs.set_file_permissions(id, \*\*params) -> None +- client.browsers.fs.write_file(id, contents, \*\*params) -> None + +### Watch + +Types: + +```python +from kernel.types.browsers.fs import WatchEventsResponse, WatchStartResponse +``` + +Methods: + +- client.browsers.fs.watch.events(watch_id, \*, id) -> WatchEventsResponse +- client.browsers.fs.watch.start(id, \*\*params) -> WatchStartResponse +- client.browsers.fs.watch.stop(watch_id, \*, id) -> None diff --git a/src/kernel/resources/browsers/__init__.py b/src/kernel/resources/browsers/__init__.py index 236b5f7..41452e9 100644 --- a/src/kernel/resources/browsers/__init__.py +++ b/src/kernel/resources/browsers/__init__.py @@ -1,5 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .fs import ( + FsResource, + AsyncFsResource, + FsResourceWithRawResponse, + AsyncFsResourceWithRawResponse, + FsResourceWithStreamingResponse, + AsyncFsResourceWithStreamingResponse, +) from .replays import ( ReplaysResource, AsyncReplaysResource, @@ -24,6 +32,12 @@ "AsyncReplaysResourceWithRawResponse", "ReplaysResourceWithStreamingResponse", "AsyncReplaysResourceWithStreamingResponse", + "FsResource", + "AsyncFsResource", + "FsResourceWithRawResponse", + "AsyncFsResourceWithRawResponse", + "FsResourceWithStreamingResponse", + "AsyncFsResourceWithStreamingResponse", "BrowsersResource", "AsyncBrowsersResource", "BrowsersResourceWithRawResponse", diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py index b44573e..6d29c9e 100644 --- a/src/kernel/resources/browsers/browsers.py +++ b/src/kernel/resources/browsers/browsers.py @@ -4,6 +4,14 @@ import httpx +from .fs.fs import ( + FsResource, + AsyncFsResource, + FsResourceWithRawResponse, + AsyncFsResourceWithRawResponse, + FsResourceWithStreamingResponse, + AsyncFsResourceWithStreamingResponse, +) from ...types import browser_create_params, browser_delete_params from .replays import ( ReplaysResource, @@ -37,6 +45,10 @@ class BrowsersResource(SyncAPIResource): def replays(self) -> ReplaysResource: return ReplaysResource(self._client) + @cached_property + def fs(self) -> FsResource: + return FsResource(self._client) + @cached_property def with_raw_response(self) -> BrowsersResourceWithRawResponse: """ @@ -239,6 +251,10 @@ class AsyncBrowsersResource(AsyncAPIResource): def replays(self) -> AsyncReplaysResource: return AsyncReplaysResource(self._client) + @cached_property + def fs(self) -> AsyncFsResource: + return AsyncFsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncBrowsersResourceWithRawResponse: """ @@ -462,6 +478,10 @@ def __init__(self, browsers: BrowsersResource) -> None: def replays(self) -> ReplaysResourceWithRawResponse: return ReplaysResourceWithRawResponse(self._browsers.replays) + @cached_property + def fs(self) -> FsResourceWithRawResponse: + return FsResourceWithRawResponse(self._browsers.fs) + class AsyncBrowsersResourceWithRawResponse: def __init__(self, browsers: AsyncBrowsersResource) -> None: @@ -487,6 +507,10 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None: def replays(self) -> AsyncReplaysResourceWithRawResponse: return AsyncReplaysResourceWithRawResponse(self._browsers.replays) + @cached_property + def fs(self) -> AsyncFsResourceWithRawResponse: + return AsyncFsResourceWithRawResponse(self._browsers.fs) + class BrowsersResourceWithStreamingResponse: def __init__(self, browsers: BrowsersResource) -> None: @@ -512,6 +536,10 @@ def __init__(self, browsers: BrowsersResource) -> None: def replays(self) -> ReplaysResourceWithStreamingResponse: return ReplaysResourceWithStreamingResponse(self._browsers.replays) + @cached_property + def fs(self) -> FsResourceWithStreamingResponse: + return FsResourceWithStreamingResponse(self._browsers.fs) + class AsyncBrowsersResourceWithStreamingResponse: def __init__(self, browsers: AsyncBrowsersResource) -> None: @@ -536,3 +564,7 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None: @cached_property def replays(self) -> AsyncReplaysResourceWithStreamingResponse: return AsyncReplaysResourceWithStreamingResponse(self._browsers.replays) + + @cached_property + def fs(self) -> AsyncFsResourceWithStreamingResponse: + return AsyncFsResourceWithStreamingResponse(self._browsers.fs) diff --git a/src/kernel/resources/browsers/fs/__init__.py b/src/kernel/resources/browsers/fs/__init__.py new file mode 100644 index 0000000..8195b3f --- /dev/null +++ b/src/kernel/resources/browsers/fs/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .fs import ( + FsResource, + AsyncFsResource, + FsResourceWithRawResponse, + AsyncFsResourceWithRawResponse, + FsResourceWithStreamingResponse, + AsyncFsResourceWithStreamingResponse, +) +from .watch import ( + WatchResource, + AsyncWatchResource, + WatchResourceWithRawResponse, + AsyncWatchResourceWithRawResponse, + WatchResourceWithStreamingResponse, + AsyncWatchResourceWithStreamingResponse, +) + +__all__ = [ + "WatchResource", + "AsyncWatchResource", + "WatchResourceWithRawResponse", + "AsyncWatchResourceWithRawResponse", + "WatchResourceWithStreamingResponse", + "AsyncWatchResourceWithStreamingResponse", + "FsResource", + "AsyncFsResource", + "FsResourceWithRawResponse", + "AsyncFsResourceWithRawResponse", + "FsResourceWithStreamingResponse", + "AsyncFsResourceWithStreamingResponse", +] diff --git a/src/kernel/resources/browsers/fs/fs.py b/src/kernel/resources/browsers/fs/fs.py new file mode 100644 index 0000000..3563c7c --- /dev/null +++ b/src/kernel/resources/browsers/fs/fs.py @@ -0,0 +1,1049 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .watch import ( + WatchResource, + AsyncWatchResource, + WatchResourceWithRawResponse, + AsyncWatchResourceWithRawResponse, + WatchResourceWithStreamingResponse, + AsyncWatchResourceWithStreamingResponse, +) +from ...._files import read_file_content, async_read_file_content +from ...._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileContent +from ...._utils import maybe_transform, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + to_custom_raw_response_wrapper, + async_to_streamed_response_wrapper, + to_custom_streamed_response_wrapper, + async_to_custom_raw_response_wrapper, + async_to_custom_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.browsers import ( + f_move_params, + f_file_info_params, + f_read_file_params, + f_list_files_params, + f_write_file_params, + f_delete_file_params, + f_create_directory_params, + f_delete_directory_params, + f_set_file_permissions_params, +) +from ....types.browsers.f_file_info_response import FFileInfoResponse +from ....types.browsers.f_list_files_response import FListFilesResponse + +__all__ = ["FsResource", "AsyncFsResource"] + + +class FsResource(SyncAPIResource): + @cached_property + def watch(self) -> WatchResource: + return WatchResource(self._client) + + @cached_property + def with_raw_response(self) -> FsResourceWithRawResponse: + """ + 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 FsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FsResourceWithStreamingResponse: + """ + 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 FsResourceWithStreamingResponse(self) + + def create_directory( + self, + id: str, + *, + path: str, + mode: str | NotGiven = NOT_GIVEN, + # 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: + """ + Create a new directory + + Args: + path: Absolute directory path to create. + + mode: Optional directory mode (octal string, e.g. 755). Defaults to 755. + + 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._put( + f"/browsers/{id}/fs/create_directory", + body=maybe_transform( + { + "path": path, + "mode": mode, + }, + f_create_directory_params.FCreateDirectoryParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def delete_directory( + self, + id: str, + *, + path: 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: + """ + Delete a directory + + Args: + path: Absolute path to delete. + + 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._put( + f"/browsers/{id}/fs/delete_directory", + body=maybe_transform({"path": path}, f_delete_directory_params.FDeleteDirectoryParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def delete_file( + self, + id: str, + *, + path: 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: + """ + Delete a file + + Args: + path: Absolute path to delete. + + 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._put( + f"/browsers/{id}/fs/delete_file", + body=maybe_transform({"path": path}, f_delete_file_params.FDeleteFileParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def file_info( + self, + id: str, + *, + path: 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, + ) -> FFileInfoResponse: + """ + Get information about a file or directory + + Args: + path: Absolute path of the file or directory. + + 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"/browsers/{id}/fs/file_info", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"path": path}, f_file_info_params.FFileInfoParams), + ), + cast_to=FFileInfoResponse, + ) + + def list_files( + self, + id: str, + *, + path: 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, + ) -> FListFilesResponse: + """ + List files in a directory + + Args: + path: Absolute directory path. + + 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"/browsers/{id}/fs/list_files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"path": path}, f_list_files_params.FListFilesParams), + ), + cast_to=FListFilesResponse, + ) + + def move( + self, + id: str, + *, + dest_path: str, + src_path: 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: + """ + Move or rename a file or directory + + Args: + dest_path: Absolute destination path. + + src_path: Absolute source path. + + 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._put( + f"/browsers/{id}/fs/move", + body=maybe_transform( + { + "dest_path": dest_path, + "src_path": src_path, + }, + f_move_params.FMoveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def read_file( + self, + id: str, + *, + path: 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, + ) -> BinaryAPIResponse: + """ + Read file contents + + Args: + path: Absolute file path to read. + + 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": "application/octet-stream", **(extra_headers or {})} + return self._get( + f"/browsers/{id}/fs/read_file", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"path": path}, f_read_file_params.FReadFileParams), + ), + cast_to=BinaryAPIResponse, + ) + + def set_file_permissions( + self, + id: str, + *, + mode: str, + path: str, + group: str | NotGiven = NOT_GIVEN, + owner: str | NotGiven = NOT_GIVEN, + # 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: + """ + Set file or directory permissions/ownership + + Args: + mode: File mode bits (octal string, e.g. 644). + + path: Absolute path whose permissions are to be changed. + + group: New group name or GID. + + owner: New owner username or UID. + + 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._put( + f"/browsers/{id}/fs/set_file_permissions", + body=maybe_transform( + { + "mode": mode, + "path": path, + "group": group, + "owner": owner, + }, + f_set_file_permissions_params.FSetFilePermissionsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def write_file( + self, + id: str, + contents: FileContent, + *, + path: str, + mode: str | NotGiven = NOT_GIVEN, + # 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: + """ + Write or create a file + + Args: + path: Destination absolute file path. + + mode: Optional file mode (octal string, e.g. 644). Defaults to 644. + + 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 {})} + extra_headers["Content-Type"] = "application/octet-stream" + return self._put( + f"/browsers/{id}/fs/write_file", + body=read_file_content(contents), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "path": path, + "mode": mode, + }, + f_write_file_params.FWriteFileParams, + ), + ), + cast_to=NoneType, + ) + + +class AsyncFsResource(AsyncAPIResource): + @cached_property + def watch(self) -> AsyncWatchResource: + return AsyncWatchResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncFsResourceWithRawResponse: + """ + 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 AsyncFsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFsResourceWithStreamingResponse: + """ + 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 AsyncFsResourceWithStreamingResponse(self) + + async def create_directory( + self, + id: str, + *, + path: str, + mode: str | NotGiven = NOT_GIVEN, + # 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: + """ + Create a new directory + + Args: + path: Absolute directory path to create. + + mode: Optional directory mode (octal string, e.g. 755). Defaults to 755. + + 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._put( + f"/browsers/{id}/fs/create_directory", + body=await async_maybe_transform( + { + "path": path, + "mode": mode, + }, + f_create_directory_params.FCreateDirectoryParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def delete_directory( + self, + id: str, + *, + path: 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: + """ + Delete a directory + + Args: + path: Absolute path to delete. + + 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._put( + f"/browsers/{id}/fs/delete_directory", + body=await async_maybe_transform({"path": path}, f_delete_directory_params.FDeleteDirectoryParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def delete_file( + self, + id: str, + *, + path: 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: + """ + Delete a file + + Args: + path: Absolute path to delete. + + 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._put( + f"/browsers/{id}/fs/delete_file", + body=await async_maybe_transform({"path": path}, f_delete_file_params.FDeleteFileParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def file_info( + self, + id: str, + *, + path: 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, + ) -> FFileInfoResponse: + """ + Get information about a file or directory + + Args: + path: Absolute path of the file or directory. + + 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"/browsers/{id}/fs/file_info", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"path": path}, f_file_info_params.FFileInfoParams), + ), + cast_to=FFileInfoResponse, + ) + + async def list_files( + self, + id: str, + *, + path: 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, + ) -> FListFilesResponse: + """ + List files in a directory + + Args: + path: Absolute directory path. + + 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"/browsers/{id}/fs/list_files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"path": path}, f_list_files_params.FListFilesParams), + ), + cast_to=FListFilesResponse, + ) + + async def move( + self, + id: str, + *, + dest_path: str, + src_path: 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: + """ + Move or rename a file or directory + + Args: + dest_path: Absolute destination path. + + src_path: Absolute source path. + + 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._put( + f"/browsers/{id}/fs/move", + body=await async_maybe_transform( + { + "dest_path": dest_path, + "src_path": src_path, + }, + f_move_params.FMoveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def read_file( + self, + id: str, + *, + path: 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, + ) -> AsyncBinaryAPIResponse: + """ + Read file contents + + Args: + path: Absolute file path to read. + + 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": "application/octet-stream", **(extra_headers or {})} + return await self._get( + f"/browsers/{id}/fs/read_file", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"path": path}, f_read_file_params.FReadFileParams), + ), + cast_to=AsyncBinaryAPIResponse, + ) + + async def set_file_permissions( + self, + id: str, + *, + mode: str, + path: str, + group: str | NotGiven = NOT_GIVEN, + owner: str | NotGiven = NOT_GIVEN, + # 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: + """ + Set file or directory permissions/ownership + + Args: + mode: File mode bits (octal string, e.g. 644). + + path: Absolute path whose permissions are to be changed. + + group: New group name or GID. + + owner: New owner username or UID. + + 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._put( + f"/browsers/{id}/fs/set_file_permissions", + body=await async_maybe_transform( + { + "mode": mode, + "path": path, + "group": group, + "owner": owner, + }, + f_set_file_permissions_params.FSetFilePermissionsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def write_file( + self, + id: str, + contents: FileContent, + *, + path: str, + mode: str | NotGiven = NOT_GIVEN, + # 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: + """ + Write or create a file + + Args: + path: Destination absolute file path. + + mode: Optional file mode (octal string, e.g. 644). Defaults to 644. + + 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 {})} + extra_headers["Content-Type"] = "application/octet-stream" + return await self._put( + f"/browsers/{id}/fs/write_file", + body=await async_read_file_content(contents), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "path": path, + "mode": mode, + }, + f_write_file_params.FWriteFileParams, + ), + ), + cast_to=NoneType, + ) + + +class FsResourceWithRawResponse: + def __init__(self, fs: FsResource) -> None: + self._fs = fs + + self.create_directory = to_raw_response_wrapper( + fs.create_directory, + ) + self.delete_directory = to_raw_response_wrapper( + fs.delete_directory, + ) + self.delete_file = to_raw_response_wrapper( + fs.delete_file, + ) + self.file_info = to_raw_response_wrapper( + fs.file_info, + ) + self.list_files = to_raw_response_wrapper( + fs.list_files, + ) + self.move = to_raw_response_wrapper( + fs.move, + ) + self.read_file = to_custom_raw_response_wrapper( + fs.read_file, + BinaryAPIResponse, + ) + self.set_file_permissions = to_raw_response_wrapper( + fs.set_file_permissions, + ) + self.write_file = to_raw_response_wrapper( + fs.write_file, + ) + + @cached_property + def watch(self) -> WatchResourceWithRawResponse: + return WatchResourceWithRawResponse(self._fs.watch) + + +class AsyncFsResourceWithRawResponse: + def __init__(self, fs: AsyncFsResource) -> None: + self._fs = fs + + self.create_directory = async_to_raw_response_wrapper( + fs.create_directory, + ) + self.delete_directory = async_to_raw_response_wrapper( + fs.delete_directory, + ) + self.delete_file = async_to_raw_response_wrapper( + fs.delete_file, + ) + self.file_info = async_to_raw_response_wrapper( + fs.file_info, + ) + self.list_files = async_to_raw_response_wrapper( + fs.list_files, + ) + self.move = async_to_raw_response_wrapper( + fs.move, + ) + self.read_file = async_to_custom_raw_response_wrapper( + fs.read_file, + AsyncBinaryAPIResponse, + ) + self.set_file_permissions = async_to_raw_response_wrapper( + fs.set_file_permissions, + ) + self.write_file = async_to_raw_response_wrapper( + fs.write_file, + ) + + @cached_property + def watch(self) -> AsyncWatchResourceWithRawResponse: + return AsyncWatchResourceWithRawResponse(self._fs.watch) + + +class FsResourceWithStreamingResponse: + def __init__(self, fs: FsResource) -> None: + self._fs = fs + + self.create_directory = to_streamed_response_wrapper( + fs.create_directory, + ) + self.delete_directory = to_streamed_response_wrapper( + fs.delete_directory, + ) + self.delete_file = to_streamed_response_wrapper( + fs.delete_file, + ) + self.file_info = to_streamed_response_wrapper( + fs.file_info, + ) + self.list_files = to_streamed_response_wrapper( + fs.list_files, + ) + self.move = to_streamed_response_wrapper( + fs.move, + ) + self.read_file = to_custom_streamed_response_wrapper( + fs.read_file, + StreamedBinaryAPIResponse, + ) + self.set_file_permissions = to_streamed_response_wrapper( + fs.set_file_permissions, + ) + self.write_file = to_streamed_response_wrapper( + fs.write_file, + ) + + @cached_property + def watch(self) -> WatchResourceWithStreamingResponse: + return WatchResourceWithStreamingResponse(self._fs.watch) + + +class AsyncFsResourceWithStreamingResponse: + def __init__(self, fs: AsyncFsResource) -> None: + self._fs = fs + + self.create_directory = async_to_streamed_response_wrapper( + fs.create_directory, + ) + self.delete_directory = async_to_streamed_response_wrapper( + fs.delete_directory, + ) + self.delete_file = async_to_streamed_response_wrapper( + fs.delete_file, + ) + self.file_info = async_to_streamed_response_wrapper( + fs.file_info, + ) + self.list_files = async_to_streamed_response_wrapper( + fs.list_files, + ) + self.move = async_to_streamed_response_wrapper( + fs.move, + ) + self.read_file = async_to_custom_streamed_response_wrapper( + fs.read_file, + AsyncStreamedBinaryAPIResponse, + ) + self.set_file_permissions = async_to_streamed_response_wrapper( + fs.set_file_permissions, + ) + self.write_file = async_to_streamed_response_wrapper( + fs.write_file, + ) + + @cached_property + def watch(self) -> AsyncWatchResourceWithStreamingResponse: + return AsyncWatchResourceWithStreamingResponse(self._fs.watch) diff --git a/src/kernel/resources/browsers/fs/watch.py b/src/kernel/resources/browsers/fs/watch.py new file mode 100644 index 0000000..a35e0de --- /dev/null +++ b/src/kernel/resources/browsers/fs/watch.py @@ -0,0 +1,369 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ...._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +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 ...._streaming import Stream, AsyncStream +from ...._base_client import make_request_options +from ....types.browsers.fs import watch_start_params +from ....types.browsers.fs.watch_start_response import WatchStartResponse +from ....types.browsers.fs.watch_events_response import WatchEventsResponse + +__all__ = ["WatchResource", "AsyncWatchResource"] + + +class WatchResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> WatchResourceWithRawResponse: + """ + 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 WatchResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> WatchResourceWithStreamingResponse: + """ + 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 WatchResourceWithStreamingResponse(self) + + def events( + self, + watch_id: str, + *, + 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, + ) -> Stream[WatchEventsResponse]: + """ + Stream filesystem events for a watch + + 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}") + if not watch_id: + raise ValueError(f"Expected a non-empty value for `watch_id` but received {watch_id!r}") + extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} + return self._get( + f"/browsers/{id}/fs/watch/{watch_id}/events", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=WatchEventsResponse, + stream=True, + stream_cls=Stream[WatchEventsResponse], + ) + + def start( + self, + id: str, + *, + path: str, + recursive: bool | NotGiven = NOT_GIVEN, + # 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, + ) -> WatchStartResponse: + """ + Watch a directory for changes + + Args: + path: Directory to watch. + + recursive: Whether to watch recursively. + + 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._post( + f"/browsers/{id}/fs/watch", + body=maybe_transform( + { + "path": path, + "recursive": recursive, + }, + watch_start_params.WatchStartParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=WatchStartResponse, + ) + + def stop( + self, + watch_id: str, + *, + 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: + """ + Stop watching a directory + + 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}") + if not watch_id: + raise ValueError(f"Expected a non-empty value for `watch_id` but received {watch_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/browsers/{id}/fs/watch/{watch_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncWatchResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncWatchResourceWithRawResponse: + """ + 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 AsyncWatchResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncWatchResourceWithStreamingResponse: + """ + 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 AsyncWatchResourceWithStreamingResponse(self) + + async def events( + self, + watch_id: str, + *, + 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, + ) -> AsyncStream[WatchEventsResponse]: + """ + Stream filesystem events for a watch + + 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}") + if not watch_id: + raise ValueError(f"Expected a non-empty value for `watch_id` but received {watch_id!r}") + extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} + return await self._get( + f"/browsers/{id}/fs/watch/{watch_id}/events", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=WatchEventsResponse, + stream=True, + stream_cls=AsyncStream[WatchEventsResponse], + ) + + async def start( + self, + id: str, + *, + path: str, + recursive: bool | NotGiven = NOT_GIVEN, + # 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, + ) -> WatchStartResponse: + """ + Watch a directory for changes + + Args: + path: Directory to watch. + + recursive: Whether to watch recursively. + + 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._post( + f"/browsers/{id}/fs/watch", + body=await async_maybe_transform( + { + "path": path, + "recursive": recursive, + }, + watch_start_params.WatchStartParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=WatchStartResponse, + ) + + async def stop( + self, + watch_id: str, + *, + 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: + """ + Stop watching a directory + + 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}") + if not watch_id: + raise ValueError(f"Expected a non-empty value for `watch_id` but received {watch_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/browsers/{id}/fs/watch/{watch_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class WatchResourceWithRawResponse: + def __init__(self, watch: WatchResource) -> None: + self._watch = watch + + self.events = to_raw_response_wrapper( + watch.events, + ) + self.start = to_raw_response_wrapper( + watch.start, + ) + self.stop = to_raw_response_wrapper( + watch.stop, + ) + + +class AsyncWatchResourceWithRawResponse: + def __init__(self, watch: AsyncWatchResource) -> None: + self._watch = watch + + self.events = async_to_raw_response_wrapper( + watch.events, + ) + self.start = async_to_raw_response_wrapper( + watch.start, + ) + self.stop = async_to_raw_response_wrapper( + watch.stop, + ) + + +class WatchResourceWithStreamingResponse: + def __init__(self, watch: WatchResource) -> None: + self._watch = watch + + self.events = to_streamed_response_wrapper( + watch.events, + ) + self.start = to_streamed_response_wrapper( + watch.start, + ) + self.stop = to_streamed_response_wrapper( + watch.stop, + ) + + +class AsyncWatchResourceWithStreamingResponse: + def __init__(self, watch: AsyncWatchResource) -> None: + self._watch = watch + + self.events = async_to_streamed_response_wrapper( + watch.events, + ) + self.start = async_to_streamed_response_wrapper( + watch.start, + ) + self.stop = async_to_streamed_response_wrapper( + watch.stop, + ) diff --git a/src/kernel/types/browsers/__init__.py b/src/kernel/types/browsers/__init__.py index 61b18bc..c4e80a8 100644 --- a/src/kernel/types/browsers/__init__.py +++ b/src/kernel/types/browsers/__init__.py @@ -2,6 +2,17 @@ from __future__ import annotations +from .f_move_params import FMoveParams as FMoveParams +from .f_file_info_params import FFileInfoParams as FFileInfoParams +from .f_read_file_params import FReadFileParams as FReadFileParams +from .f_list_files_params import FListFilesParams as FListFilesParams +from .f_write_file_params import FWriteFileParams as FWriteFileParams from .replay_start_params import ReplayStartParams as ReplayStartParams +from .f_delete_file_params import FDeleteFileParams as FDeleteFileParams +from .f_file_info_response import FFileInfoResponse as FFileInfoResponse from .replay_list_response import ReplayListResponse as ReplayListResponse +from .f_list_files_response import FListFilesResponse as FListFilesResponse from .replay_start_response import ReplayStartResponse as ReplayStartResponse +from .f_create_directory_params import FCreateDirectoryParams as FCreateDirectoryParams +from .f_delete_directory_params import FDeleteDirectoryParams as FDeleteDirectoryParams +from .f_set_file_permissions_params import FSetFilePermissionsParams as FSetFilePermissionsParams diff --git a/src/kernel/types/browsers/f_create_directory_params.py b/src/kernel/types/browsers/f_create_directory_params.py new file mode 100644 index 0000000..20924f3 --- /dev/null +++ b/src/kernel/types/browsers/f_create_directory_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FCreateDirectoryParams"] + + +class FCreateDirectoryParams(TypedDict, total=False): + path: Required[str] + """Absolute directory path to create.""" + + mode: str + """Optional directory mode (octal string, e.g. 755). Defaults to 755.""" diff --git a/src/kernel/types/browsers/f_delete_directory_params.py b/src/kernel/types/browsers/f_delete_directory_params.py new file mode 100644 index 0000000..8f5a086 --- /dev/null +++ b/src/kernel/types/browsers/f_delete_directory_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FDeleteDirectoryParams"] + + +class FDeleteDirectoryParams(TypedDict, total=False): + path: Required[str] + """Absolute path to delete.""" diff --git a/src/kernel/types/browsers/f_delete_file_params.py b/src/kernel/types/browsers/f_delete_file_params.py new file mode 100644 index 0000000..d79bb8a --- /dev/null +++ b/src/kernel/types/browsers/f_delete_file_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FDeleteFileParams"] + + +class FDeleteFileParams(TypedDict, total=False): + path: Required[str] + """Absolute path to delete.""" diff --git a/src/kernel/types/browsers/f_file_info_params.py b/src/kernel/types/browsers/f_file_info_params.py new file mode 100644 index 0000000..9ddf41e --- /dev/null +++ b/src/kernel/types/browsers/f_file_info_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FFileInfoParams"] + + +class FFileInfoParams(TypedDict, total=False): + path: Required[str] + """Absolute path of the file or directory.""" diff --git a/src/kernel/types/browsers/f_file_info_response.py b/src/kernel/types/browsers/f_file_info_response.py new file mode 100644 index 0000000..7da1574 --- /dev/null +++ b/src/kernel/types/browsers/f_file_info_response.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["FFileInfoResponse"] + + +class FFileInfoResponse(BaseModel): + is_dir: bool + """Whether the path is a directory.""" + + mod_time: datetime + """Last modification time.""" + + mode: str + """File mode bits (e.g., "drwxr-xr-x" or "-rw-r--r--").""" + + name: str + """Base name of the file or directory.""" + + path: str + """Absolute path.""" + + size_bytes: int + """Size in bytes. 0 for directories.""" diff --git a/src/kernel/types/browsers/f_list_files_params.py b/src/kernel/types/browsers/f_list_files_params.py new file mode 100644 index 0000000..87026f5 --- /dev/null +++ b/src/kernel/types/browsers/f_list_files_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FListFilesParams"] + + +class FListFilesParams(TypedDict, total=False): + path: Required[str] + """Absolute directory path.""" diff --git a/src/kernel/types/browsers/f_list_files_response.py b/src/kernel/types/browsers/f_list_files_response.py new file mode 100644 index 0000000..9fca14b --- /dev/null +++ b/src/kernel/types/browsers/f_list_files_response.py @@ -0,0 +1,32 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from datetime import datetime +from typing_extensions import TypeAlias + +from ..._models import BaseModel + +__all__ = ["FListFilesResponse", "FListFilesResponseItem"] + + +class FListFilesResponseItem(BaseModel): + is_dir: bool + """Whether the path is a directory.""" + + mod_time: datetime + """Last modification time.""" + + mode: str + """File mode bits (e.g., "drwxr-xr-x" or "-rw-r--r--").""" + + name: str + """Base name of the file or directory.""" + + path: str + """Absolute path.""" + + size_bytes: int + """Size in bytes. 0 for directories.""" + + +FListFilesResponse: TypeAlias = List[FListFilesResponseItem] diff --git a/src/kernel/types/browsers/f_move_params.py b/src/kernel/types/browsers/f_move_params.py new file mode 100644 index 0000000..d324cc9 --- /dev/null +++ b/src/kernel/types/browsers/f_move_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FMoveParams"] + + +class FMoveParams(TypedDict, total=False): + dest_path: Required[str] + """Absolute destination path.""" + + src_path: Required[str] + """Absolute source path.""" diff --git a/src/kernel/types/browsers/f_read_file_params.py b/src/kernel/types/browsers/f_read_file_params.py new file mode 100644 index 0000000..ee5d2e9 --- /dev/null +++ b/src/kernel/types/browsers/f_read_file_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FReadFileParams"] + + +class FReadFileParams(TypedDict, total=False): + path: Required[str] + """Absolute file path to read.""" diff --git a/src/kernel/types/browsers/f_set_file_permissions_params.py b/src/kernel/types/browsers/f_set_file_permissions_params.py new file mode 100644 index 0000000..5a02c1e --- /dev/null +++ b/src/kernel/types/browsers/f_set_file_permissions_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FSetFilePermissionsParams"] + + +class FSetFilePermissionsParams(TypedDict, total=False): + mode: Required[str] + """File mode bits (octal string, e.g. 644).""" + + path: Required[str] + """Absolute path whose permissions are to be changed.""" + + group: str + """New group name or GID.""" + + owner: str + """New owner username or UID.""" diff --git a/src/kernel/types/browsers/f_write_file_params.py b/src/kernel/types/browsers/f_write_file_params.py new file mode 100644 index 0000000..557eac1 --- /dev/null +++ b/src/kernel/types/browsers/f_write_file_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FWriteFileParams"] + + +class FWriteFileParams(TypedDict, total=False): + path: Required[str] + """Destination absolute file path.""" + + mode: str + """Optional file mode (octal string, e.g. 644). Defaults to 644.""" diff --git a/src/kernel/types/browsers/fs/__init__.py b/src/kernel/types/browsers/fs/__init__.py new file mode 100644 index 0000000..ebd13d9 --- /dev/null +++ b/src/kernel/types/browsers/fs/__init__.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .watch_start_params import WatchStartParams as WatchStartParams +from .watch_start_response import WatchStartResponse as WatchStartResponse +from .watch_events_response import WatchEventsResponse as WatchEventsResponse diff --git a/src/kernel/types/browsers/fs/watch_events_response.py b/src/kernel/types/browsers/fs/watch_events_response.py new file mode 100644 index 0000000..8df2f50 --- /dev/null +++ b/src/kernel/types/browsers/fs/watch_events_response.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ...._models import BaseModel + +__all__ = ["WatchEventsResponse"] + + +class WatchEventsResponse(BaseModel): + path: str + """Absolute path of the file or directory.""" + + type: Literal["CREATE", "WRITE", "DELETE", "RENAME"] + """Event type.""" + + is_dir: Optional[bool] = None + """Whether the affected path is a directory.""" + + name: Optional[str] = None + """Base name of the file or directory affected.""" diff --git a/src/kernel/types/browsers/fs/watch_start_params.py b/src/kernel/types/browsers/fs/watch_start_params.py new file mode 100644 index 0000000..5afddb1 --- /dev/null +++ b/src/kernel/types/browsers/fs/watch_start_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["WatchStartParams"] + + +class WatchStartParams(TypedDict, total=False): + path: Required[str] + """Directory to watch.""" + + recursive: bool + """Whether to watch recursively.""" diff --git a/src/kernel/types/browsers/fs/watch_start_response.py b/src/kernel/types/browsers/fs/watch_start_response.py new file mode 100644 index 0000000..b9f78e4 --- /dev/null +++ b/src/kernel/types/browsers/fs/watch_start_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ...._models import BaseModel + +__all__ = ["WatchStartResponse"] + + +class WatchStartResponse(BaseModel): + watch_id: Optional[str] = None + """Unique identifier for the directory watch""" diff --git a/tests/api_resources/browsers/fs/__init__.py b/tests/api_resources/browsers/fs/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/browsers/fs/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/browsers/fs/test_watch.py b/tests/api_resources/browsers/fs/test_watch.py new file mode 100644 index 0000000..b815c8a --- /dev/null +++ b/tests/api_resources/browsers/fs/test_watch.py @@ -0,0 +1,358 @@ +# 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.browsers.fs import WatchStartResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestWatch: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + def test_method_events(self, client: Kernel) -> None: + watch_stream = client.browsers.fs.watch.events( + watch_id="watch_id", + id="id", + ) + watch_stream.response.close() + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + def test_raw_response_events(self, client: Kernel) -> None: + response = client.browsers.fs.watch.with_raw_response.events( + watch_id="watch_id", + id="id", + ) + + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + stream = response.parse() + stream.close() + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + def test_streaming_response_events(self, client: Kernel) -> None: + with client.browsers.fs.watch.with_streaming_response.events( + watch_id="watch_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + stream = response.parse() + stream.close() + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + def test_path_params_events(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.watch.with_raw_response.events( + watch_id="watch_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `watch_id` but received ''"): + client.browsers.fs.watch.with_raw_response.events( + watch_id="", + id="id", + ) + + @pytest.mark.skip() + @parametrize + def test_method_start(self, client: Kernel) -> None: + watch = client.browsers.fs.watch.start( + id="id", + path="path", + ) + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_method_start_with_all_params(self, client: Kernel) -> None: + watch = client.browsers.fs.watch.start( + id="id", + path="path", + recursive=True, + ) + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_raw_response_start(self, client: Kernel) -> None: + response = client.browsers.fs.watch.with_raw_response.start( + id="id", + path="path", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + watch = response.parse() + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_streaming_response_start(self, client: Kernel) -> None: + with client.browsers.fs.watch.with_streaming_response.start( + id="id", + path="path", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + watch = response.parse() + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_start(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.watch.with_raw_response.start( + id="", + path="path", + ) + + @pytest.mark.skip() + @parametrize + def test_method_stop(self, client: Kernel) -> None: + watch = client.browsers.fs.watch.stop( + watch_id="watch_id", + id="id", + ) + assert watch is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_stop(self, client: Kernel) -> None: + response = client.browsers.fs.watch.with_raw_response.stop( + watch_id="watch_id", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + watch = response.parse() + assert watch is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_stop(self, client: Kernel) -> None: + with client.browsers.fs.watch.with_streaming_response.stop( + watch_id="watch_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + watch = response.parse() + assert watch is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_stop(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.watch.with_raw_response.stop( + watch_id="watch_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `watch_id` but received ''"): + client.browsers.fs.watch.with_raw_response.stop( + watch_id="", + id="id", + ) + + +class TestAsyncWatch: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + async def test_method_events(self, async_client: AsyncKernel) -> None: + watch_stream = await async_client.browsers.fs.watch.events( + watch_id="watch_id", + id="id", + ) + await watch_stream.response.aclose() + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + async def test_raw_response_events(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.watch.with_raw_response.events( + watch_id="watch_id", + id="id", + ) + + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + stream = await response.parse() + await stream.close() + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + async def test_streaming_response_events(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.watch.with_streaming_response.events( + watch_id="watch_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + stream = await response.parse() + await stream.close() + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip( + reason="currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail" + ) + @parametrize + async def test_path_params_events(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.watch.with_raw_response.events( + watch_id="watch_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `watch_id` but received ''"): + await async_client.browsers.fs.watch.with_raw_response.events( + watch_id="", + id="id", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_start(self, async_client: AsyncKernel) -> None: + watch = await async_client.browsers.fs.watch.start( + id="id", + path="path", + ) + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_method_start_with_all_params(self, async_client: AsyncKernel) -> None: + watch = await async_client.browsers.fs.watch.start( + id="id", + path="path", + recursive=True, + ) + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_raw_response_start(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.watch.with_raw_response.start( + id="id", + path="path", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + watch = await response.parse() + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_start(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.watch.with_streaming_response.start( + id="id", + path="path", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + watch = await response.parse() + assert_matches_type(WatchStartResponse, watch, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_start(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.watch.with_raw_response.start( + id="", + path="path", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_stop(self, async_client: AsyncKernel) -> None: + watch = await async_client.browsers.fs.watch.stop( + watch_id="watch_id", + id="id", + ) + assert watch is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_stop(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.watch.with_raw_response.stop( + watch_id="watch_id", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + watch = await response.parse() + assert watch is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_stop(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.watch.with_streaming_response.stop( + watch_id="watch_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + watch = await response.parse() + assert watch is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_stop(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.watch.with_raw_response.stop( + watch_id="watch_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `watch_id` but received ''"): + await async_client.browsers.fs.watch.with_raw_response.stop( + watch_id="", + id="id", + ) diff --git a/tests/api_resources/browsers/test_fs.py b/tests/api_resources/browsers/test_fs.py new file mode 100644 index 0000000..c82e09d --- /dev/null +++ b/tests/api_resources/browsers/test_fs.py @@ -0,0 +1,977 @@ +# 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 httpx +import pytest +from respx import MockRouter + +from kernel import Kernel, AsyncKernel +from tests.utils import assert_matches_type +from kernel._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, +) +from kernel.types.browsers import ( + FFileInfoResponse, + FListFilesResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFs: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip() + @parametrize + def test_method_create_directory(self, client: Kernel) -> None: + f = client.browsers.fs.create_directory( + id="id", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_method_create_directory_with_all_params(self, client: Kernel) -> None: + f = client.browsers.fs.create_directory( + id="id", + path="/J!", + mode="0611", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_create_directory(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.create_directory( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_create_directory(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.create_directory( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_create_directory(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.create_directory( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + def test_method_delete_directory(self, client: Kernel) -> None: + f = client.browsers.fs.delete_directory( + id="id", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_delete_directory(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.delete_directory( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_delete_directory(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.delete_directory( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_delete_directory(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.delete_directory( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + def test_method_delete_file(self, client: Kernel) -> None: + f = client.browsers.fs.delete_file( + id="id", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_delete_file(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.delete_file( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_delete_file(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.delete_file( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_delete_file(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.delete_file( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + def test_method_file_info(self, client: Kernel) -> None: + f = client.browsers.fs.file_info( + id="id", + path="/J!", + ) + assert_matches_type(FFileInfoResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_raw_response_file_info(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.file_info( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert_matches_type(FFileInfoResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_streaming_response_file_info(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.file_info( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert_matches_type(FFileInfoResponse, f, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_file_info(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.file_info( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + def test_method_list_files(self, client: Kernel) -> None: + f = client.browsers.fs.list_files( + id="id", + path="/J!", + ) + assert_matches_type(FListFilesResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_raw_response_list_files(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.list_files( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert_matches_type(FListFilesResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_streaming_response_list_files(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.list_files( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert_matches_type(FListFilesResponse, f, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_list_files(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.list_files( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + def test_method_move(self, client: Kernel) -> None: + f = client.browsers.fs.move( + id="id", + dest_path="/J!", + src_path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_move(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.move( + id="id", + dest_path="/J!", + src_path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_move(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.move( + id="id", + dest_path="/J!", + src_path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_move(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.move( + id="", + dest_path="/J!", + src_path="/J!", + ) + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_read_file(self, client: Kernel, respx_mock: MockRouter) -> None: + respx_mock.get("/browsers/id/fs/read_file").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + f = client.browsers.fs.read_file( + id="id", + path="/J!", + ) + assert f.is_closed + assert f.json() == {"foo": "bar"} + assert cast(Any, f.is_closed) is True + assert isinstance(f, BinaryAPIResponse) + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_raw_response_read_file(self, client: Kernel, respx_mock: MockRouter) -> None: + respx_mock.get("/browsers/id/fs/read_file").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + f = client.browsers.fs.with_raw_response.read_file( + id="id", + path="/J!", + ) + + assert f.is_closed is True + assert f.http_request.headers.get("X-Stainless-Lang") == "python" + assert f.json() == {"foo": "bar"} + assert isinstance(f, BinaryAPIResponse) + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_streaming_response_read_file(self, client: Kernel, respx_mock: MockRouter) -> None: + respx_mock.get("/browsers/id/fs/read_file").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + with client.browsers.fs.with_streaming_response.read_file( + id="id", + path="/J!", + ) as f: + assert not f.is_closed + assert f.http_request.headers.get("X-Stainless-Lang") == "python" + + assert f.json() == {"foo": "bar"} + assert cast(Any, f.is_closed) is True + assert isinstance(f, StreamedBinaryAPIResponse) + + assert cast(Any, f.is_closed) is True + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_path_params_read_file(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.read_file( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + def test_method_set_file_permissions(self, client: Kernel) -> None: + f = client.browsers.fs.set_file_permissions( + id="id", + mode="0611", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_method_set_file_permissions_with_all_params(self, client: Kernel) -> None: + f = client.browsers.fs.set_file_permissions( + id="id", + mode="0611", + path="/J!", + group="group", + owner="owner", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_set_file_permissions(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.set_file_permissions( + id="id", + mode="0611", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_set_file_permissions(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.set_file_permissions( + id="id", + mode="0611", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_set_file_permissions(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.set_file_permissions( + id="", + mode="0611", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + def test_method_write_file(self, client: Kernel) -> None: + f = client.browsers.fs.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_method_write_file_with_all_params(self, client: Kernel) -> None: + f = client.browsers.fs.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + mode="0611", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_write_file(self, client: Kernel) -> None: + response = client.browsers.fs.with_raw_response.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_write_file(self, client: Kernel) -> None: + with client.browsers.fs.with_streaming_response.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_write_file(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.browsers.fs.with_raw_response.write_file( + id="", + contents=b"raw file contents", + path="/J!", + ) + + +class TestAsyncFs: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip() + @parametrize + async def test_method_create_directory(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.create_directory( + id="id", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_method_create_directory_with_all_params(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.create_directory( + id="id", + path="/J!", + mode="0611", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_create_directory(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.create_directory( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_create_directory(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.create_directory( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_create_directory(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.create_directory( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_delete_directory(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.delete_directory( + id="id", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_delete_directory(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.delete_directory( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_delete_directory(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.delete_directory( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_delete_directory(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.delete_directory( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_delete_file(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.delete_file( + id="id", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_delete_file(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.delete_file( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_delete_file(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.delete_file( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_delete_file(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.delete_file( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_file_info(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.file_info( + id="id", + path="/J!", + ) + assert_matches_type(FFileInfoResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_raw_response_file_info(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.file_info( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert_matches_type(FFileInfoResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_file_info(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.file_info( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert_matches_type(FFileInfoResponse, f, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_file_info(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.file_info( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_list_files(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.list_files( + id="id", + path="/J!", + ) + assert_matches_type(FListFilesResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_raw_response_list_files(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.list_files( + id="id", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert_matches_type(FListFilesResponse, f, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_list_files(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.list_files( + id="id", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert_matches_type(FListFilesResponse, f, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_list_files(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.list_files( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_move(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.move( + id="id", + dest_path="/J!", + src_path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_move(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.move( + id="id", + dest_path="/J!", + src_path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_move(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.move( + id="id", + dest_path="/J!", + src_path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_move(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.move( + id="", + dest_path="/J!", + src_path="/J!", + ) + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_read_file(self, async_client: AsyncKernel, respx_mock: MockRouter) -> None: + respx_mock.get("/browsers/id/fs/read_file").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + f = await async_client.browsers.fs.read_file( + id="id", + path="/J!", + ) + assert f.is_closed + assert await f.json() == {"foo": "bar"} + assert cast(Any, f.is_closed) is True + assert isinstance(f, AsyncBinaryAPIResponse) + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_raw_response_read_file(self, async_client: AsyncKernel, respx_mock: MockRouter) -> None: + respx_mock.get("/browsers/id/fs/read_file").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + f = await async_client.browsers.fs.with_raw_response.read_file( + id="id", + path="/J!", + ) + + assert f.is_closed is True + assert f.http_request.headers.get("X-Stainless-Lang") == "python" + assert await f.json() == {"foo": "bar"} + assert isinstance(f, AsyncBinaryAPIResponse) + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_streaming_response_read_file(self, async_client: AsyncKernel, respx_mock: MockRouter) -> None: + respx_mock.get("/browsers/id/fs/read_file").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + async with async_client.browsers.fs.with_streaming_response.read_file( + id="id", + path="/J!", + ) as f: + assert not f.is_closed + assert f.http_request.headers.get("X-Stainless-Lang") == "python" + + assert await f.json() == {"foo": "bar"} + assert cast(Any, f.is_closed) is True + assert isinstance(f, AsyncStreamedBinaryAPIResponse) + + assert cast(Any, f.is_closed) is True + + @pytest.mark.skip() + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_path_params_read_file(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.read_file( + id="", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_set_file_permissions(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.set_file_permissions( + id="id", + mode="0611", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_method_set_file_permissions_with_all_params(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.set_file_permissions( + id="id", + mode="0611", + path="/J!", + group="group", + owner="owner", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_set_file_permissions(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.set_file_permissions( + id="id", + mode="0611", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_set_file_permissions(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.set_file_permissions( + id="id", + mode="0611", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_set_file_permissions(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.set_file_permissions( + id="", + mode="0611", + path="/J!", + ) + + @pytest.mark.skip() + @parametrize + async def test_method_write_file(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_method_write_file_with_all_params(self, async_client: AsyncKernel) -> None: + f = await async_client.browsers.fs.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + mode="0611", + ) + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_write_file(self, async_client: AsyncKernel) -> None: + response = await async_client.browsers.fs.with_raw_response.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + f = await response.parse() + assert f is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_write_file(self, async_client: AsyncKernel) -> None: + async with async_client.browsers.fs.with_streaming_response.write_file( + id="id", + contents=b"raw file contents", + path="/J!", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + f = await response.parse() + assert f is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_write_file(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.browsers.fs.with_raw_response.write_file( + id="", + contents=b"raw file contents", + path="/J!", + ) From b3cb7da385f70061f4c37e748e0b1bf69c6b77c2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:18:20 +0000 Subject: [PATCH 3/3] release: 0.9.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 13 +++++++++++++ pyproject.toml | 2 +- src/kernel/_version.py | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a3bdfd2..6d78745 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.3" + ".": "0.9.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fe9a35..fddb4f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.9.0 (2025-08-08) + +Full Changelog: [v0.8.3...v0.9.0](https://github.com/onkernel/kernel-python-sdk/compare/v0.8.3...v0.9.0) + +### Features + +* **api:** browser instance file i/o ([14667cd](https://github.com/onkernel/kernel-python-sdk/commit/14667cdfd06540585ffac570b8963b322cf9ef23)) + + +### Chores + +* **internal:** fix ruff target version ([07b55e4](https://github.com/onkernel/kernel-python-sdk/commit/07b55e4a4b65b403b3b6f69b95b221e2020cf30b)) + ## 0.8.3 (2025-08-01) Full Changelog: [v0.8.2...v0.8.3](https://github.com/onkernel/kernel-python-sdk/compare/v0.8.2...v0.8.3) diff --git a/pyproject.toml b/pyproject.toml index a4c4b29..49f04c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.8.3" +version = "0.9.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 98240d7..a21b043 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.8.3" # x-release-please-version +__version__ = "0.9.0" # x-release-please-version