diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2fbefb942..85c311828 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.58.0" + ".": "0.59.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 900ce23a3..1eaf9aeec 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-6b4c63a026f224ec02ccd715e063e07107b545bb859218afaac2b3df84cd227a.yml -openapi_spec_hash: 76072cd766a9c45cff8890bb2bb8b1d5 -config_hash: a8ac5e38099129b07ae4decb0774719d +configured_endpoints: 102 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-a8e2289b32b616e0bd7e15995a6553d0335bd21e30617a013d07450f8f5a7a20.yml +openapi_spec_hash: cd13a7af1ffe64c7ce8753f87786e01f +config_hash: 457068371129b47b67f0f2d6b8267368 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5095bbba2..7b00c7c10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 0.59.0 (2025-09-08) + +Full Changelog: [v0.58.0...v0.59.0](https://github.com/runloopai/api-client-python/compare/v0.58.0...v0.59.0) + +### Features + +* **api:** api update ([d28f600](https://github.com/runloopai/api-client-python/commit/d28f60090e9c8c3c508812bfaf4bacbdd0b64330)) +* **api:** api update ([a7b44bc](https://github.com/runloopai/api-client-python/commit/a7b44bc091060518d507dbd806694de9ba09c1f8)) +* **api:** api update ([39c93bd](https://github.com/runloopai/api-client-python/commit/39c93bd7061e77c01fbb1cd913ede94ce90664c4)) + + +### Chores + +* **internal:** codegen related update ([4ed8b7a](https://github.com/runloopai/api-client-python/commit/4ed8b7a3ab98378214f74e79202051260f8488da)) +* **tests:** simplify `get_platform` test ([6b38a37](https://github.com/runloopai/api-client-python/commit/6b38a37e0e3630b360090fd4ab91b4ffc431c46c)) + ## 0.58.0 (2025-09-04) Full Changelog: [v0.57.0...v0.58.0](https://github.com/runloopai/api-client-python/compare/v0.57.0...v0.58.0) diff --git a/api.md b/api.md index 0c827fe6b..3076ddf36 100644 --- a/api.md +++ b/api.md @@ -73,6 +73,7 @@ Types: from runloop_api_client.types import ( DevboxAsyncExecutionDetailView, DevboxExecutionDetailView, + DevboxKillExecutionRequest, DevboxListView, DevboxSnapshotListView, DevboxSnapshotView, @@ -266,7 +267,8 @@ Methods: - client.devboxes.executions.execute_async(id, \*\*params) -> DevboxAsyncExecutionDetailView - client.devboxes.executions.execute_sync(id, \*\*params) -> DevboxExecutionDetailView - client.devboxes.executions.kill(execution_id, \*, devbox_id, \*\*params) -> DevboxAsyncExecutionDetailView -- client.devboxes.executions.stream_stdout_updates(execution_id, \*, devbox_id, \*\*params) -> DevboxAsyncExecutionDetailView +- client.devboxes.executions.stream_stderr_updates(execution_id, \*, devbox_id, \*\*params) -> ExecutionUpdateChunk +- client.devboxes.executions.stream_stdout_updates(execution_id, \*, devbox_id, \*\*params) -> ExecutionUpdateChunk # Scenarios diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 0a62aa9d6..000000000 --- a/mypy.ini +++ /dev/null @@ -1,50 +0,0 @@ -[mypy] -pretty = True -show_error_codes = True - -# Exclude _files.py because mypy isn't smart enough to apply -# the correct type narrowing and as this is an internal module -# it's fine to just use Pyright. -# -# We also exclude our `tests` as mypy doesn't always infer -# types correctly and Pyright will still catch any type errors. -exclude = ^(src/runloop_api_client/_files\.py|_dev/.*\.py|tests/.*)$ - -strict_equality = True -implicit_reexport = True -check_untyped_defs = True -no_implicit_optional = True - -warn_return_any = True -warn_unreachable = True -warn_unused_configs = True - -# Turn these options off as it could cause conflicts -# with the Pyright options. -warn_unused_ignores = False -warn_redundant_casts = False - -disallow_any_generics = True -disallow_untyped_defs = True -disallow_untyped_calls = True -disallow_subclassing_any = True -disallow_incomplete_defs = True -disallow_untyped_decorators = True -cache_fine_grained = True - -# By default, mypy reports an error if you assign a value to the result -# of a function call that doesn't return anything. We do this in our test -# cases: -# ``` -# result = ... -# assert result is None -# ``` -# Changing this codegen to make mypy happy would increase complexity -# and would not be worth it. -disable_error_code = func-returns-value,overload-cannot-match - -# https://github.com/python/mypy/issues/12162 -[mypy.overrides] -module = "black.files.*" -ignore_errors = true -ignore_missing_imports = true diff --git a/pyproject.toml b/pyproject.toml index 52e917e86..3e52c5ea7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "runloop_api_client" -version = "0.58.0" +version = "0.59.0" description = "The official Python library for the runloop API" dynamic = ["readme"] license = "MIT" @@ -57,7 +57,6 @@ dev-dependencies = [ "dirty-equals>=0.6.0", "importlib-metadata>=6.7.0", "rich>=13.7.1", - "nest_asyncio==1.6.0", "pytest-xdist>=3.6.1", ] @@ -166,6 +165,58 @@ reportOverlappingOverload = false reportImportCycles = false reportPrivateUsage = false +[tool.mypy] +pretty = true +show_error_codes = true + +# Exclude _files.py because mypy isn't smart enough to apply +# the correct type narrowing and as this is an internal module +# it's fine to just use Pyright. +# +# We also exclude our `tests` as mypy doesn't always infer +# types correctly and Pyright will still catch any type errors. +exclude = ['src/runloop_api_client/_files.py', '_dev/.*.py', 'tests/.*'] + +strict_equality = true +implicit_reexport = true +check_untyped_defs = true +no_implicit_optional = true + +warn_return_any = true +warn_unreachable = true +warn_unused_configs = true + +# Turn these options off as it could cause conflicts +# with the Pyright options. +warn_unused_ignores = false +warn_redundant_casts = false + +disallow_any_generics = true +disallow_untyped_defs = true +disallow_untyped_calls = true +disallow_subclassing_any = true +disallow_incomplete_defs = true +disallow_untyped_decorators = true +cache_fine_grained = true + +# By default, mypy reports an error if you assign a value to the result +# of a function call that doesn't return anything. We do this in our test +# cases: +# ``` +# result = ... +# assert result is None +# ``` +# Changing this codegen to make mypy happy would increase complexity +# and would not be worth it. +disable_error_code = "func-returns-value,overload-cannot-match" + +# https://github.com/python/mypy/issues/12162 +[[tool.mypy.overrides]] +module = "black.files.*" +ignore_errors = true +ignore_missing_imports = true + + [tool.ruff] line-length = 120 output-format = "grouped" diff --git a/requirements-dev.lock b/requirements-dev.lock index de857a2d6..2a74d01aa 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -75,7 +75,6 @@ multidict==6.4.4 mypy==1.14.1 mypy-extensions==1.0.0 # via mypy -nest-asyncio==1.6.0 nodeenv==1.8.0 # via pyright nox==2023.4.22 diff --git a/src/runloop_api_client/_version.py b/src/runloop_api_client/_version.py index d2b85015b..533907a8a 100644 --- a/src/runloop_api_client/_version.py +++ b/src/runloop_api_client/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "runloop_api_client" -__version__ = "0.58.0" # x-release-please-version +__version__ = "0.59.0" # x-release-please-version diff --git a/src/runloop_api_client/resources/devboxes/executions.py b/src/runloop_api_client/resources/devboxes/executions.py index 0002113ff..27cd21c79 100755 --- a/src/runloop_api_client/resources/devboxes/executions.py +++ b/src/runloop_api_client/resources/devboxes/executions.py @@ -26,7 +26,8 @@ execution_retrieve_params, execution_execute_sync_params, execution_execute_async_params, - execution_stream_updates_params, + execution_stream_stderr_updates_params, + execution_stream_stdout_updates_params, ) from ...lib.polling_async import async_poll_until from ...types.devbox_execution_detail_view import DevboxExecutionDetailView @@ -299,6 +300,9 @@ def kill( killing the launched process. Optionally kill the entire process group. Args: + kill_process_group: Whether to kill the entire process group (default: false). If true, kills all + processes in the same process group as the target process. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -326,7 +330,7 @@ def kill( cast_to=DevboxAsyncExecutionDetailView, ) - def stream_stdout_updates( + def stream_stderr_updates( self, execution_id: str, *, @@ -340,7 +344,7 @@ def stream_stdout_updates( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Stream[ExecutionUpdateChunk]: """ - Tails the stdout logs for the given execution with SSE streaming + Tails the stderr logs for the given execution with SSE streaming Args: offset: The byte offset to start the stream from @@ -359,14 +363,14 @@ def stream_stdout_updates( raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") if extra_headers and extra_headers.get(RAW_RESPONSE_HEADER): return self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stdout_updates", + f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( - {"offset": offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": offset}, execution_stream_stderr_updates_params.ExecutionStreamStderrUpdatesParams ), ), cast_to=DevboxAsyncExecutionDetailView, @@ -377,14 +381,15 @@ def stream_stdout_updates( def create_stream(last_offset: str | None) -> Stream[ExecutionUpdateChunk]: new_offset = last_offset if last_offset is not None else (None if isinstance(offset, NotGiven) else offset) return self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stdout_updates", + f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( - {"offset": new_offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": new_offset}, + execution_stream_stderr_updates_params.ExecutionStreamStderrUpdatesParams, ), ), cast_to=DevboxAsyncExecutionDetailView, @@ -405,7 +410,7 @@ def get_offset(item: ExecutionUpdateChunk) -> str | None: ReconnectingStream(current_stream=initial_stream, stream_creator=create_stream, get_offset=get_offset), ) - def stream_stderr_updates( + def stream_stdout_updates( self, execution_id: str, *, @@ -419,7 +424,7 @@ def stream_stderr_updates( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Stream[ExecutionUpdateChunk]: """ - Tails the stderr logs for the given execution with SSE streaming + Tails the stdout logs for the given execution with SSE streaming Args: offset: The byte offset to start the stream from @@ -438,14 +443,14 @@ def stream_stderr_updates( raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") if extra_headers and extra_headers.get(RAW_RESPONSE_HEADER): return self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", + f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stdout_updates", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( - {"offset": offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": offset}, execution_stream_stdout_updates_params.ExecutionStreamStdoutUpdatesParams ), ), cast_to=DevboxAsyncExecutionDetailView, @@ -456,14 +461,15 @@ def stream_stderr_updates( def create_stream(last_offset: str | None) -> Stream[ExecutionUpdateChunk]: new_offset = last_offset if last_offset is not None else (None if isinstance(offset, NotGiven) else offset) return self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", + f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stdout_updates", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( - {"offset": new_offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": new_offset}, + execution_stream_stdout_updates_params.ExecutionStreamStdoutUpdatesParams, ), ), cast_to=DevboxAsyncExecutionDetailView, @@ -736,6 +742,9 @@ async def kill( killing the launched process. Optionally kill the entire process group. Args: + kill_process_group: Whether to kill the entire process group (default: false). If true, kills all + processes in the same process group as the target process. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -765,7 +774,7 @@ async def kill( cast_to=DevboxAsyncExecutionDetailView, ) - async def stream_updates( + async def stream_stderr_updates( self, execution_id: str, *, @@ -779,7 +788,7 @@ async def stream_updates( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncStream[ExecutionUpdateChunk]: """ - Tails the logs for the given execution with SSE streaming + Tails the stderr logs for the given execution with SSE streaming Args: offset: The byte offset to start the stream from @@ -796,17 +805,16 @@ async def stream_updates( raise ValueError(f"Expected a non-empty value for `devbox_id` but received {devbox_id!r}") if not execution_id: raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - # If caller requested a raw or streaming response wrapper, return the underlying stream as-is if extra_headers and extra_headers.get(RAW_RESPONSE_HEADER): return await self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_updates", + f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"offset": offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": offset}, execution_stream_stderr_updates_params.ExecutionStreamStderrUpdatesParams ), ), cast_to=DevboxAsyncExecutionDetailView, @@ -817,14 +825,15 @@ async def stream_updates( async def create_stream(last_offset: str | None) -> AsyncStream[ExecutionUpdateChunk]: new_offset = last_offset if last_offset is not None else (None if isinstance(offset, NotGiven) else offset) return await self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_updates", + f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"offset": new_offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": new_offset}, + execution_stream_stderr_updates_params.ExecutionStreamStderrUpdatesParams, ), ), cast_to=DevboxAsyncExecutionDetailView, @@ -876,6 +885,7 @@ async def stream_stdout_updates( raise ValueError(f"Expected a non-empty value for `devbox_id` but received {devbox_id!r}") if not execution_id: raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + # If caller requested a raw or streaming response wrapper, return the underlying stream as-is if extra_headers and extra_headers.get(RAW_RESPONSE_HEADER): return await self._get( f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stdout_updates", @@ -885,7 +895,7 @@ async def stream_stdout_updates( extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"offset": offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": offset}, execution_stream_stdout_updates_params.ExecutionStreamStdoutUpdatesParams ), ), cast_to=DevboxAsyncExecutionDetailView, @@ -903,86 +913,8 @@ async def create_stream(last_offset: str | None) -> AsyncStream[ExecutionUpdateC extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"offset": new_offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams - ), - ), - cast_to=DevboxAsyncExecutionDetailView, - stream=True, - stream_cls=AsyncStream[ExecutionUpdateChunk], - ) - - initial_stream = await create_stream(None) - - def get_offset(item: ExecutionUpdateChunk) -> str | None: - value = getattr(item, "offset", None) - if value is None: - return None - return str(value) - - return cast( - AsyncStream[ExecutionUpdateChunk], - AsyncReconnectingStream(current_stream=initial_stream, stream_creator=create_stream, get_offset=get_offset), - ) - - async def stream_stderr_updates( - self, - execution_id: str, - *, - devbox_id: str, - offset: 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, - ) -> AsyncStream[ExecutionUpdateChunk]: - """ - Tails the stderr logs for the given execution with SSE streaming - - Args: - offset: The byte offset to start the stream from - - 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 devbox_id: - raise ValueError(f"Expected a non-empty value for `devbox_id` but received {devbox_id!r}") - if not execution_id: - raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - if extra_headers and extra_headers.get(RAW_RESPONSE_HEADER): - return await self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"offset": offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams - ), - ), - cast_to=DevboxAsyncExecutionDetailView, - stream=True, - stream_cls=AsyncStream[ExecutionUpdateChunk], - ) - - async def create_stream(last_offset: str | None) -> AsyncStream[ExecutionUpdateChunk]: - new_offset = last_offset if last_offset is not None else (None if isinstance(offset, NotGiven) else offset) - return await self._get( - f"/v1/devboxes/{devbox_id}/executions/{execution_id}/stream_stderr_updates", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"offset": new_offset}, execution_stream_updates_params.ExecutionStreamUpdatesParams + {"offset": new_offset}, + execution_stream_stdout_updates_params.ExecutionStreamStdoutUpdatesParams, ), ), cast_to=DevboxAsyncExecutionDetailView, diff --git a/src/runloop_api_client/types/devboxes/__init__.py b/src/runloop_api_client/types/devboxes/__init__.py index 43e642744..472d68e9a 100644 --- a/src/runloop_api_client/types/devboxes/__init__.py +++ b/src/runloop_api_client/types/devboxes/__init__.py @@ -77,7 +77,6 @@ from .code_action_application_result import CodeActionApplicationResult as CodeActionApplicationResult from .execution_execute_async_params import ExecutionExecuteAsyncParams as ExecutionExecuteAsyncParams from .lsp_set_watch_directory_params import LspSetWatchDirectoryParams as LspSetWatchDirectoryParams -from .execution_stream_updates_params import ExecutionStreamUpdatesParams as ExecutionStreamUpdatesParams from .lsp_get_code_segment_info_params import LspGetCodeSegmentInfoParams as LspGetCodeSegmentInfoParams from .lsp_set_watch_directory_response import LspSetWatchDirectoryResponse as LspSetWatchDirectoryResponse from .computer_mouse_interaction_params import ComputerMouseInteractionParams as ComputerMouseInteractionParams @@ -91,6 +90,12 @@ from .computer_keyboard_interaction_response import ( ComputerKeyboardInteractionResponse as ComputerKeyboardInteractionResponse, ) +from .execution_stream_stderr_updates_params import ( + ExecutionStreamStderrUpdatesParams as ExecutionStreamStderrUpdatesParams, +) +from .execution_stream_stdout_updates_params import ( + ExecutionStreamStdoutUpdatesParams as ExecutionStreamStdoutUpdatesParams, +) from .lsp_get_code_actions_for_diagnostic_params import ( LspGetCodeActionsForDiagnosticParams as LspGetCodeActionsForDiagnosticParams, ) diff --git a/src/runloop_api_client/types/devboxes/execution_kill_params.py b/src/runloop_api_client/types/devboxes/execution_kill_params.py index 384da945c..0df5c8615 100644 --- a/src/runloop_api_client/types/devboxes/execution_kill_params.py +++ b/src/runloop_api_client/types/devboxes/execution_kill_params.py @@ -12,3 +12,7 @@ class ExecutionKillParams(TypedDict, total=False): devbox_id: Required[str] kill_process_group: Optional[bool] + """Whether to kill the entire process group (default: false). + + If true, kills all processes in the same process group as the target process. + """ diff --git a/src/runloop_api_client/types/devboxes/execution_stream_updates_params.py b/src/runloop_api_client/types/devboxes/execution_stream_stderr_updates_params.py similarity index 70% rename from src/runloop_api_client/types/devboxes/execution_stream_updates_params.py rename to src/runloop_api_client/types/devboxes/execution_stream_stderr_updates_params.py index 3473cbc2c..b82639556 100644 --- a/src/runloop_api_client/types/devboxes/execution_stream_updates_params.py +++ b/src/runloop_api_client/types/devboxes/execution_stream_stderr_updates_params.py @@ -4,10 +4,10 @@ from typing_extensions import Required, TypedDict -__all__ = ["ExecutionStreamUpdatesParams"] +__all__ = ["ExecutionStreamStderrUpdatesParams"] -class ExecutionStreamUpdatesParams(TypedDict, total=False): +class ExecutionStreamStderrUpdatesParams(TypedDict, total=False): devbox_id: Required[str] offset: str diff --git a/src/runloop_api_client/types/devboxes/execution_stream_stdout_updates_params.py b/src/runloop_api_client/types/devboxes/execution_stream_stdout_updates_params.py new file mode 100644 index 000000000..7296156b0 --- /dev/null +++ b/src/runloop_api_client/types/devboxes/execution_stream_stdout_updates_params.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["ExecutionStreamStdoutUpdatesParams"] + + +class ExecutionStreamStdoutUpdatesParams(TypedDict, total=False): + devbox_id: Required[str] + + offset: str + """The byte offset to start the stream from""" diff --git a/src/runloop_api_client/types/devboxes/execution_update_chunk.py b/src/runloop_api_client/types/devboxes/execution_update_chunk.py index f5366d0cb..eda7add55 100644 --- a/src/runloop_api_client/types/devboxes/execution_update_chunk.py +++ b/src/runloop_api_client/types/devboxes/execution_update_chunk.py @@ -1,7 +1,6 @@ # 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 @@ -9,32 +8,8 @@ class ExecutionUpdateChunk(BaseModel): - devbox_id: str - """Devbox id where command was executed.""" + output: str + """The latest log stream chunk.""" - execution_id: str - """Ephemeral id of the execution in progress.""" - - status: Literal["queued", "running", "completed"] - """Current status of the execution.""" - - exit_status: Optional[int] = None - """Exit code of command execution. - - This field will remain unset until the execution has completed. - """ - - shell_name: Optional[str] = None - """Shell name.""" - - stderr: Optional[str] = None - """Standard error generated by command. - - This field will remain unset until the execution has completed. - """ - - stdout: Optional[str] = None - """Standard out generated by command. - - This field will remain unset until the execution has completed. - """ + offset: Optional[int] = None + """The byte offset of this chunk of log stream.""" diff --git a/tests/test_client.py b/tests/test_client.py index cb84f9ebe..ca53896b3 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -6,13 +6,10 @@ import os import sys import json -import time import asyncio import inspect -import subprocess import tracemalloc from typing import Any, Union, cast -from textwrap import dedent from unittest import mock from typing_extensions import Literal @@ -23,14 +20,17 @@ from runloop_api_client import Runloop, AsyncRunloop, APIResponseValidationError from runloop_api_client._types import Omit +from runloop_api_client._utils import asyncify from runloop_api_client._models import BaseModel, FinalRequestOptions from runloop_api_client._exceptions import RunloopError, APIStatusError, APITimeoutError, APIResponseValidationError from runloop_api_client._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, + OtherPlatform, DefaultHttpxClient, DefaultAsyncHttpxClient, + get_platform, make_request_options, ) @@ -1727,50 +1727,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert response.http_request.headers.get("x-stainless-retry-count") == "42" - def test_get_platform(self) -> None: - # A previous implementation of asyncify could leave threads unterminated when - # used with nest_asyncio. - # - # Since nest_asyncio.apply() is global and cannot be un-applied, this - # test is run in a separate process to avoid affecting other tests. - test_code = dedent(""" - import asyncio - import nest_asyncio - import threading - - from runloop_api_client._utils import asyncify - from runloop_api_client._base_client import get_platform - - async def test_main() -> None: - result = await asyncify(get_platform)() - print(result) - for thread in threading.enumerate(): - print(thread.name) - - nest_asyncio.apply() - asyncio.run(test_main()) - """) - with subprocess.Popen( - [sys.executable, "-c", test_code], - text=True, - ) as process: - timeout = 10 # seconds - - start_time = time.monotonic() - while True: - return_code = process.poll() - if return_code is not None: - if return_code != 0: - raise AssertionError("calling get_platform using asyncify resulted in a non-zero exit code") - - # success - break - - if time.monotonic() - start_time > timeout: - process.kill() - raise AssertionError("calling get_platform using asyncify resulted in a hung process") - - time.sleep(0.1) + async def test_get_platform(self) -> None: + platform = await asyncify(get_platform)() + assert isinstance(platform, (str, OtherPlatform)) async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly