Skip to content

Commit 382b901

Browse files
feat(api): api update
1 parent 27007c0 commit 382b901

File tree

4 files changed

+231
-2
lines changed

4 files changed

+231
-2
lines changed

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 91
1+
configured_endpoints: 92
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-1d4b018cbfb409baf83725737f00789a9ddbbdbdbe12db1ac7a1fd2cf9c453f0.yml
33
openapi_spec_hash: 1c533f386f6d3d3802d353cc6f1df547
4-
config_hash: 55cf3b0829d3d91846df7c4cfab7db0d
4+
config_hash: 33b544375e4a932cbb2890f79a9aa040

api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ Methods:
297297
- <code title="get /v1/scenarios/runs">client.scenarios.runs.<a href="./src/runloop_api_client/resources/scenarios/runs.py">list</a>(\*\*<a href="src/runloop_api_client/types/scenarios/run_list_params.py">params</a>) -> <a href="./src/runloop_api_client/types/scenario_run_view.py">SyncBenchmarkRunsCursorIDPage[ScenarioRunView]</a></code>
298298
- <code title="post /v1/scenarios/runs/{id}/cancel">client.scenarios.runs.<a href="./src/runloop_api_client/resources/scenarios/runs.py">cancel</a>(id) -> <a href="./src/runloop_api_client/types/scenario_run_view.py">ScenarioRunView</a></code>
299299
- <code title="post /v1/scenarios/runs/{id}/complete">client.scenarios.runs.<a href="./src/runloop_api_client/resources/scenarios/runs.py">complete</a>(id) -> <a href="./src/runloop_api_client/types/scenario_run_view.py">ScenarioRunView</a></code>
300+
- <code title="post /v1/scenarios/runs/{id}/download_logs">client.scenarios.runs.<a href="./src/runloop_api_client/resources/scenarios/runs.py">download_logs</a>(id) -> BinaryAPIResponse</code>
300301
- <code title="post /v1/scenarios/runs/{id}/score">client.scenarios.runs.<a href="./src/runloop_api_client/resources/scenarios/runs.py">score</a>(id) -> <a href="./src/runloop_api_client/types/scenario_run_view.py">ScenarioRunView</a></code>
301302

302303
## Scorers

src/runloop_api_client/resources/scenarios/runs.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,18 @@
99
from ..._compat import cached_property
1010
from ..._resource import SyncAPIResource, AsyncAPIResource
1111
from ..._response import (
12+
BinaryAPIResponse,
13+
AsyncBinaryAPIResponse,
14+
StreamedBinaryAPIResponse,
15+
AsyncStreamedBinaryAPIResponse,
1216
to_raw_response_wrapper,
1317
to_streamed_response_wrapper,
1418
async_to_raw_response_wrapper,
19+
to_custom_raw_response_wrapper,
1520
async_to_streamed_response_wrapper,
21+
to_custom_streamed_response_wrapper,
22+
async_to_custom_raw_response_wrapper,
23+
async_to_custom_streamed_response_wrapper,
1624
)
1725
from ...pagination import SyncBenchmarkRunsCursorIDPage, AsyncBenchmarkRunsCursorIDPage
1826
from ..._exceptions import RunloopError
@@ -213,6 +221,48 @@ def complete(
213221
cast_to=ScenarioRunView,
214222
)
215223

