From 150113bfd23a5e6376e6600a338d7c50ccfe0095 Mon Sep 17 00:00:00 2001 From: stainless-bot Date: Fri, 23 Aug 2024 20:48:52 +0000 Subject: [PATCH] feat(api): manual updates --- .release-please-manifest.json | 2 +- .stats.yml | 4 +- README.md | 2 +- api.md | 64 +- pyproject.toml | 2 +- src/runloop_api_client/_client.py | 8 + src/runloop_api_client/_constants.py | 6 +- src/runloop_api_client/_version.py | 2 +- src/runloop_api_client/resources/__init__.py | 14 + .../resources/deployments.py | 488 ++++++++++++++ .../resources/devboxes/__init__.py | 14 + .../resources/devboxes/devboxes.py | 213 +++++- .../resources/devboxes/executions.py | 598 +++++++++++++++++ .../resources/devboxes/logs.py | 88 ++- .../resources/functions/functions.py | 50 ++ .../resources/functions/invocations.py | 79 +++ src/runloop_api_client/types/__init__.py | 11 +- .../types/deployment_get_params.py | 15 + .../types/deployment_get_response.py | 59 ++ .../types/deployment_logs_response.py | 26 + .../types/deployment_redeploy_response.py | 50 ++ .../types/deployment_retrieve_response.py | 50 ++ .../types/deployment_tail_response.py | 26 + .../types/devbox_create_ssh_key_response.py | 18 + .../types/devbox_execute_async_params.py | 12 + .../types/devbox_list_response.py | 17 + src/runloop_api_client/types/devbox_view.py | 3 + .../types/devboxes/__init__.py | 5 + .../devbox_async_execution_detail_view.py | 37 ++ .../devboxes/devbox_execution_detail_view.py | 21 + .../execution_execute_async_params.py | 12 + .../devboxes/execution_execute_sync_params.py | 12 + .../devboxes/execution_retrieve_params.py | 14 + .../types/functions/__init__.py | 1 + .../functions/invocation_logs_response.py | 26 + .../api_resources/devboxes/test_executions.py | 612 ++++++++++++++++++ tests/api_resources/devboxes/test_logs.py | 76 +++ .../functions/test_invocations.py | 81 ++- tests/api_resources/test_deployments.py | 398 ++++++++++++ tests/api_resources/test_devboxes.py | 189 +++++- tests/api_resources/test_functions.py | 50 ++ tests/test_client.py | 52 +- 42 files changed, 3443 insertions(+), 64 deletions(-) create mode 100755 src/runloop_api_client/resources/deployments.py create mode 100755 src/runloop_api_client/resources/devboxes/executions.py create mode 100755 src/runloop_api_client/types/deployment_get_params.py create mode 100755 src/runloop_api_client/types/deployment_get_response.py create mode 100755 src/runloop_api_client/types/deployment_logs_response.py create mode 100755 src/runloop_api_client/types/deployment_redeploy_response.py create mode 100755 src/runloop_api_client/types/deployment_retrieve_response.py create mode 100755 src/runloop_api_client/types/deployment_tail_response.py create mode 100755 src/runloop_api_client/types/devbox_create_ssh_key_response.py create mode 100755 src/runloop_api_client/types/devbox_execute_async_params.py create mode 100755 src/runloop_api_client/types/devbox_list_response.py create mode 100755 src/runloop_api_client/types/devboxes/devbox_async_execution_detail_view.py create mode 100755 src/runloop_api_client/types/devboxes/devbox_execution_detail_view.py create mode 100755 src/runloop_api_client/types/devboxes/execution_execute_async_params.py create mode 100755 src/runloop_api_client/types/devboxes/execution_execute_sync_params.py create mode 100755 src/runloop_api_client/types/devboxes/execution_retrieve_params.py create mode 100755 src/runloop_api_client/types/functions/invocation_logs_response.py create mode 100755 tests/api_resources/devboxes/test_executions.py create mode 100755 tests/api_resources/test_deployments.py diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 000572ece..b0699969f 100755 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.13" + ".": "0.1.0-alpha.14" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index cd6612ae1..41b5ab409 100755 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-8c7e1b2377a7a76ebd891bda5df65c28f1574bae085e0460b8f614811bb193fe.yml +configured_endpoints: 36 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-ea589851f2dbba35fea6c010ac4c577cad56aa44e1d5bd4e5b472c802b2f13c4.yml diff --git a/README.md b/README.md index c30cc313a..8dc4c7e51 100755 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ Error codes are as followed: ### Retries -Certain errors are automatically retried 0 times by default, with a short exponential backoff. +Certain errors are automatically retried 2 times by default, with a short exponential backoff. Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors are all retried by default. diff --git a/api.md b/api.md index 292241006..ba23ae8ae 100755 --- a/api.md +++ b/api.md @@ -43,15 +43,37 @@ Types: from runloop_api_client.types import CodeMountParameters ``` +# Deployments + +Types: + +```python +from runloop_api_client.types import ( + DeploymentRetrieveResponse, + DeploymentGetResponse, + DeploymentLogsResponse, + DeploymentRedeployResponse, + DeploymentTailResponse, +) +``` + +Methods: + +- client.deployments.retrieve(deployment_id) -> DeploymentRetrieveResponse +- client.deployments.get(\*\*params) -> DeploymentGetResponse +- client.deployments.logs(deployment_id) -> DeploymentLogsResponse +- client.deployments.redeploy(deployment_id) -> DeploymentRedeployResponse +- client.deployments.tail(deployment_id) -> DeploymentTailResponse + # Devboxes Types: ```python from runloop_api_client.types import ( - DevboxExecutionDetailView, - DevboxListView, DevboxView, + DevboxListResponse, + DevboxCreateSSHKeyResponse, DevboxReadFileContentsResponse, DevboxUploadFileResponse, ) @@ -61,31 +83,49 @@ Methods: - client.devboxes.create(\*\*params) -> DevboxView - client.devboxes.retrieve(id) -> DevboxView -- client.devboxes.list(\*\*params) -> DevboxListView -- client.devboxes.execute_sync(id, \*\*params) -> DevboxExecutionDetailView +- client.devboxes.list(\*\*params) -> DevboxListResponse +- client.devboxes.create_ssh_key(id) -> DevboxCreateSSHKeyResponse +- client.devboxes.execute_async(id, \*\*params) -> DevboxAsyncExecutionDetailView +- client.devboxes.execute_sync(id, \*\*params) -> DevboxExecutionDetailView - client.devboxes.read_file_contents(id, \*\*params) -> str - client.devboxes.shutdown(id) -> DevboxView - client.devboxes.upload_file(id, \*\*params) -> object -- client.devboxes.write_file(id, \*\*params) -> DevboxExecutionDetailView +- client.devboxes.write_file(id, \*\*params) -> DevboxExecutionDetailView ## Logs +Methods: + +- client.devboxes.logs.list(id) -> DevboxLogsListView +- client.devboxes.logs.tail(id) -> None + +## Executions + Types: ```python -from runloop_api_client.types.devboxes import DevboxLogsListView +from runloop_api_client.types.devboxes import ( + DevboxAsyncExecutionDetailView, + DevboxExecutionDetailView, + DevboxLogsListView, +) ``` Methods: -- client.devboxes.logs.list(id) -> DevboxLogsListView +- client.devboxes.executions.retrieve(exe_id, \*, id, \*\*params) -> DevboxAsyncExecutionDetailView +- client.devboxes.executions.execute_async(id, \*\*params) -> DevboxAsyncExecutionDetailView +- client.devboxes.executions.execute_sync(id, \*\*params) -> DevboxExecutionDetailView +- client.devboxes.executions.kill(exe_id, \*, id) -> DevboxAsyncExecutionDetailView +- client.devboxes.executions.logs(execution_id, \*, id) -> DevboxLogsListView +- client.devboxes.executions.tail(execution_id, \*, id) -> None # Functions Types: ```python -from runloop_api_client.types import FunctionListView +from runloop_api_client.types import FunctionListView, FunctionListOpenAPIResponse ``` Methods: @@ -93,13 +133,18 @@ Methods: - client.functions.list() -> FunctionListView - client.functions.invoke_async(function_name, \*, project_name, \*\*params) -> FunctionInvocationExecutionDetailView - client.functions.invoke_sync(function_name, \*, project_name, \*\*params) -> FunctionInvocationExecutionDetailView +- client.functions.list_openapi() -> object ## Invocations Types: ```python -from runloop_api_client.types.functions import FunctionInvocationListView, KillOperationResponse +from runloop_api_client.types.functions import ( + FunctionInvocationListView, + KillOperationResponse, + InvocationLogsResponse, +) ``` Methods: @@ -107,6 +152,7 @@ Methods: - client.functions.invocations.retrieve(invocation_id) -> FunctionInvocationExecutionDetailView - client.functions.invocations.list(\*\*params) -> FunctionInvocationListView - client.functions.invocations.kill(invocation_id) -> object +- client.functions.invocations.logs(invocation_id) -> InvocationLogsResponse # Projects diff --git a/pyproject.toml b/pyproject.toml index cdeb9d124..22380a1af 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "runloop_api_client" -version = "0.1.0-alpha.13" +version = "0.1.0-alpha.14" description = "The official Python library for the runloop API" dynamic = ["readme"] license = "MIT" diff --git a/src/runloop_api_client/_client.py b/src/runloop_api_client/_client.py index 1609aebcc..f173ecd62 100755 --- a/src/runloop_api_client/_client.py +++ b/src/runloop_api_client/_client.py @@ -47,6 +47,7 @@ class Runloop(SyncAPIClient): blueprints: resources.BlueprintsResource + deployments: resources.DeploymentsResource devboxes: resources.DevboxesResource functions: resources.FunctionsResource projects: resources.ProjectsResource @@ -108,6 +109,7 @@ def __init__( ) self.blueprints = resources.BlueprintsResource(self) + self.deployments = resources.DeploymentsResource(self) self.devboxes = resources.DevboxesResource(self) self.functions = resources.FunctionsResource(self) self.projects = resources.ProjectsResource(self) @@ -221,6 +223,7 @@ def _make_status_error( class AsyncRunloop(AsyncAPIClient): blueprints: resources.AsyncBlueprintsResource + deployments: resources.AsyncDeploymentsResource devboxes: resources.AsyncDevboxesResource functions: resources.AsyncFunctionsResource projects: resources.AsyncProjectsResource @@ -282,6 +285,7 @@ def __init__( ) self.blueprints = resources.AsyncBlueprintsResource(self) + self.deployments = resources.AsyncDeploymentsResource(self) self.devboxes = resources.AsyncDevboxesResource(self) self.functions = resources.AsyncFunctionsResource(self) self.projects = resources.AsyncProjectsResource(self) @@ -396,6 +400,7 @@ def _make_status_error( class RunloopWithRawResponse: def __init__(self, client: Runloop) -> None: self.blueprints = resources.BlueprintsResourceWithRawResponse(client.blueprints) + self.deployments = resources.DeploymentsResourceWithRawResponse(client.deployments) self.devboxes = resources.DevboxesResourceWithRawResponse(client.devboxes) self.functions = resources.FunctionsResourceWithRawResponse(client.functions) self.projects = resources.ProjectsResourceWithRawResponse(client.projects) @@ -404,6 +409,7 @@ def __init__(self, client: Runloop) -> None: class AsyncRunloopWithRawResponse: def __init__(self, client: AsyncRunloop) -> None: self.blueprints = resources.AsyncBlueprintsResourceWithRawResponse(client.blueprints) + self.deployments = resources.AsyncDeploymentsResourceWithRawResponse(client.deployments) self.devboxes = resources.AsyncDevboxesResourceWithRawResponse(client.devboxes) self.functions = resources.AsyncFunctionsResourceWithRawResponse(client.functions) self.projects = resources.AsyncProjectsResourceWithRawResponse(client.projects) @@ -412,6 +418,7 @@ def __init__(self, client: AsyncRunloop) -> None: class RunloopWithStreamedResponse: def __init__(self, client: Runloop) -> None: self.blueprints = resources.BlueprintsResourceWithStreamingResponse(client.blueprints) + self.deployments = resources.DeploymentsResourceWithStreamingResponse(client.deployments) self.devboxes = resources.DevboxesResourceWithStreamingResponse(client.devboxes) self.functions = resources.FunctionsResourceWithStreamingResponse(client.functions) self.projects = resources.ProjectsResourceWithStreamingResponse(client.projects) @@ -420,6 +427,7 @@ def __init__(self, client: Runloop) -> None: class AsyncRunloopWithStreamedResponse: def __init__(self, client: AsyncRunloop) -> None: self.blueprints = resources.AsyncBlueprintsResourceWithStreamingResponse(client.blueprints) + self.deployments = resources.AsyncDeploymentsResourceWithStreamingResponse(client.deployments) self.devboxes = resources.AsyncDevboxesResourceWithStreamingResponse(client.devboxes) self.functions = resources.AsyncFunctionsResourceWithStreamingResponse(client.functions) self.projects = resources.AsyncProjectsResourceWithStreamingResponse(client.projects) diff --git a/src/runloop_api_client/_constants.py b/src/runloop_api_client/_constants.py index 8e36fea12..a2ac3b6f3 100755 --- a/src/runloop_api_client/_constants.py +++ b/src/runloop_api_client/_constants.py @@ -7,8 +7,8 @@ # default timeout is 1 minute DEFAULT_TIMEOUT = httpx.Timeout(timeout=60.0, connect=5.0) -DEFAULT_MAX_RETRIES = 0 +DEFAULT_MAX_RETRIES = 2 DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20) -INITIAL_RETRY_DELAY = 1.0 -MAX_RETRY_DELAY = 5.0 +INITIAL_RETRY_DELAY = 0.5 +MAX_RETRY_DELAY = 8.0 diff --git a/src/runloop_api_client/_version.py b/src/runloop_api_client/_version.py index afe22f572..70a399d94 100755 --- 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.1.0-alpha.13" # x-release-please-version +__version__ = "0.1.0-alpha.14" # x-release-please-version diff --git a/src/runloop_api_client/resources/__init__.py b/src/runloop_api_client/resources/__init__.py index f36499829..e26ff0410 100755 --- a/src/runloop_api_client/resources/__init__.py +++ b/src/runloop_api_client/resources/__init__.py @@ -32,6 +32,14 @@ BlueprintsResourceWithStreamingResponse, AsyncBlueprintsResourceWithStreamingResponse, ) +from .deployments import ( + DeploymentsResource, + AsyncDeploymentsResource, + DeploymentsResourceWithRawResponse, + AsyncDeploymentsResourceWithRawResponse, + DeploymentsResourceWithStreamingResponse, + AsyncDeploymentsResourceWithStreamingResponse, +) __all__ = [ "BlueprintsResource", @@ -40,6 +48,12 @@ "AsyncBlueprintsResourceWithRawResponse", "BlueprintsResourceWithStreamingResponse", "AsyncBlueprintsResourceWithStreamingResponse", + "DeploymentsResource", + "AsyncDeploymentsResource", + "DeploymentsResourceWithRawResponse", + "AsyncDeploymentsResourceWithRawResponse", + "DeploymentsResourceWithStreamingResponse", + "AsyncDeploymentsResourceWithStreamingResponse", "DevboxesResource", "AsyncDevboxesResource", "DevboxesResourceWithRawResponse", diff --git a/src/runloop_api_client/resources/deployments.py b/src/runloop_api_client/resources/deployments.py new file mode 100755 index 000000000..70abbe237 --- /dev/null +++ b/src/runloop_api_client/resources/deployments.py @@ -0,0 +1,488 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import deployment_get_params +from .._types import NOT_GIVEN, Body, Query, Headers, 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 .._base_client import make_request_options +from ..types.deployment_get_response import DeploymentGetResponse +from ..types.deployment_logs_response import DeploymentLogsResponse +from ..types.deployment_tail_response import DeploymentTailResponse +from ..types.deployment_redeploy_response import DeploymentRedeployResponse +from ..types.deployment_retrieve_response import DeploymentRetrieveResponse + +__all__ = ["DeploymentsResource", "AsyncDeploymentsResource"] + + +class DeploymentsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> DeploymentsResourceWithRawResponse: + return DeploymentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DeploymentsResourceWithStreamingResponse: + return DeploymentsResourceWithStreamingResponse(self) + + def retrieve( + self, + deployment_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, + ) -> DeploymentRetrieveResponse: + """ + Get details of a deployment + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return self._get( + f"/v1/deployments/{deployment_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentRetrieveResponse, + ) + + def get( + self, + *, + limit: str | NotGiven = NOT_GIVEN, + starting_after: 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, + ) -> DeploymentGetResponse: + """ + Get list of all deployments for the authenticated user. + + Args: + limit: Page Limit + + starting_after: Load the next page starting after the given token. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/deployments", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "starting_after": starting_after, + }, + deployment_get_params.DeploymentGetParams, + ), + ), + cast_to=DeploymentGetResponse, + ) + + def logs( + self, + deployment_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, + ) -> DeploymentLogsResponse: + """ + Get list of all logs from a deployment. + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return self._get( + f"/v1/deployments/{deployment_id}/logs", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentLogsResponse, + ) + + def redeploy( + self, + deployment_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, + ) -> DeploymentRedeployResponse: + """ + Creates a deployment for a previously deployed version. + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return self._post( + f"/v1/deployments/{deployment_id}/redeploy", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentRedeployResponse, + ) + + def tail( + self, + deployment_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, + ) -> DeploymentTailResponse: + """ + Tails the logs for the given deployment with SSE streaming + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return self._get( + f"/v1/deployments/{deployment_id}/logs/tail", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentTailResponse, + ) + + +class AsyncDeploymentsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncDeploymentsResourceWithRawResponse: + return AsyncDeploymentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDeploymentsResourceWithStreamingResponse: + return AsyncDeploymentsResourceWithStreamingResponse(self) + + async def retrieve( + self, + deployment_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, + ) -> DeploymentRetrieveResponse: + """ + Get details of a deployment + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return await self._get( + f"/v1/deployments/{deployment_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentRetrieveResponse, + ) + + async def get( + self, + *, + limit: str | NotGiven = NOT_GIVEN, + starting_after: 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, + ) -> DeploymentGetResponse: + """ + Get list of all deployments for the authenticated user. + + Args: + limit: Page Limit + + starting_after: Load the next page starting after the given token. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/deployments", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "limit": limit, + "starting_after": starting_after, + }, + deployment_get_params.DeploymentGetParams, + ), + ), + cast_to=DeploymentGetResponse, + ) + + async def logs( + self, + deployment_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, + ) -> DeploymentLogsResponse: + """ + Get list of all logs from a deployment. + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return await self._get( + f"/v1/deployments/{deployment_id}/logs", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentLogsResponse, + ) + + async def redeploy( + self, + deployment_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, + ) -> DeploymentRedeployResponse: + """ + Creates a deployment for a previously deployed version. + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return await self._post( + f"/v1/deployments/{deployment_id}/redeploy", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentRedeployResponse, + ) + + async def tail( + self, + deployment_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, + ) -> DeploymentTailResponse: + """ + Tails the logs for the given deployment with SSE streaming + + 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 deployment_id: + raise ValueError(f"Expected a non-empty value for `deployment_id` but received {deployment_id!r}") + return await self._get( + f"/v1/deployments/{deployment_id}/logs/tail", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeploymentTailResponse, + ) + + +class DeploymentsResourceWithRawResponse: + def __init__(self, deployments: DeploymentsResource) -> None: + self._deployments = deployments + + self.retrieve = to_raw_response_wrapper( + deployments.retrieve, + ) + self.get = to_raw_response_wrapper( + deployments.get, + ) + self.logs = to_raw_response_wrapper( + deployments.logs, + ) + self.redeploy = to_raw_response_wrapper( + deployments.redeploy, + ) + self.tail = to_raw_response_wrapper( + deployments.tail, + ) + + +class AsyncDeploymentsResourceWithRawResponse: + def __init__(self, deployments: AsyncDeploymentsResource) -> None: + self._deployments = deployments + + self.retrieve = async_to_raw_response_wrapper( + deployments.retrieve, + ) + self.get = async_to_raw_response_wrapper( + deployments.get, + ) + self.logs = async_to_raw_response_wrapper( + deployments.logs, + ) + self.redeploy = async_to_raw_response_wrapper( + deployments.redeploy, + ) + self.tail = async_to_raw_response_wrapper( + deployments.tail, + ) + + +class DeploymentsResourceWithStreamingResponse: + def __init__(self, deployments: DeploymentsResource) -> None: + self._deployments = deployments + + self.retrieve = to_streamed_response_wrapper( + deployments.retrieve, + ) + self.get = to_streamed_response_wrapper( + deployments.get, + ) + self.logs = to_streamed_response_wrapper( + deployments.logs, + ) + self.redeploy = to_streamed_response_wrapper( + deployments.redeploy, + ) + self.tail = to_streamed_response_wrapper( + deployments.tail, + ) + + +class AsyncDeploymentsResourceWithStreamingResponse: + def __init__(self, deployments: AsyncDeploymentsResource) -> None: + self._deployments = deployments + + self.retrieve = async_to_streamed_response_wrapper( + deployments.retrieve, + ) + self.get = async_to_streamed_response_wrapper( + deployments.get, + ) + self.logs = async_to_streamed_response_wrapper( + deployments.logs, + ) + self.redeploy = async_to_streamed_response_wrapper( + deployments.redeploy, + ) + self.tail = async_to_streamed_response_wrapper( + deployments.tail, + ) diff --git a/src/runloop_api_client/resources/devboxes/__init__.py b/src/runloop_api_client/resources/devboxes/__init__.py index 814a1ca00..ec7c746ac 100755 --- a/src/runloop_api_client/resources/devboxes/__init__.py +++ b/src/runloop_api_client/resources/devboxes/__init__.py @@ -16,6 +16,14 @@ DevboxesResourceWithStreamingResponse, AsyncDevboxesResourceWithStreamingResponse, ) +from .executions import ( + ExecutionsResource, + AsyncExecutionsResource, + ExecutionsResourceWithRawResponse, + AsyncExecutionsResourceWithRawResponse, + ExecutionsResourceWithStreamingResponse, + AsyncExecutionsResourceWithStreamingResponse, +) __all__ = [ "LogsResource", @@ -24,6 +32,12 @@ "AsyncLogsResourceWithRawResponse", "LogsResourceWithStreamingResponse", "AsyncLogsResourceWithStreamingResponse", + "ExecutionsResource", + "AsyncExecutionsResource", + "ExecutionsResourceWithRawResponse", + "AsyncExecutionsResourceWithRawResponse", + "ExecutionsResourceWithStreamingResponse", + "AsyncExecutionsResourceWithStreamingResponse", "DevboxesResource", "AsyncDevboxesResource", "DevboxesResourceWithRawResponse", diff --git a/src/runloop_api_client/resources/devboxes/devboxes.py b/src/runloop_api_client/resources/devboxes/devboxes.py index 7b1c0388d..4586a46b5 100755 --- a/src/runloop_api_client/resources/devboxes/devboxes.py +++ b/src/runloop_api_client/resources/devboxes/devboxes.py @@ -20,6 +20,7 @@ devbox_write_file_params, devbox_upload_file_params, devbox_execute_sync_params, + devbox_execute_async_params, devbox_read_file_contents_params, ) from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes @@ -30,6 +31,14 @@ async_maybe_transform, ) from ..._compat import cached_property +from .executions import ( + ExecutionsResource, + AsyncExecutionsResource, + ExecutionsResourceWithRawResponse, + AsyncExecutionsResourceWithRawResponse, + ExecutionsResourceWithStreamingResponse, + AsyncExecutionsResourceWithStreamingResponse, +) from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( to_raw_response_wrapper, @@ -39,8 +48,10 @@ ) from ..._base_client import make_request_options from ...types.devbox_view import DevboxView -from ...types.devbox_list_view import DevboxListView -from ...types.devbox_execution_detail_view import DevboxExecutionDetailView +from ...types.devbox_list_response import DevboxListResponse +from ...types.devbox_create_ssh_key_response import DevboxCreateSSHKeyResponse +from ...types.devboxes.devbox_execution_detail_view import DevboxExecutionDetailView +from ...types.devboxes.devbox_async_execution_detail_view import DevboxAsyncExecutionDetailView __all__ = ["DevboxesResource", "AsyncDevboxesResource"] @@ -50,6 +61,10 @@ class DevboxesResource(SyncAPIResource): def logs(self) -> LogsResource: return LogsResource(self._client) + @cached_property + def executions(self) -> ExecutionsResource: + return ExecutionsResource(self._client) + @cached_property def with_raw_response(self) -> DevboxesResourceWithRawResponse: return DevboxesResourceWithRawResponse(self) @@ -183,7 +198,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DevboxListView: + ) -> DevboxListResponse: """List all devboxes or filter by status. If no status is provided, all devboxes @@ -220,7 +235,77 @@ def list( devbox_list_params.DevboxListParams, ), ), - cast_to=DevboxListView, + cast_to=DevboxListResponse, + ) + + def create_ssh_key( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DevboxCreateSSHKeyResponse: + """ + Create an SSH key for a devbox by id. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + f"/v1/devboxes/{id}/create_ssh_key", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxCreateSSHKeyResponse, + ) + + def execute_async( + self, + id: str, + *, + command: 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, + ) -> DevboxAsyncExecutionDetailView: + """ + Asynchronously execute a command on a devbox + + Args: + command: The command to execute on the Devbox. + + 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"/v1/devboxes/{id}/executions/execute_async", + body=maybe_transform({"command": command}, devbox_execute_async_params.DevboxExecuteAsyncParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, ) def execute_sync( @@ -434,6 +519,10 @@ class AsyncDevboxesResource(AsyncAPIResource): def logs(self) -> AsyncLogsResource: return AsyncLogsResource(self._client) + @cached_property + def executions(self) -> AsyncExecutionsResource: + return AsyncExecutionsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncDevboxesResourceWithRawResponse: return AsyncDevboxesResourceWithRawResponse(self) @@ -567,7 +656,7 @@ async def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DevboxListView: + ) -> DevboxListResponse: """List all devboxes or filter by status. If no status is provided, all devboxes @@ -604,7 +693,79 @@ async def list( devbox_list_params.DevboxListParams, ), ), - cast_to=DevboxListView, + cast_to=DevboxListResponse, + ) + + async def create_ssh_key( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DevboxCreateSSHKeyResponse: + """ + Create an SSH key for a devbox by id. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + f"/v1/devboxes/{id}/create_ssh_key", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxCreateSSHKeyResponse, + ) + + async def execute_async( + self, + id: str, + *, + command: 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, + ) -> DevboxAsyncExecutionDetailView: + """ + Asynchronously execute a command on a devbox + + Args: + command: The command to execute on the Devbox. + + 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"/v1/devboxes/{id}/executions/execute_async", + body=await async_maybe_transform( + {"command": command}, devbox_execute_async_params.DevboxExecuteAsyncParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, ) async def execute_sync( @@ -826,6 +987,12 @@ def __init__(self, devboxes: DevboxesResource) -> None: self.list = to_raw_response_wrapper( devboxes.list, ) + self.create_ssh_key = to_raw_response_wrapper( + devboxes.create_ssh_key, + ) + self.execute_async = to_raw_response_wrapper( + devboxes.execute_async, + ) self.execute_sync = to_raw_response_wrapper( devboxes.execute_sync, ) @@ -846,6 +1013,10 @@ def __init__(self, devboxes: DevboxesResource) -> None: def logs(self) -> LogsResourceWithRawResponse: return LogsResourceWithRawResponse(self._devboxes.logs) + @cached_property + def executions(self) -> ExecutionsResourceWithRawResponse: + return ExecutionsResourceWithRawResponse(self._devboxes.executions) + class AsyncDevboxesResourceWithRawResponse: def __init__(self, devboxes: AsyncDevboxesResource) -> None: @@ -860,6 +1031,12 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None: self.list = async_to_raw_response_wrapper( devboxes.list, ) + self.create_ssh_key = async_to_raw_response_wrapper( + devboxes.create_ssh_key, + ) + self.execute_async = async_to_raw_response_wrapper( + devboxes.execute_async, + ) self.execute_sync = async_to_raw_response_wrapper( devboxes.execute_sync, ) @@ -880,6 +1057,10 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None: def logs(self) -> AsyncLogsResourceWithRawResponse: return AsyncLogsResourceWithRawResponse(self._devboxes.logs) + @cached_property + def executions(self) -> AsyncExecutionsResourceWithRawResponse: + return AsyncExecutionsResourceWithRawResponse(self._devboxes.executions) + class DevboxesResourceWithStreamingResponse: def __init__(self, devboxes: DevboxesResource) -> None: @@ -894,6 +1075,12 @@ def __init__(self, devboxes: DevboxesResource) -> None: self.list = to_streamed_response_wrapper( devboxes.list, ) + self.create_ssh_key = to_streamed_response_wrapper( + devboxes.create_ssh_key, + ) + self.execute_async = to_streamed_response_wrapper( + devboxes.execute_async, + ) self.execute_sync = to_streamed_response_wrapper( devboxes.execute_sync, ) @@ -914,6 +1101,10 @@ def __init__(self, devboxes: DevboxesResource) -> None: def logs(self) -> LogsResourceWithStreamingResponse: return LogsResourceWithStreamingResponse(self._devboxes.logs) + @cached_property + def executions(self) -> ExecutionsResourceWithStreamingResponse: + return ExecutionsResourceWithStreamingResponse(self._devboxes.executions) + class AsyncDevboxesResourceWithStreamingResponse: def __init__(self, devboxes: AsyncDevboxesResource) -> None: @@ -928,6 +1119,12 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None: self.list = async_to_streamed_response_wrapper( devboxes.list, ) + self.create_ssh_key = async_to_streamed_response_wrapper( + devboxes.create_ssh_key, + ) + self.execute_async = async_to_streamed_response_wrapper( + devboxes.execute_async, + ) self.execute_sync = async_to_streamed_response_wrapper( devboxes.execute_sync, ) @@ -947,3 +1144,7 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None: @cached_property def logs(self) -> AsyncLogsResourceWithStreamingResponse: return AsyncLogsResourceWithStreamingResponse(self._devboxes.logs) + + @cached_property + def executions(self) -> AsyncExecutionsResourceWithStreamingResponse: + return AsyncExecutionsResourceWithStreamingResponse(self._devboxes.executions) diff --git a/src/runloop_api_client/resources/devboxes/executions.py b/src/runloop_api_client/resources/devboxes/executions.py new file mode 100755 index 000000000..9b68a432f --- /dev/null +++ b/src/runloop_api_client/resources/devboxes/executions.py @@ -0,0 +1,598 @@ +# 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 ..._base_client import make_request_options +from ...types.devboxes import execution_retrieve_params, execution_execute_sync_params, execution_execute_async_params +from ...types.devboxes.devbox_logs_list_view import DevboxLogsListView +from ...types.devboxes.devbox_execution_detail_view import DevboxExecutionDetailView +from ...types.devboxes.devbox_async_execution_detail_view import DevboxAsyncExecutionDetailView + +__all__ = ["ExecutionsResource", "AsyncExecutionsResource"] + + +class ExecutionsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ExecutionsResourceWithRawResponse: + return ExecutionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ExecutionsResourceWithStreamingResponse: + return ExecutionsResourceWithStreamingResponse(self) + + def retrieve( + self, + exe_id: str, + *, + id: str, + command: 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, + ) -> DevboxAsyncExecutionDetailView: + """ + Get status of an execution on a devbox. + + Args: + command: The command to execute on the Devbox. + + 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 exe_id: + raise ValueError(f"Expected a non-empty value for `exe_id` but received {exe_id!r}") + return self._post( + f"/v1/devboxes/{id}/executions/{exe_id}", + body=maybe_transform({"command": command}, execution_retrieve_params.ExecutionRetrieveParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, + ) + + def execute_async( + self, + id: str, + *, + command: 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, + ) -> DevboxAsyncExecutionDetailView: + """ + Asynchronously execute a command on a devbox + + Args: + command: The command to execute on the Devbox. + + 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"/v1/devboxes/{id}/executions/execute_async", + body=maybe_transform({"command": command}, execution_execute_async_params.ExecutionExecuteAsyncParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, + ) + + def execute_sync( + self, + id: str, + *, + command: 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, + ) -> DevboxExecutionDetailView: + """ + Synchronously execute a command on a devbox + + Args: + command: The command to execute on the Devbox. + + 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"/v1/devboxes/{id}/execute_sync", + body=maybe_transform({"command": command}, execution_execute_sync_params.ExecutionExecuteSyncParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxExecutionDetailView, + ) + + def kill( + self, + exe_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, + ) -> DevboxAsyncExecutionDetailView: + """ + Kill an asynchronous execution currently running on a devbox + + 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 exe_id: + raise ValueError(f"Expected a non-empty value for `exe_id` but received {exe_id!r}") + return self._post( + f"/v1/devboxes/{id}/executions/{exe_id}/kill", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, + ) + + def logs( + self, + execution_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, + ) -> DevboxLogsListView: + """ + Get all logs from a Devbox execution by id. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not execution_id: + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return self._get( + f"/v1/devboxes/{id}/executions/{execution_id}/logs", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxLogsListView, + ) + + def tail( + self, + execution_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: + """Tail the logs for the given devbox async execution. + + This will return past log + entries and continue from there. This is a streaming api and will continue to + stream logs until the connection is closed. + + 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 execution_id: + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + f"/v1/devboxes/{id}/executions/{execution_id}/logs/tail", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncExecutionsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncExecutionsResourceWithRawResponse: + return AsyncExecutionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncExecutionsResourceWithStreamingResponse: + return AsyncExecutionsResourceWithStreamingResponse(self) + + async def retrieve( + self, + exe_id: str, + *, + id: str, + command: 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, + ) -> DevboxAsyncExecutionDetailView: + """ + Get status of an execution on a devbox. + + Args: + command: The command to execute on the Devbox. + + 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 exe_id: + raise ValueError(f"Expected a non-empty value for `exe_id` but received {exe_id!r}") + return await self._post( + f"/v1/devboxes/{id}/executions/{exe_id}", + body=await async_maybe_transform({"command": command}, execution_retrieve_params.ExecutionRetrieveParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, + ) + + async def execute_async( + self, + id: str, + *, + command: 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, + ) -> DevboxAsyncExecutionDetailView: + """ + Asynchronously execute a command on a devbox + + Args: + command: The command to execute on the Devbox. + + 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"/v1/devboxes/{id}/executions/execute_async", + body=await async_maybe_transform( + {"command": command}, execution_execute_async_params.ExecutionExecuteAsyncParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, + ) + + async def execute_sync( + self, + id: str, + *, + command: 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, + ) -> DevboxExecutionDetailView: + """ + Synchronously execute a command on a devbox + + Args: + command: The command to execute on the Devbox. + + 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"/v1/devboxes/{id}/execute_sync", + body=await async_maybe_transform( + {"command": command}, execution_execute_sync_params.ExecutionExecuteSyncParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxExecutionDetailView, + ) + + async def kill( + self, + exe_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, + ) -> DevboxAsyncExecutionDetailView: + """ + Kill an asynchronous execution currently running on a devbox + + 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 exe_id: + raise ValueError(f"Expected a non-empty value for `exe_id` but received {exe_id!r}") + return await self._post( + f"/v1/devboxes/{id}/executions/{exe_id}/kill", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxAsyncExecutionDetailView, + ) + + async def logs( + self, + execution_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, + ) -> DevboxLogsListView: + """ + Get all logs from a Devbox execution by id. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not execution_id: + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return await self._get( + f"/v1/devboxes/{id}/executions/{execution_id}/logs", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DevboxLogsListView, + ) + + async def tail( + self, + execution_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: + """Tail the logs for the given devbox async execution. + + This will return past log + entries and continue from there. This is a streaming api and will continue to + stream logs until the connection is closed. + + 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 execution_id: + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + f"/v1/devboxes/{id}/executions/{execution_id}/logs/tail", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class ExecutionsResourceWithRawResponse: + def __init__(self, executions: ExecutionsResource) -> None: + self._executions = executions + + self.retrieve = to_raw_response_wrapper( + executions.retrieve, + ) + self.execute_async = to_raw_response_wrapper( + executions.execute_async, + ) + self.execute_sync = to_raw_response_wrapper( + executions.execute_sync, + ) + self.kill = to_raw_response_wrapper( + executions.kill, + ) + self.logs = to_raw_response_wrapper( + executions.logs, + ) + self.tail = to_raw_response_wrapper( + executions.tail, + ) + + +class AsyncExecutionsResourceWithRawResponse: + def __init__(self, executions: AsyncExecutionsResource) -> None: + self._executions = executions + + self.retrieve = async_to_raw_response_wrapper( + executions.retrieve, + ) + self.execute_async = async_to_raw_response_wrapper( + executions.execute_async, + ) + self.execute_sync = async_to_raw_response_wrapper( + executions.execute_sync, + ) + self.kill = async_to_raw_response_wrapper( + executions.kill, + ) + self.logs = async_to_raw_response_wrapper( + executions.logs, + ) + self.tail = async_to_raw_response_wrapper( + executions.tail, + ) + + +class ExecutionsResourceWithStreamingResponse: + def __init__(self, executions: ExecutionsResource) -> None: + self._executions = executions + + self.retrieve = to_streamed_response_wrapper( + executions.retrieve, + ) + self.execute_async = to_streamed_response_wrapper( + executions.execute_async, + ) + self.execute_sync = to_streamed_response_wrapper( + executions.execute_sync, + ) + self.kill = to_streamed_response_wrapper( + executions.kill, + ) + self.logs = to_streamed_response_wrapper( + executions.logs, + ) + self.tail = to_streamed_response_wrapper( + executions.tail, + ) + + +class AsyncExecutionsResourceWithStreamingResponse: + def __init__(self, executions: AsyncExecutionsResource) -> None: + self._executions = executions + + self.retrieve = async_to_streamed_response_wrapper( + executions.retrieve, + ) + self.execute_async = async_to_streamed_response_wrapper( + executions.execute_async, + ) + self.execute_sync = async_to_streamed_response_wrapper( + executions.execute_sync, + ) + self.kill = async_to_streamed_response_wrapper( + executions.kill, + ) + self.logs = async_to_streamed_response_wrapper( + executions.logs, + ) + self.tail = async_to_streamed_response_wrapper( + executions.tail, + ) diff --git a/src/runloop_api_client/resources/devboxes/logs.py b/src/runloop_api_client/resources/devboxes/logs.py index cabe8f329..1f03fc023 100755 --- a/src/runloop_api_client/resources/devboxes/logs.py +++ b/src/runloop_api_client/resources/devboxes/logs.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -61,6 +61,43 @@ def list( cast_to=DevboxLogsListView, ) + def tail( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """Tail the logs for the given devbox. + + This will return past log entries and + continue from there. This is a streaming api and will continue to stream logs + until the connection is closed. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + f"/v1/devboxes/{id}/logs/tail", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + class AsyncLogsResource(AsyncAPIResource): @cached_property @@ -104,6 +141,43 @@ async def list( cast_to=DevboxLogsListView, ) + async def tail( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """Tail the logs for the given devbox. + + This will return past log entries and + continue from there. This is a streaming api and will continue to stream logs + until the connection is closed. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + f"/v1/devboxes/{id}/logs/tail", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + class LogsResourceWithRawResponse: def __init__(self, logs: LogsResource) -> None: @@ -112,6 +186,9 @@ def __init__(self, logs: LogsResource) -> None: self.list = to_raw_response_wrapper( logs.list, ) + self.tail = to_raw_response_wrapper( + logs.tail, + ) class AsyncLogsResourceWithRawResponse: @@ -121,6 +198,9 @@ def __init__(self, logs: AsyncLogsResource) -> None: self.list = async_to_raw_response_wrapper( logs.list, ) + self.tail = async_to_raw_response_wrapper( + logs.tail, + ) class LogsResourceWithStreamingResponse: @@ -130,6 +210,9 @@ def __init__(self, logs: LogsResource) -> None: self.list = to_streamed_response_wrapper( logs.list, ) + self.tail = to_streamed_response_wrapper( + logs.tail, + ) class AsyncLogsResourceWithStreamingResponse: @@ -139,3 +222,6 @@ def __init__(self, logs: AsyncLogsResource) -> None: self.list = async_to_streamed_response_wrapper( logs.list, ) + self.tail = async_to_streamed_response_wrapper( + logs.tail, + ) diff --git a/src/runloop_api_client/resources/functions/functions.py b/src/runloop_api_client/resources/functions/functions.py index 006a23817..8628eca96 100755 --- a/src/runloop_api_client/resources/functions/functions.py +++ b/src/runloop_api_client/resources/functions/functions.py @@ -164,6 +164,25 @@ def invoke_sync( cast_to=FunctionInvocationExecutionDetailView, ) + def list_openapi( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """Get the OpenAPI Spec for this project.""" + return self._get( + "/v1/functions/openapi", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + class AsyncFunctionsResource(AsyncAPIResource): @cached_property @@ -296,6 +315,25 @@ async def invoke_sync( cast_to=FunctionInvocationExecutionDetailView, ) + async def list_openapi( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """Get the OpenAPI Spec for this project.""" + return await self._get( + "/v1/functions/openapi", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + class FunctionsResourceWithRawResponse: def __init__(self, functions: FunctionsResource) -> None: @@ -310,6 +348,9 @@ def __init__(self, functions: FunctionsResource) -> None: self.invoke_sync = to_raw_response_wrapper( functions.invoke_sync, ) + self.list_openapi = to_raw_response_wrapper( + functions.list_openapi, + ) @cached_property def invocations(self) -> InvocationsResourceWithRawResponse: @@ -329,6 +370,9 @@ def __init__(self, functions: AsyncFunctionsResource) -> None: self.invoke_sync = async_to_raw_response_wrapper( functions.invoke_sync, ) + self.list_openapi = async_to_raw_response_wrapper( + functions.list_openapi, + ) @cached_property def invocations(self) -> AsyncInvocationsResourceWithRawResponse: @@ -348,6 +392,9 @@ def __init__(self, functions: FunctionsResource) -> None: self.invoke_sync = to_streamed_response_wrapper( functions.invoke_sync, ) + self.list_openapi = to_streamed_response_wrapper( + functions.list_openapi, + ) @cached_property def invocations(self) -> InvocationsResourceWithStreamingResponse: @@ -367,6 +414,9 @@ def __init__(self, functions: AsyncFunctionsResource) -> None: self.invoke_sync = async_to_streamed_response_wrapper( functions.invoke_sync, ) + self.list_openapi = async_to_streamed_response_wrapper( + functions.list_openapi, + ) @cached_property def invocations(self) -> AsyncInvocationsResourceWithStreamingResponse: diff --git a/src/runloop_api_client/resources/functions/invocations.py b/src/runloop_api_client/resources/functions/invocations.py index 59491d1e7..5e9c2b046 100755 --- a/src/runloop_api_client/resources/functions/invocations.py +++ b/src/runloop_api_client/resources/functions/invocations.py @@ -19,6 +19,7 @@ ) from ..._base_client import make_request_options from ...types.functions import invocation_list_params +from ...types.functions.invocation_logs_response import InvocationLogsResponse from ...types.functions.function_invocation_list_view import FunctionInvocationListView from ...types.shared.function_invocation_execution_detail_view import FunctionInvocationExecutionDetailView @@ -149,6 +150,39 @@ def kill( cast_to=object, ) + def logs( + self, + invocation_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, + ) -> InvocationLogsResponse: + """ + Get the logs for the given invocation. + + 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 invocation_id: + raise ValueError(f"Expected a non-empty value for `invocation_id` but received {invocation_id!r}") + return self._get( + f"/v1/functions/invocations/{invocation_id}/logs", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvocationLogsResponse, + ) + class AsyncInvocationsResource(AsyncAPIResource): @cached_property @@ -274,6 +308,39 @@ async def kill( cast_to=object, ) + async def logs( + self, + invocation_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, + ) -> InvocationLogsResponse: + """ + Get the logs for the given invocation. + + 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 invocation_id: + raise ValueError(f"Expected a non-empty value for `invocation_id` but received {invocation_id!r}") + return await self._get( + f"/v1/functions/invocations/{invocation_id}/logs", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvocationLogsResponse, + ) + class InvocationsResourceWithRawResponse: def __init__(self, invocations: InvocationsResource) -> None: @@ -288,6 +355,9 @@ def __init__(self, invocations: InvocationsResource) -> None: self.kill = to_raw_response_wrapper( invocations.kill, ) + self.logs = to_raw_response_wrapper( + invocations.logs, + ) class AsyncInvocationsResourceWithRawResponse: @@ -303,6 +373,9 @@ def __init__(self, invocations: AsyncInvocationsResource) -> None: self.kill = async_to_raw_response_wrapper( invocations.kill, ) + self.logs = async_to_raw_response_wrapper( + invocations.logs, + ) class InvocationsResourceWithStreamingResponse: @@ -318,6 +391,9 @@ def __init__(self, invocations: InvocationsResource) -> None: self.kill = to_streamed_response_wrapper( invocations.kill, ) + self.logs = to_streamed_response_wrapper( + invocations.logs, + ) class AsyncInvocationsResourceWithStreamingResponse: @@ -333,3 +409,6 @@ def __init__(self, invocations: AsyncInvocationsResource) -> None: self.kill = async_to_streamed_response_wrapper( invocations.kill, ) + self.logs = async_to_streamed_response_wrapper( + invocations.logs, + ) diff --git a/src/runloop_api_client/types/__init__.py b/src/runloop_api_client/types/__init__.py index 5817fab7d..e1b1ebff5 100755 --- a/src/runloop_api_client/types/__init__.py +++ b/src/runloop_api_client/types/__init__.py @@ -9,26 +9,33 @@ from .devbox_view import DevboxView as DevboxView from .resource_size import ResourceSize as ResourceSize from .blueprint_view import BlueprintView as BlueprintView -from .devbox_list_view import DevboxListView as DevboxListView from .project_list_view import ProjectListView as ProjectListView from .devbox_list_params import DevboxListParams as DevboxListParams from .function_list_view import FunctionListView as FunctionListView from .blueprint_build_log import BlueprintBuildLog as BlueprintBuildLog from .blueprint_list_view import BlueprintListView as BlueprintListView from .devbox_create_params import DevboxCreateParams as DevboxCreateParams +from .devbox_list_response import DevboxListResponse as DevboxListResponse from .blueprint_list_params import BlueprintListParams as BlueprintListParams from .code_mount_parameters import CodeMountParameters as CodeMountParameters +from .deployment_get_params import DeploymentGetParams as DeploymentGetParams from .blueprint_preview_view import BlueprintPreviewView as BlueprintPreviewView from .blueprint_create_params import BlueprintCreateParams as BlueprintCreateParams +from .deployment_get_response import DeploymentGetResponse as DeploymentGetResponse from .blueprint_preview_params import BlueprintPreviewParams as BlueprintPreviewParams +from .deployment_logs_response import DeploymentLogsResponse as DeploymentLogsResponse +from .deployment_tail_response import DeploymentTailResponse as DeploymentTailResponse from .devbox_write_file_params import DevboxWriteFileParams as DevboxWriteFileParams from .devbox_upload_file_params import DevboxUploadFileParams as DevboxUploadFileParams from .blueprint_build_parameters import BlueprintBuildParameters as BlueprintBuildParameters from .devbox_execute_sync_params import DevboxExecuteSyncParams as DevboxExecuteSyncParams from .code_mount_parameters_param import CodeMountParametersParam as CodeMountParametersParam +from .devbox_execute_async_params import DevboxExecuteAsyncParams as DevboxExecuteAsyncParams from .function_invoke_sync_params import FunctionInvokeSyncParams as FunctionInvokeSyncParams -from .devbox_execution_detail_view import DevboxExecutionDetailView as DevboxExecutionDetailView +from .deployment_redeploy_response import DeploymentRedeployResponse as DeploymentRedeployResponse +from .deployment_retrieve_response import DeploymentRetrieveResponse as DeploymentRetrieveResponse from .function_invoke_async_params import FunctionInvokeAsyncParams as FunctionInvokeAsyncParams from .blueprint_build_logs_list_view import BlueprintBuildLogsListView as BlueprintBuildLogsListView +from .devbox_create_ssh_key_response import DevboxCreateSSHKeyResponse as DevboxCreateSSHKeyResponse from .devbox_read_file_contents_params import DevboxReadFileContentsParams as DevboxReadFileContentsParams from .devbox_read_file_contents_response import DevboxReadFileContentsResponse as DevboxReadFileContentsResponse diff --git a/src/runloop_api_client/types/deployment_get_params.py b/src/runloop_api_client/types/deployment_get_params.py new file mode 100755 index 000000000..c4c564b6b --- /dev/null +++ b/src/runloop_api_client/types/deployment_get_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 TypedDict + +__all__ = ["DeploymentGetParams"] + + +class DeploymentGetParams(TypedDict, total=False): + limit: str + """Page Limit""" + + starting_after: str + """Load the next page starting after the given token.""" diff --git a/src/runloop_api_client/types/deployment_get_response.py b/src/runloop_api_client/types/deployment_get_response.py new file mode 100755 index 000000000..e291ac77f --- /dev/null +++ b/src/runloop_api_client/types/deployment_get_response.py @@ -0,0 +1,59 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DeploymentGetResponse", "Deployment"] + + +class Deployment(BaseModel): + id: Optional[str] = None + """ID of the deployment.""" + + deploy_commit_message: Optional[str] = None + """Associated Commit Message""" + + deploy_commit_sha: Optional[str] = None + """Associated Commit Sha""" + + deploy_commit_time_ms: Optional[int] = None + """Associated Commit Time""" + + deploy_end_time_ms: Optional[int] = None + """Time the Deploy completed (Unix timestamp milliseconds).""" + + deploy_start_time_ms: Optional[int] = None + """Time the Deploy was started (Unix timestamp milliseconds).""" + + deployed_functions: Optional[List[str]] = None + """The list of deployed functions.""" + + failure_code: Optional[str] = None + """ + Failure code (generic_failure | git_clone_failure | not_runloop_repo | + secrets_failure | provision_failure | runtime_failure). Only set on + deploy_failed. + """ + + failure_message: Optional[str] = None + """Failure message""" + + project_name: Optional[str] = None + """Project name associated with the deployment.""" + + redeploy_of: Optional[str] = None + """ID of original deployment this is redeployment for.""" + + status: Optional[Literal["scheduled", "skipped", "in_progress", "failed", "deployed"]] = None + """Status of the deploy.""" + + +class DeploymentGetResponse(BaseModel): + deployments: Optional[List[Deployment]] = None + """List of projects matching given query.""" + + has_more: Optional[bool] = None + + total_count: Optional[int] = None diff --git a/src/runloop_api_client/types/deployment_logs_response.py b/src/runloop_api_client/types/deployment_logs_response.py new file mode 100755 index 000000000..ccd2ec3da --- /dev/null +++ b/src/runloop_api_client/types/deployment_logs_response.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel + +__all__ = ["DeploymentLogsResponse", "Log"] + + +class Log(BaseModel): + level: Optional[str] = None + """Log line severity level.""" + + message: Optional[str] = None + """Log line message.""" + + timestamp_ms: Optional[int] = None + """Time of log (Unix timestamp milliseconds).""" + + +class DeploymentLogsResponse(BaseModel): + deployment_id: Optional[str] = None + """ID of the given deployment.""" + + logs: Optional[List[Log]] = None + """List of logs for the given deployment.""" diff --git a/src/runloop_api_client/types/deployment_redeploy_response.py b/src/runloop_api_client/types/deployment_redeploy_response.py new file mode 100755 index 000000000..679938a26 --- /dev/null +++ b/src/runloop_api_client/types/deployment_redeploy_response.py @@ -0,0 +1,50 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DeploymentRedeployResponse"] + + +class DeploymentRedeployResponse(BaseModel): + id: Optional[str] = None + """ID of the deployment.""" + + deploy_commit_message: Optional[str] = None + """Associated Commit Message""" + + deploy_commit_sha: Optional[str] = None + """Associated Commit Sha""" + + deploy_commit_time_ms: Optional[int] = None + """Associated Commit Time""" + + deploy_end_time_ms: Optional[int] = None + """Time the Deploy completed (Unix timestamp milliseconds).""" + + deploy_start_time_ms: Optional[int] = None + """Time the Deploy was started (Unix timestamp milliseconds).""" + + deployed_functions: Optional[List[str]] = None + """The list of deployed functions.""" + + failure_code: Optional[str] = None + """ + Failure code (generic_failure | git_clone_failure | not_runloop_repo | + secrets_failure | provision_failure | runtime_failure). Only set on + deploy_failed. + """ + + failure_message: Optional[str] = None + """Failure message""" + + project_name: Optional[str] = None + """Project name associated with the deployment.""" + + redeploy_of: Optional[str] = None + """ID of original deployment this is redeployment for.""" + + status: Optional[Literal["scheduled", "skipped", "in_progress", "failed", "deployed"]] = None + """Status of the deploy.""" diff --git a/src/runloop_api_client/types/deployment_retrieve_response.py b/src/runloop_api_client/types/deployment_retrieve_response.py new file mode 100755 index 000000000..a2fa1bf41 --- /dev/null +++ b/src/runloop_api_client/types/deployment_retrieve_response.py @@ -0,0 +1,50 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DeploymentRetrieveResponse"] + + +class DeploymentRetrieveResponse(BaseModel): + id: Optional[str] = None + """ID of the deployment.""" + + deploy_commit_message: Optional[str] = None + """Associated Commit Message""" + + deploy_commit_sha: Optional[str] = None + """Associated Commit Sha""" + + deploy_commit_time_ms: Optional[int] = None + """Associated Commit Time""" + + deploy_end_time_ms: Optional[int] = None + """Time the Deploy completed (Unix timestamp milliseconds).""" + + deploy_start_time_ms: Optional[int] = None + """Time the Deploy was started (Unix timestamp milliseconds).""" + + deployed_functions: Optional[List[str]] = None + """The list of deployed functions.""" + + failure_code: Optional[str] = None + """ + Failure code (generic_failure | git_clone_failure | not_runloop_repo | + secrets_failure | provision_failure | runtime_failure). Only set on + deploy_failed. + """ + + failure_message: Optional[str] = None + """Failure message""" + + project_name: Optional[str] = None + """Project name associated with the deployment.""" + + redeploy_of: Optional[str] = None + """ID of original deployment this is redeployment for.""" + + status: Optional[Literal["scheduled", "skipped", "in_progress", "failed", "deployed"]] = None + """Status of the deploy.""" diff --git a/src/runloop_api_client/types/deployment_tail_response.py b/src/runloop_api_client/types/deployment_tail_response.py new file mode 100755 index 000000000..afd26fc86 --- /dev/null +++ b/src/runloop_api_client/types/deployment_tail_response.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel + +__all__ = ["DeploymentTailResponse", "Log"] + + +class Log(BaseModel): + level: Optional[str] = None + """Log line severity level.""" + + message: Optional[str] = None + """Log line message.""" + + timestamp_ms: Optional[int] = None + """Time of log (Unix timestamp milliseconds).""" + + +class DeploymentTailResponse(BaseModel): + deployment_id: Optional[str] = None + """ID of the given deployment.""" + + logs: Optional[List[Log]] = None + """List of logs for the given deployment.""" diff --git a/src/runloop_api_client/types/devbox_create_ssh_key_response.py b/src/runloop_api_client/types/devbox_create_ssh_key_response.py new file mode 100755 index 000000000..3f8c7c366 --- /dev/null +++ b/src/runloop_api_client/types/devbox_create_ssh_key_response.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel + +__all__ = ["DevboxCreateSSHKeyResponse"] + + +class DevboxCreateSSHKeyResponse(BaseModel): + id: Optional[str] = None + """The id of the Devbox.""" + + ssh_private_key: Optional[str] = None + """The ssh private key, in PEM format.""" + + url: Optional[str] = None + """The url of the Devbox.""" diff --git a/src/runloop_api_client/types/devbox_execute_async_params.py b/src/runloop_api_client/types/devbox_execute_async_params.py new file mode 100755 index 000000000..9f5a7a8f4 --- /dev/null +++ b/src/runloop_api_client/types/devbox_execute_async_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 TypedDict + +__all__ = ["DevboxExecuteAsyncParams"] + + +class DevboxExecuteAsyncParams(TypedDict, total=False): + command: str + """The command to execute on the Devbox.""" diff --git a/src/runloop_api_client/types/devbox_list_response.py b/src/runloop_api_client/types/devbox_list_response.py new file mode 100755 index 000000000..d56c67f9f --- /dev/null +++ b/src/runloop_api_client/types/devbox_list_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel +from .devbox_view import DevboxView + +__all__ = ["DevboxListResponse"] + + +class DevboxListResponse(BaseModel): + devboxes: Optional[List[DevboxView]] = None + """List of devboxes matching filter.""" + + has_more: Optional[bool] = None + + total_count: Optional[int] = None diff --git a/src/runloop_api_client/types/devbox_view.py b/src/runloop_api_client/types/devbox_view.py index 71eb25578..e2433cc10 100755 --- a/src/runloop_api_client/types/devbox_view.py +++ b/src/runloop_api_client/types/devbox_view.py @@ -21,6 +21,9 @@ class DevboxView(BaseModel): end_time_ms: Optional[int] = None """The time the Devbox finished execution (Unix timestamp milliseconds).""" + failure_reason: Optional[Literal["out_of_memory", "out_of_disk", "execution_failed"]] = None + """The failure reason if the Devbox failed, if any.""" + initiator_id: Optional[str] = None """The initiator ID of the devbox.""" diff --git a/src/runloop_api_client/types/devboxes/__init__.py b/src/runloop_api_client/types/devboxes/__init__.py index 7baebfdd7..90ed90bb5 100755 --- a/src/runloop_api_client/types/devboxes/__init__.py +++ b/src/runloop_api_client/types/devboxes/__init__.py @@ -3,3 +3,8 @@ from __future__ import annotations from .devbox_logs_list_view import DevboxLogsListView as DevboxLogsListView +from .execution_retrieve_params import ExecutionRetrieveParams as ExecutionRetrieveParams +from .devbox_execution_detail_view import DevboxExecutionDetailView as DevboxExecutionDetailView +from .execution_execute_sync_params import ExecutionExecuteSyncParams as ExecutionExecuteSyncParams +from .execution_execute_async_params import ExecutionExecuteAsyncParams as ExecutionExecuteAsyncParams +from .devbox_async_execution_detail_view import DevboxAsyncExecutionDetailView as DevboxAsyncExecutionDetailView diff --git a/src/runloop_api_client/types/devboxes/devbox_async_execution_detail_view.py b/src/runloop_api_client/types/devboxes/devbox_async_execution_detail_view.py new file mode 100755 index 000000000..ea60ca7f0 --- /dev/null +++ b/src/runloop_api_client/types/devboxes/devbox_async_execution_detail_view.py @@ -0,0 +1,37 @@ +# 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__ = ["DevboxAsyncExecutionDetailView"] + + +class DevboxAsyncExecutionDetailView(BaseModel): + devbox_id: Optional[str] = None + """Devbox id where command was executed.""" + + execution_id: Optional[str] = None + """Ephemeral id of the execution in progress.""" + + exit_status: Optional[int] = None + """Exit code of command execution. + + This field will remain unset until the execution has completed. + """ + + status: Optional[Literal["running", "success", "failure", "canceled"]] = None + """Current status of the execution.""" + + 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. + """ diff --git a/src/runloop_api_client/types/devboxes/devbox_execution_detail_view.py b/src/runloop_api_client/types/devboxes/devbox_execution_detail_view.py new file mode 100755 index 000000000..eadd60b1d --- /dev/null +++ b/src/runloop_api_client/types/devboxes/devbox_execution_detail_view.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..._models import BaseModel + +__all__ = ["DevboxExecutionDetailView"] + + +class DevboxExecutionDetailView(BaseModel): + devbox_id: Optional[str] = None + """Devbox id where command was executed.""" + + exit_status: Optional[int] = None + """Exit status of command execution.""" + + stderr: Optional[str] = None + """Standard error generated by command.""" + + stdout: Optional[str] = None + """Standard out generated by command.""" diff --git a/src/runloop_api_client/types/devboxes/execution_execute_async_params.py b/src/runloop_api_client/types/devboxes/execution_execute_async_params.py new file mode 100755 index 000000000..7878309c5 --- /dev/null +++ b/src/runloop_api_client/types/devboxes/execution_execute_async_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 TypedDict + +__all__ = ["ExecutionExecuteAsyncParams"] + + +class ExecutionExecuteAsyncParams(TypedDict, total=False): + command: str + """The command to execute on the Devbox.""" diff --git a/src/runloop_api_client/types/devboxes/execution_execute_sync_params.py b/src/runloop_api_client/types/devboxes/execution_execute_sync_params.py new file mode 100755 index 000000000..392794ac9 --- /dev/null +++ b/src/runloop_api_client/types/devboxes/execution_execute_sync_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 TypedDict + +__all__ = ["ExecutionExecuteSyncParams"] + + +class ExecutionExecuteSyncParams(TypedDict, total=False): + command: str + """The command to execute on the Devbox.""" diff --git a/src/runloop_api_client/types/devboxes/execution_retrieve_params.py b/src/runloop_api_client/types/devboxes/execution_retrieve_params.py new file mode 100755 index 000000000..3cafe88fe --- /dev/null +++ b/src/runloop_api_client/types/devboxes/execution_retrieve_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__ = ["ExecutionRetrieveParams"] + + +class ExecutionRetrieveParams(TypedDict, total=False): + id: Required[str] + + command: str + """The command to execute on the Devbox.""" diff --git a/src/runloop_api_client/types/functions/__init__.py b/src/runloop_api_client/types/functions/__init__.py index 65762ab89..da953f2d5 100755 --- a/src/runloop_api_client/types/functions/__init__.py +++ b/src/runloop_api_client/types/functions/__init__.py @@ -3,4 +3,5 @@ from __future__ import annotations from .invocation_list_params import InvocationListParams as InvocationListParams +from .invocation_logs_response import InvocationLogsResponse as InvocationLogsResponse from .function_invocation_list_view import FunctionInvocationListView as FunctionInvocationListView diff --git a/src/runloop_api_client/types/functions/invocation_logs_response.py b/src/runloop_api_client/types/functions/invocation_logs_response.py new file mode 100755 index 000000000..240b32c4a --- /dev/null +++ b/src/runloop_api_client/types/functions/invocation_logs_response.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +__all__ = ["InvocationLogsResponse", "Log"] + + +class Log(BaseModel): + level: Optional[str] = None + """Log line severity level.""" + + message: Optional[str] = None + """Log line message.""" + + timestamp_ms: Optional[int] = None + """Time of log (Unix timestamp milliseconds).""" + + +class InvocationLogsResponse(BaseModel): + invocation_id: Optional[str] = None + """ID of the invocation.""" + + logs: Optional[List[Log]] = None + """List of logs for the given invocation.""" diff --git a/tests/api_resources/devboxes/test_executions.py b/tests/api_resources/devboxes/test_executions.py new file mode 100755 index 000000000..665142572 --- /dev/null +++ b/tests/api_resources/devboxes/test_executions.py @@ -0,0 +1,612 @@ +# 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 tests.utils import assert_matches_type +from runloop_api_client import Runloop, AsyncRunloop +from runloop_api_client.types.devboxes import ( + DevboxLogsListView, + DevboxExecutionDetailView, + DevboxAsyncExecutionDetailView, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestExecutions: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: Runloop) -> None: + execution = client.devboxes.executions.retrieve( + exe_id="exeId", + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_method_retrieve_with_all_params(self, client: Runloop) -> None: + execution = client.devboxes.executions.retrieve( + exe_id="exeId", + id="id", + command="command", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Runloop) -> None: + response = client.devboxes.executions.with_raw_response.retrieve( + exe_id="exeId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Runloop) -> None: + with client.devboxes.executions.with_streaming_response.retrieve( + exe_id="exeId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.executions.with_raw_response.retrieve( + exe_id="exeId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `exe_id` but received ''"): + client.devboxes.executions.with_raw_response.retrieve( + exe_id="", + id="id", + ) + + @parametrize + def test_method_execute_async(self, client: Runloop) -> None: + execution = client.devboxes.executions.execute_async( + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_method_execute_async_with_all_params(self, client: Runloop) -> None: + execution = client.devboxes.executions.execute_async( + id="id", + command="command", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_raw_response_execute_async(self, client: Runloop) -> None: + response = client.devboxes.executions.with_raw_response.execute_async( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_streaming_response_execute_async(self, client: Runloop) -> None: + with client.devboxes.executions.with_streaming_response.execute_async( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_execute_async(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.executions.with_raw_response.execute_async( + id="", + ) + + @parametrize + def test_method_execute_sync(self, client: Runloop) -> None: + execution = client.devboxes.executions.execute_sync( + id="id", + ) + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_method_execute_sync_with_all_params(self, client: Runloop) -> None: + execution = client.devboxes.executions.execute_sync( + id="id", + command="command", + ) + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_raw_response_execute_sync(self, client: Runloop) -> None: + response = client.devboxes.executions.with_raw_response.execute_sync( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = response.parse() + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_streaming_response_execute_sync(self, client: Runloop) -> None: + with client.devboxes.executions.with_streaming_response.execute_sync( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = response.parse() + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_execute_sync(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.executions.with_raw_response.execute_sync( + id="", + ) + + @parametrize + def test_method_kill(self, client: Runloop) -> None: + execution = client.devboxes.executions.kill( + exe_id="exeId", + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_raw_response_kill(self, client: Runloop) -> None: + response = client.devboxes.executions.with_raw_response.kill( + exe_id="exeId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + def test_streaming_response_kill(self, client: Runloop) -> None: + with client.devboxes.executions.with_streaming_response.kill( + exe_id="exeId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_kill(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.executions.with_raw_response.kill( + exe_id="exeId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `exe_id` but received ''"): + client.devboxes.executions.with_raw_response.kill( + exe_id="", + id="id", + ) + + @parametrize + def test_method_logs(self, client: Runloop) -> None: + execution = client.devboxes.executions.logs( + execution_id="execution_id", + id="id", + ) + assert_matches_type(DevboxLogsListView, execution, path=["response"]) + + @parametrize + def test_raw_response_logs(self, client: Runloop) -> None: + response = client.devboxes.executions.with_raw_response.logs( + execution_id="execution_id", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = response.parse() + assert_matches_type(DevboxLogsListView, execution, path=["response"]) + + @parametrize + def test_streaming_response_logs(self, client: Runloop) -> None: + with client.devboxes.executions.with_streaming_response.logs( + execution_id="execution_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = response.parse() + assert_matches_type(DevboxLogsListView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_logs(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.executions.with_raw_response.logs( + execution_id="execution_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): + client.devboxes.executions.with_raw_response.logs( + execution_id="", + id="id", + ) + + @parametrize + def test_method_tail(self, client: Runloop) -> None: + execution = client.devboxes.executions.tail( + execution_id="execution_id", + id="id", + ) + assert execution is None + + @parametrize + def test_raw_response_tail(self, client: Runloop) -> None: + response = client.devboxes.executions.with_raw_response.tail( + execution_id="execution_id", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = response.parse() + assert execution is None + + @parametrize + def test_streaming_response_tail(self, client: Runloop) -> None: + with client.devboxes.executions.with_streaming_response.tail( + execution_id="execution_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = response.parse() + assert execution is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_tail(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.executions.with_raw_response.tail( + execution_id="execution_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): + client.devboxes.executions.with_raw_response.tail( + execution_id="", + id="id", + ) + + +class TestAsyncExecutions: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.retrieve( + exe_id="exeId", + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.retrieve( + exe_id="exeId", + id="id", + command="command", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.executions.with_raw_response.retrieve( + exe_id="exeId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.executions.with_streaming_response.retrieve( + exe_id="exeId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.executions.with_raw_response.retrieve( + exe_id="exeId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `exe_id` but received ''"): + await async_client.devboxes.executions.with_raw_response.retrieve( + exe_id="", + id="id", + ) + + @parametrize + async def test_method_execute_async(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.execute_async( + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_method_execute_async_with_all_params(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.execute_async( + id="id", + command="command", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_raw_response_execute_async(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.executions.with_raw_response.execute_async( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_streaming_response_execute_async(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.executions.with_streaming_response.execute_async( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_execute_async(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.executions.with_raw_response.execute_async( + id="", + ) + + @parametrize + async def test_method_execute_sync(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.execute_sync( + id="id", + ) + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_method_execute_sync_with_all_params(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.execute_sync( + id="id", + command="command", + ) + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_raw_response_execute_sync(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.executions.with_raw_response.execute_sync( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = await response.parse() + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_streaming_response_execute_sync(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.executions.with_streaming_response.execute_sync( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = await response.parse() + assert_matches_type(DevboxExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_execute_sync(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.executions.with_raw_response.execute_sync( + id="", + ) + + @parametrize + async def test_method_kill(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.kill( + exe_id="exeId", + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_raw_response_kill(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.executions.with_raw_response.kill( + exe_id="exeId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + @parametrize + async def test_streaming_response_kill(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.executions.with_streaming_response.kill( + exe_id="exeId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_kill(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.executions.with_raw_response.kill( + exe_id="exeId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `exe_id` but received ''"): + await async_client.devboxes.executions.with_raw_response.kill( + exe_id="", + id="id", + ) + + @parametrize + async def test_method_logs(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.logs( + execution_id="execution_id", + id="id", + ) + assert_matches_type(DevboxLogsListView, execution, path=["response"]) + + @parametrize + async def test_raw_response_logs(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.executions.with_raw_response.logs( + execution_id="execution_id", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = await response.parse() + assert_matches_type(DevboxLogsListView, execution, path=["response"]) + + @parametrize + async def test_streaming_response_logs(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.executions.with_streaming_response.logs( + execution_id="execution_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = await response.parse() + assert_matches_type(DevboxLogsListView, execution, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_logs(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.executions.with_raw_response.logs( + execution_id="execution_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): + await async_client.devboxes.executions.with_raw_response.logs( + execution_id="", + id="id", + ) + + @parametrize + async def test_method_tail(self, async_client: AsyncRunloop) -> None: + execution = await async_client.devboxes.executions.tail( + execution_id="execution_id", + id="id", + ) + assert execution is None + + @parametrize + async def test_raw_response_tail(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.executions.with_raw_response.tail( + execution_id="execution_id", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + execution = await response.parse() + assert execution is None + + @parametrize + async def test_streaming_response_tail(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.executions.with_streaming_response.tail( + execution_id="execution_id", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + execution = await response.parse() + assert execution is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_tail(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.executions.with_raw_response.tail( + execution_id="execution_id", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): + await async_client.devboxes.executions.with_raw_response.tail( + execution_id="", + id="id", + ) diff --git a/tests/api_resources/devboxes/test_logs.py b/tests/api_resources/devboxes/test_logs.py index 85ea9be84..c0d8bdc24 100755 --- a/tests/api_resources/devboxes/test_logs.py +++ b/tests/api_resources/devboxes/test_logs.py @@ -55,6 +55,44 @@ def test_path_params_list(self, client: Runloop) -> None: "", ) + @parametrize + def test_method_tail(self, client: Runloop) -> None: + log = client.devboxes.logs.tail( + "id", + ) + assert log is None + + @parametrize + def test_raw_response_tail(self, client: Runloop) -> None: + response = client.devboxes.logs.with_raw_response.tail( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + log = response.parse() + assert log is None + + @parametrize + def test_streaming_response_tail(self, client: Runloop) -> None: + with client.devboxes.logs.with_streaming_response.tail( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + log = response.parse() + assert log is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_tail(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.logs.with_raw_response.tail( + "", + ) + class TestAsyncLogs: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @@ -96,3 +134,41 @@ async def test_path_params_list(self, async_client: AsyncRunloop) -> None: await async_client.devboxes.logs.with_raw_response.list( "", ) + + @parametrize + async def test_method_tail(self, async_client: AsyncRunloop) -> None: + log = await async_client.devboxes.logs.tail( + "id", + ) + assert log is None + + @parametrize + async def test_raw_response_tail(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.logs.with_raw_response.tail( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + log = await response.parse() + assert log is None + + @parametrize + async def test_streaming_response_tail(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.logs.with_streaming_response.tail( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + log = await response.parse() + assert log is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_tail(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.logs.with_raw_response.tail( + "", + ) diff --git a/tests/api_resources/functions/test_invocations.py b/tests/api_resources/functions/test_invocations.py index 726e5843c..38953c074 100755 --- a/tests/api_resources/functions/test_invocations.py +++ b/tests/api_resources/functions/test_invocations.py @@ -10,7 +10,10 @@ from tests.utils import assert_matches_type from runloop_api_client import Runloop, AsyncRunloop from runloop_api_client.types.shared import FunctionInvocationExecutionDetailView -from runloop_api_client.types.functions import FunctionInvocationListView +from runloop_api_client.types.functions import ( + InvocationLogsResponse, + FunctionInvocationListView, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -127,6 +130,44 @@ def test_path_params_kill(self, client: Runloop) -> None: "", ) + @parametrize + def test_method_logs(self, client: Runloop) -> None: + invocation = client.functions.invocations.logs( + "invocation_id", + ) + assert_matches_type(InvocationLogsResponse, invocation, path=["response"]) + + @parametrize + def test_raw_response_logs(self, client: Runloop) -> None: + response = client.functions.invocations.with_raw_response.logs( + "invocation_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invocation = response.parse() + assert_matches_type(InvocationLogsResponse, invocation, path=["response"]) + + @parametrize + def test_streaming_response_logs(self, client: Runloop) -> None: + with client.functions.invocations.with_streaming_response.logs( + "invocation_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invocation = response.parse() + assert_matches_type(InvocationLogsResponse, invocation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_logs(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `invocation_id` but received ''"): + client.functions.invocations.with_raw_response.logs( + "", + ) + class TestAsyncInvocations: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @@ -239,3 +280,41 @@ async def test_path_params_kill(self, async_client: AsyncRunloop) -> None: await async_client.functions.invocations.with_raw_response.kill( "", ) + + @parametrize + async def test_method_logs(self, async_client: AsyncRunloop) -> None: + invocation = await async_client.functions.invocations.logs( + "invocation_id", + ) + assert_matches_type(InvocationLogsResponse, invocation, path=["response"]) + + @parametrize + async def test_raw_response_logs(self, async_client: AsyncRunloop) -> None: + response = await async_client.functions.invocations.with_raw_response.logs( + "invocation_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invocation = await response.parse() + assert_matches_type(InvocationLogsResponse, invocation, path=["response"]) + + @parametrize + async def test_streaming_response_logs(self, async_client: AsyncRunloop) -> None: + async with async_client.functions.invocations.with_streaming_response.logs( + "invocation_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invocation = await response.parse() + assert_matches_type(InvocationLogsResponse, invocation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_logs(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `invocation_id` but received ''"): + await async_client.functions.invocations.with_raw_response.logs( + "", + ) diff --git a/tests/api_resources/test_deployments.py b/tests/api_resources/test_deployments.py new file mode 100755 index 000000000..5a83bef98 --- /dev/null +++ b/tests/api_resources/test_deployments.py @@ -0,0 +1,398 @@ +# 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 tests.utils import assert_matches_type +from runloop_api_client import Runloop, AsyncRunloop +from runloop_api_client.types import ( + DeploymentGetResponse, + DeploymentLogsResponse, + DeploymentTailResponse, + DeploymentRedeployResponse, + DeploymentRetrieveResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDeployments: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: Runloop) -> None: + deployment = client.deployments.retrieve( + "deployment_id", + ) + assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Runloop) -> None: + response = client.deployments.with_raw_response.retrieve( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = response.parse() + assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Runloop) -> None: + with client.deployments.with_streaming_response.retrieve( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = response.parse() + assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + client.deployments.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_get(self, client: Runloop) -> None: + deployment = client.deployments.get() + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + @parametrize + def test_method_get_with_all_params(self, client: Runloop) -> None: + deployment = client.deployments.get( + limit="limit", + starting_after="starting_after", + ) + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Runloop) -> None: + response = client.deployments.with_raw_response.get() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = response.parse() + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Runloop) -> None: + with client.deployments.with_streaming_response.get() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = response.parse() + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_logs(self, client: Runloop) -> None: + deployment = client.deployments.logs( + "deployment_id", + ) + assert_matches_type(DeploymentLogsResponse, deployment, path=["response"]) + + @parametrize + def test_raw_response_logs(self, client: Runloop) -> None: + response = client.deployments.with_raw_response.logs( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = response.parse() + assert_matches_type(DeploymentLogsResponse, deployment, path=["response"]) + + @parametrize + def test_streaming_response_logs(self, client: Runloop) -> None: + with client.deployments.with_streaming_response.logs( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = response.parse() + assert_matches_type(DeploymentLogsResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_logs(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + client.deployments.with_raw_response.logs( + "", + ) + + @parametrize + def test_method_redeploy(self, client: Runloop) -> None: + deployment = client.deployments.redeploy( + "deployment_id", + ) + assert_matches_type(DeploymentRedeployResponse, deployment, path=["response"]) + + @parametrize + def test_raw_response_redeploy(self, client: Runloop) -> None: + response = client.deployments.with_raw_response.redeploy( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = response.parse() + assert_matches_type(DeploymentRedeployResponse, deployment, path=["response"]) + + @parametrize + def test_streaming_response_redeploy(self, client: Runloop) -> None: + with client.deployments.with_streaming_response.redeploy( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = response.parse() + assert_matches_type(DeploymentRedeployResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_redeploy(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + client.deployments.with_raw_response.redeploy( + "", + ) + + @parametrize + def test_method_tail(self, client: Runloop) -> None: + deployment = client.deployments.tail( + "deployment_id", + ) + assert_matches_type(DeploymentTailResponse, deployment, path=["response"]) + + @parametrize + def test_raw_response_tail(self, client: Runloop) -> None: + response = client.deployments.with_raw_response.tail( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = response.parse() + assert_matches_type(DeploymentTailResponse, deployment, path=["response"]) + + @parametrize + def test_streaming_response_tail(self, client: Runloop) -> None: + with client.deployments.with_streaming_response.tail( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = response.parse() + assert_matches_type(DeploymentTailResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_tail(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + client.deployments.with_raw_response.tail( + "", + ) + + +class TestAsyncDeployments: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncRunloop) -> None: + deployment = await async_client.deployments.retrieve( + "deployment_id", + ) + assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncRunloop) -> None: + response = await async_client.deployments.with_raw_response.retrieve( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = await response.parse() + assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncRunloop) -> None: + async with async_client.deployments.with_streaming_response.retrieve( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = await response.parse() + assert_matches_type(DeploymentRetrieveResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + await async_client.deployments.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_get(self, async_client: AsyncRunloop) -> None: + deployment = await async_client.deployments.get() + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + @parametrize + async def test_method_get_with_all_params(self, async_client: AsyncRunloop) -> None: + deployment = await async_client.deployments.get( + limit="limit", + starting_after="starting_after", + ) + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncRunloop) -> None: + response = await async_client.deployments.with_raw_response.get() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = await response.parse() + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncRunloop) -> None: + async with async_client.deployments.with_streaming_response.get() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = await response.parse() + assert_matches_type(DeploymentGetResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_logs(self, async_client: AsyncRunloop) -> None: + deployment = await async_client.deployments.logs( + "deployment_id", + ) + assert_matches_type(DeploymentLogsResponse, deployment, path=["response"]) + + @parametrize + async def test_raw_response_logs(self, async_client: AsyncRunloop) -> None: + response = await async_client.deployments.with_raw_response.logs( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = await response.parse() + assert_matches_type(DeploymentLogsResponse, deployment, path=["response"]) + + @parametrize + async def test_streaming_response_logs(self, async_client: AsyncRunloop) -> None: + async with async_client.deployments.with_streaming_response.logs( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = await response.parse() + assert_matches_type(DeploymentLogsResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_logs(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + await async_client.deployments.with_raw_response.logs( + "", + ) + + @parametrize + async def test_method_redeploy(self, async_client: AsyncRunloop) -> None: + deployment = await async_client.deployments.redeploy( + "deployment_id", + ) + assert_matches_type(DeploymentRedeployResponse, deployment, path=["response"]) + + @parametrize + async def test_raw_response_redeploy(self, async_client: AsyncRunloop) -> None: + response = await async_client.deployments.with_raw_response.redeploy( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = await response.parse() + assert_matches_type(DeploymentRedeployResponse, deployment, path=["response"]) + + @parametrize + async def test_streaming_response_redeploy(self, async_client: AsyncRunloop) -> None: + async with async_client.deployments.with_streaming_response.redeploy( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = await response.parse() + assert_matches_type(DeploymentRedeployResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_redeploy(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + await async_client.deployments.with_raw_response.redeploy( + "", + ) + + @parametrize + async def test_method_tail(self, async_client: AsyncRunloop) -> None: + deployment = await async_client.deployments.tail( + "deployment_id", + ) + assert_matches_type(DeploymentTailResponse, deployment, path=["response"]) + + @parametrize + async def test_raw_response_tail(self, async_client: AsyncRunloop) -> None: + response = await async_client.deployments.with_raw_response.tail( + "deployment_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deployment = await response.parse() + assert_matches_type(DeploymentTailResponse, deployment, path=["response"]) + + @parametrize + async def test_streaming_response_tail(self, async_client: AsyncRunloop) -> None: + async with async_client.deployments.with_streaming_response.tail( + "deployment_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deployment = await response.parse() + assert_matches_type(DeploymentTailResponse, deployment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_tail(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `deployment_id` but received ''"): + await async_client.deployments.with_raw_response.tail( + "", + ) diff --git a/tests/api_resources/test_devboxes.py b/tests/api_resources/test_devboxes.py index 1024eb26f..9b82bde44 100755 --- a/tests/api_resources/test_devboxes.py +++ b/tests/api_resources/test_devboxes.py @@ -11,9 +11,10 @@ from runloop_api_client import Runloop, AsyncRunloop from runloop_api_client.types import ( DevboxView, - DevboxListView, - DevboxExecutionDetailView, + DevboxListResponse, + DevboxCreateSSHKeyResponse, ) +from runloop_api_client.types.devboxes import DevboxExecutionDetailView, DevboxAsyncExecutionDetailView base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -106,7 +107,7 @@ def test_path_params_retrieve(self, client: Runloop) -> None: @parametrize def test_method_list(self, client: Runloop) -> None: devbox = client.devboxes.list() - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Runloop) -> None: @@ -115,7 +116,7 @@ def test_method_list_with_all_params(self, client: Runloop) -> None: starting_after="starting_after", status="status", ) - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) @parametrize def test_raw_response_list(self, client: Runloop) -> None: @@ -124,7 +125,7 @@ def test_raw_response_list(self, client: Runloop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" devbox = response.parse() - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) @parametrize def test_streaming_response_list(self, client: Runloop) -> None: @@ -133,10 +134,94 @@ def test_streaming_response_list(self, client: Runloop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" devbox = response.parse() - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) assert cast(Any, response.is_closed) is True + @parametrize + def test_method_create_ssh_key(self, client: Runloop) -> None: + devbox = client.devboxes.create_ssh_key( + "id", + ) + assert_matches_type(DevboxCreateSSHKeyResponse, devbox, path=["response"]) + + @parametrize + def test_raw_response_create_ssh_key(self, client: Runloop) -> None: + response = client.devboxes.with_raw_response.create_ssh_key( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + devbox = response.parse() + assert_matches_type(DevboxCreateSSHKeyResponse, devbox, path=["response"]) + + @parametrize + def test_streaming_response_create_ssh_key(self, client: Runloop) -> None: + with client.devboxes.with_streaming_response.create_ssh_key( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + devbox = response.parse() + assert_matches_type(DevboxCreateSSHKeyResponse, devbox, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_create_ssh_key(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.with_raw_response.create_ssh_key( + "", + ) + + @parametrize + def test_method_execute_async(self, client: Runloop) -> None: + devbox = client.devboxes.execute_async( + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + @parametrize + def test_method_execute_async_with_all_params(self, client: Runloop) -> None: + devbox = client.devboxes.execute_async( + id="id", + command="command", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + @parametrize + def test_raw_response_execute_async(self, client: Runloop) -> None: + response = client.devboxes.with_raw_response.execute_async( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + devbox = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + @parametrize + def test_streaming_response_execute_async(self, client: Runloop) -> None: + with client.devboxes.with_streaming_response.execute_async( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + devbox = response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_execute_async(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.devboxes.with_raw_response.execute_async( + id="", + ) + @parametrize def test_method_execute_sync(self, client: Runloop) -> None: devbox = client.devboxes.execute_sync( @@ -450,7 +535,7 @@ async def test_path_params_retrieve(self, async_client: AsyncRunloop) -> None: @parametrize async def test_method_list(self, async_client: AsyncRunloop) -> None: devbox = await async_client.devboxes.list() - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> None: @@ -459,7 +544,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> starting_after="starting_after", status="status", ) - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncRunloop) -> None: @@ -468,7 +553,7 @@ async def test_raw_response_list(self, async_client: AsyncRunloop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" devbox = await response.parse() - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncRunloop) -> None: @@ -477,10 +562,94 @@ async def test_streaming_response_list(self, async_client: AsyncRunloop) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" devbox = await response.parse() - assert_matches_type(DevboxListView, devbox, path=["response"]) + assert_matches_type(DevboxListResponse, devbox, path=["response"]) assert cast(Any, response.is_closed) is True + @parametrize + async def test_method_create_ssh_key(self, async_client: AsyncRunloop) -> None: + devbox = await async_client.devboxes.create_ssh_key( + "id", + ) + assert_matches_type(DevboxCreateSSHKeyResponse, devbox, path=["response"]) + + @parametrize + async def test_raw_response_create_ssh_key(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.with_raw_response.create_ssh_key( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + devbox = await response.parse() + assert_matches_type(DevboxCreateSSHKeyResponse, devbox, path=["response"]) + + @parametrize + async def test_streaming_response_create_ssh_key(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.with_streaming_response.create_ssh_key( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + devbox = await response.parse() + assert_matches_type(DevboxCreateSSHKeyResponse, devbox, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_create_ssh_key(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.with_raw_response.create_ssh_key( + "", + ) + + @parametrize + async def test_method_execute_async(self, async_client: AsyncRunloop) -> None: + devbox = await async_client.devboxes.execute_async( + id="id", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + @parametrize + async def test_method_execute_async_with_all_params(self, async_client: AsyncRunloop) -> None: + devbox = await async_client.devboxes.execute_async( + id="id", + command="command", + ) + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + @parametrize + async def test_raw_response_execute_async(self, async_client: AsyncRunloop) -> None: + response = await async_client.devboxes.with_raw_response.execute_async( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + devbox = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + @parametrize + async def test_streaming_response_execute_async(self, async_client: AsyncRunloop) -> None: + async with async_client.devboxes.with_streaming_response.execute_async( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + devbox = await response.parse() + assert_matches_type(DevboxAsyncExecutionDetailView, devbox, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_execute_async(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.devboxes.with_raw_response.execute_async( + id="", + ) + @parametrize async def test_method_execute_sync(self, async_client: AsyncRunloop) -> None: devbox = await async_client.devboxes.execute_sync( diff --git a/tests/api_resources/test_functions.py b/tests/api_resources/test_functions.py index e168b5de1..fa60f9801 100755 --- a/tests/api_resources/test_functions.py +++ b/tests/api_resources/test_functions.py @@ -169,6 +169,31 @@ def test_path_params_invoke_sync(self, client: Runloop) -> None: request={}, ) + @parametrize + def test_method_list_openapi(self, client: Runloop) -> None: + function = client.functions.list_openapi() + assert_matches_type(object, function, path=["response"]) + + @parametrize + def test_raw_response_list_openapi(self, client: Runloop) -> None: + response = client.functions.with_raw_response.list_openapi() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + function = response.parse() + assert_matches_type(object, function, path=["response"]) + + @parametrize + def test_streaming_response_list_openapi(self, client: Runloop) -> None: + with client.functions.with_streaming_response.list_openapi() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + function = response.parse() + assert_matches_type(object, function, path=["response"]) + + assert cast(Any, response.is_closed) is True + class TestAsyncFunctions: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @@ -323,3 +348,28 @@ async def test_path_params_invoke_sync(self, async_client: AsyncRunloop) -> None project_name="project_name", request={}, ) + + @parametrize + async def test_method_list_openapi(self, async_client: AsyncRunloop) -> None: + function = await async_client.functions.list_openapi() + assert_matches_type(object, function, path=["response"]) + + @parametrize + async def test_raw_response_list_openapi(self, async_client: AsyncRunloop) -> None: + response = await async_client.functions.with_raw_response.list_openapi() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + function = await response.parse() + assert_matches_type(object, function, path=["response"]) + + @parametrize + async def test_streaming_response_list_openapi(self, async_client: AsyncRunloop) -> None: + async with async_client.functions.with_streaming_response.list_openapi() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + function = await response.parse() + assert_matches_type(object, function, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/test_client.py b/tests/test_client.py index a9738496a..ab10be034 100755 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -87,7 +87,7 @@ def test_copy_default_options(self) -> None: # options that have a default are overridden correctly copied = self.client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 0 + assert self.client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 @@ -706,20 +706,20 @@ class Model(BaseModel): "remaining_retries,retry_after,timeout", [ [3, "20", 20], - [3, "0", 1], - [3, "-10", 1], + [3, "0", 0.5], + [3, "-10", 0.5], [3, "60", 60], - [3, "61", 1], + [3, "61", 0.5], [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], - [3, "Fri, 29 Sep 2023 16:26:37 GMT", 1], - [3, "Fri, 29 Sep 2023 16:26:27 GMT", 1], + [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], - [3, "Fri, 29 Sep 2023 16:27:38 GMT", 1], - [3, "99999999999999999999999999999999999", 1], - [3, "Zun, 29 Sep 2023 16:26:27 GMT", 1], - [3, "", 1], - [2, "", 1 * 2.0], - [1, "", 1 * 4.0], + [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], + [3, "99999999999999999999999999999999999", 0.5], + [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "", 0.5], + [2, "", 0.5 * 2.0], + [1, "", 0.5 * 4.0], ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) @@ -729,7 +729,7 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 1 * 0.875) # pyright: ignore[reportUnknownMemberType] + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("runloop_api_client._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -820,7 +820,7 @@ def test_copy_default_options(self) -> None: # options that have a default are overridden correctly copied = self.client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 0 + assert self.client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 @@ -1442,20 +1442,20 @@ class Model(BaseModel): "remaining_retries,retry_after,timeout", [ [3, "20", 20], - [3, "0", 1], - [3, "-10", 1], + [3, "0", 0.5], + [3, "-10", 0.5], [3, "60", 60], - [3, "61", 1], + [3, "61", 0.5], [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], - [3, "Fri, 29 Sep 2023 16:26:37 GMT", 1], - [3, "Fri, 29 Sep 2023 16:26:27 GMT", 1], + [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], - [3, "Fri, 29 Sep 2023 16:27:38 GMT", 1], - [3, "99999999999999999999999999999999999", 1], - [3, "Zun, 29 Sep 2023 16:26:27 GMT", 1], - [3, "", 1], - [2, "", 1 * 2.0], - [1, "", 1 * 4.0], + [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], + [3, "99999999999999999999999999999999999", 0.5], + [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "", 0.5], + [2, "", 0.5 * 2.0], + [1, "", 0.5 * 4.0], ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) @@ -1466,7 +1466,7 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 1 * 0.875) # pyright: ignore[reportUnknownMemberType] + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("runloop_api_client._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url)