224+
def download_logs(
225+
self,
226+
id: str,
227+
*,
228+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
229+
# The extra values given here take precedence over values defined on the client or passed to this method.
230+
extra_headers: Headers | None = None,
231+
extra_query: Query | None = None,
232+
extra_body: Body | None = None,
233+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
234+
idempotency_key: str | None = None,
235+
) -> BinaryAPIResponse:
236+
"""
237+
Download a zip file containing all logs for a Scenario run from the associated
238+
devbox.
239+
240+
Args:
241+
extra_headers: Send extra headers
242+
243+
extra_query: Add additional query parameters to the request
244+
245+
extra_body: Add additional JSON properties to the request
246+
247+
timeout: Override the client-level default timeout for this request, in seconds
248+
249+
idempotency_key: Specify a custom idempotency key for this request
250+
"""
251+
if not id:
252+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
253+
extra_headers = {"Accept": "application/zip", **(extra_headers or {})}
254+
return self._post(
255+
f"/v1/scenarios/runs/{id}/download_logs",
256+
options=make_request_options(
257+
extra_headers=extra_headers,
258+
extra_query=extra_query,
259+
extra_body=extra_body,
260+
timeout=timeout,
261+
idempotency_key=idempotency_key,
262+
),
263+
cast_to=BinaryAPIResponse,
264+
)
265+
216266
def score(
217267
self,
218268
id: str,
@@ -583,6 +633,48 @@ async def complete(
583633
cast_to=ScenarioRunView,
584634
)
585635

636+
async def download_logs(
637+
self,
638+
id: str,
639+
*,
640+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
641+
# The extra values given here take precedence over values defined on the client or passed to this method.
642+
extra_headers: Headers | None = None,
643+
extra_query: Query | None = None,
644+
extra_body: Body | None = None,
645+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
646+
idempotency_key: str | None = None,
647+
) -> AsyncBinaryAPIResponse:
648+
"""
649+
Download a zip file containing all logs for a Scenario run from the associated
650+
devbox.
651+
652+
Args:
653+
extra_headers: Send extra headers
654+
655+
extra_query: Add additional query parameters to the request
656+
657+
extra_body: Add additional JSON properties to the request
658+
659+
timeout: Override the client-level default timeout for this request, in seconds
660+
661+
idempotency_key: Specify a custom idempotency key for this request
662+
"""
663+
if not id:
664+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
665+
extra_headers = {"Accept": "application/zip", **(extra_headers or {})}
666+
return await self._post(
667+
f"/v1/scenarios/runs/{id}/download_logs",
668+
options=make_request_options(
669+
extra_headers=extra_headers,
670+
extra_query=extra_query,
671+
extra_body=extra_body,
672+
timeout=timeout,
673+
idempotency_key=idempotency_key,
674+
),
675+
cast_to=AsyncBinaryAPIResponse,
676+
)
677+
586678
async def score(
587679
self,
588680
id: str,
@@ -782,6 +874,10 @@ def __init__(self, runs: RunsResource) -> None:
782874
self.complete = to_raw_response_wrapper(
783875
runs.complete,
784876
)
877+
self.download_logs = to_custom_raw_response_wrapper(
878+
runs.download_logs,
879+
BinaryAPIResponse,
880+
)
785881
self.score = to_raw_response_wrapper(
786882
runs.score,
787883
)
@@ -803,6 +899,10 @@ def __init__(self, runs: AsyncRunsResource) -> None:
803899
self.complete = async_to_raw_response_wrapper(
804900
runs.complete,
805901
)
902+
self.download_logs = async_to_custom_raw_response_wrapper(
903+
runs.download_logs,
904+
AsyncBinaryAPIResponse,
905+
)
806906
self.score = async_to_raw_response_wrapper(
807907
runs.score,
808908
)
@@ -824,6 +924,10 @@ def __init__(self, runs: RunsResource) -> None:
824924
self.complete = to_streamed_response_wrapper(
825925
runs.complete,
826926
)
927+
self.download_logs = to_custom_streamed_response_wrapper(
928+
runs.download_logs,
929+
StreamedBinaryAPIResponse,
930+
)
827931
self.score = to_streamed_response_wrapper(
828932
runs.score,
829933
)
@@ -845,6 +949,10 @@ def __init__(self, runs: AsyncRunsResource) -> None:
845949
self.complete = async_to_streamed_response_wrapper(
846950
runs.complete,
847951
)
952+
self.download_logs = async_to_custom_streamed_response_wrapper(
953+
runs.download_logs,
954+
AsyncStreamedBinaryAPIResponse,
955+
)
848956
self.score = async_to_streamed_response_wrapper(
849957
runs.score,
850958
)

tests/api_resources/scenarios/test_runs.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@
55
import os
66
from typing import Any, cast
77

8+
import httpx
89
import pytest
10+
from respx import MockRouter
911

1012
from tests.utils import assert_matches_type
1113
from runloop_api_client import Runloop, AsyncRunloop
1214
from runloop_api_client.types import ScenarioRunView
15+
from runloop_api_client._response import (
16+
BinaryAPIResponse,
17+
AsyncBinaryAPIResponse,
18+
StreamedBinaryAPIResponse,
19+
AsyncStreamedBinaryAPIResponse,
20+
)
1321
from runloop_api_client.pagination import SyncBenchmarkRunsCursorIDPage, AsyncBenchmarkRunsCursorIDPage
1422

1523
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -166,6 +174,62 @@ def test_path_params_complete(self, client: Runloop) -> None:
166174
"",
167175
)
168176

177+
@parametrize
178+
@pytest.mark.respx(base_url=base_url)
179+
def test_method_download_logs(self, client: Runloop, respx_mock: MockRouter) -> None:
180+
respx_mock.post("/v1/scenarios/runs/id/download_logs").mock(
181+
return_value=httpx.Response(200, json={"foo": "bar"})
182+
)
183+
run = client.scenarios.runs.download_logs(
184+
"id",
185+
)
186+
assert run.is_closed
187+
assert run.json() == {"foo": "bar"}
188+
assert cast(Any, run.is_closed) is True
189+
assert isinstance(run, BinaryAPIResponse)
190+
191+
@parametrize
192+
@pytest.mark.respx(base_url=base_url)
193+
def test_raw_response_download_logs(self, client: Runloop, respx_mock: MockRouter) -> None:
194+
respx_mock.post("/v1/scenarios/runs/id/download_logs").mock(
195+
return_value=httpx.Response(200, json={"foo": "bar"})
196+
)
197+
198+
run = client.scenarios.runs.with_raw_response.download_logs(
199+
"id",
200+
)
201+
202+
assert run.is_closed is True
203+
assert run.http_request.headers.get("X-Stainless-Lang") == "python"
204+
assert run.json() == {"foo": "bar"}
205+
assert isinstance(run, BinaryAPIResponse)
206+
207+
@parametrize
208+
@pytest.mark.respx(base_url=base_url)
209+
def test_streaming_response_download_logs(self, client: Runloop, respx_mock: MockRouter) -> None:
210+
respx_mock.post("/v1/scenarios/runs/id/download_logs").mock(
211+
return_value=httpx.Response(200, json={"foo": "bar"})
212+
)
213+
with client.scenarios.runs.with_streaming_response.download_logs(
214+
"id",
215+
) as run:
216+
assert not run.is_closed
217+
assert run.http_request.headers.get("X-Stainless-Lang") == "python"
218+
219+
assert run.json() == {"foo": "bar"}
220+
assert cast(Any, run.is_closed) is True
221+
assert isinstance(run, StreamedBinaryAPIResponse)
222+
223+
assert cast(Any, run.is_closed) is True
224+
225+
@parametrize
226+
@pytest.mark.respx(base_url=base_url)
227+
def test_path_params_download_logs(self, client: Runloop) -> None:
228+
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
229+
client.scenarios.runs.with_raw_response.download_logs(
230+
"",
231+
)
232+
169233
@parametrize
170234
def test_method_score(self, client: Runloop) -> None:
171235
run = client.scenarios.runs.score(
@@ -358,6 +422,62 @@ async def test_path_params_complete(self, async_client: AsyncRunloop) -> None:
358422
"",
359423
)
360424

425+
@parametrize
426+
@pytest.mark.respx(base_url=base_url)
427+
async def test_method_download_logs(self, async_client: AsyncRunloop, respx_mock: MockRouter) -> None:
428+
respx_mock.post("/v1/scenarios/runs/id/download_logs").mock(
429+
return_value=httpx.Response(200, json={"foo": "bar"})
430+
)
431+
run = await async_client.scenarios.runs.download_logs(
432+
"id",
433+
)
434+
assert run.is_closed
435+
assert await run.json() == {"foo": "bar"}
436+
assert cast(Any, run.is_closed) is True
437+
assert isinstance(run, AsyncBinaryAPIResponse)
438+
439+
@parametrize
440+
@pytest.mark.respx(base_url=base_url)
441+
async def test_raw_response_download_logs(self, async_client: AsyncRunloop, respx_mock: MockRouter) -> None:
442+
respx_mock.post("/v1/scenarios/runs/id/download_logs").mock(
443+
return_value=httpx.Response(200, json={"foo": "bar"})
444+
)
445+
446+
run = await async_client.scenarios.runs.with_raw_response.download_logs(
447+
"id",
448+
)
449+
450+
assert run.is_closed is True
451+
assert run.http_request.headers.get("X-Stainless-Lang") == "python"
452+
assert await run.json() == {"foo": "bar"}
453+
assert isinstance(run, AsyncBinaryAPIResponse)
454+
455+
@parametrize
456+
@pytest.mark.respx(base_url=base_url)
457+
async def test_streaming_response_download_logs(self, async_client: AsyncRunloop, respx_mock: MockRouter) -> None:
458+
respx_mock.post("/v1/scenarios/runs/id/download_logs").mock(
459+
return_value=httpx.Response(200, json={"foo": "bar"})
460+
)
461+
async with async_client.scenarios.runs.with_streaming_response.download_logs(
462+
"id",
463+
) as run:
464+
assert not run.is_closed
465+
assert run.http_request.headers.get("X-Stainless-Lang") == "python"
466+
467+
assert await run.json() == {"foo": "bar"}
468+
assert cast(Any, run.is_closed) is True
469+
assert isinstance(run, AsyncStreamedBinaryAPIResponse)
470+
471+
assert cast(Any, run.is_closed) is True
472+
473+
@parametrize
474+
@pytest.mark.respx(base_url=base_url)
475+
async def test_path_params_download_logs(self, async_client: AsyncRunloop) -> None:
476+
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
477+
await async_client.scenarios.runs.with_raw_response.download_logs(
478+
"",
479+
)
480+
361481
@parametrize
362482
async def test_method_score(self, async_client: AsyncRunloop) -> None:
363483
run = await async_client.scenarios.runs.score(

0 commit comments

Comments
 (0)