Skip to content

Commit d6aedc6

Browse files
feat(api): api update
1 parent 5f74568 commit d6aedc6

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 ..._base_client import AsyncPaginator, make_request_options
@@ -210,6 +218,48 @@ def complete(
210218
cast_to=ScenarioRunView,
211219
)
212220

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

492+
async def download_logs(
493+
self,
494+
id: str,
495+
*,
496+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
497+
# The extra values given here take precedence over values defined on the client or passed to this method.
498+
extra_headers: Headers | None = None,
499+
extra_query: Query | None = None,
500+
extra_body: Body | None = None,
501+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
502+
idempotency_key: str | None = None,
503+
) -> AsyncBinaryAPIResponse:
504+
"""
505+
Download a zip file containing all logs for a Scenario run from the associated
506+
devbox.
507+
508+
Args:
509+
extra_headers: Send extra headers
510+
511+
extra_query: Add additional query parameters to the request
512+
513+
extra_body: Add additional JSON properties to the request
514+
515+
timeout: Override the client-level default timeout for this request, in seconds
516+
517+
idempotency_key: Specify a custom idempotency key for this request
518+
"""
519+
if not id:
520+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
521+
extra_headers = {"Accept": "application/zip", **(extra_headers or {})}
522+
return await self._post(
523+
f"/v1/scenarios/runs/{id}/download_logs",
524+
options=make_request_options(
525+
extra_headers=extra_headers,
526+
extra_query=extra_query,
527+
extra_body=extra_body,
528+
timeout=timeout,
529+
idempotency_key=idempotency_key,
530+
),
531+
cast_to=AsyncBinaryAPIResponse,
532+
)
533+
442534
async def score(
443535
self,
444536
id: str,
@@ -496,6 +588,10 @@ def __init__(self, runs: RunsResource) -> None:
496588
self.complete = to_raw_response_wrapper(
497589
runs.complete,
498590
)
591+
self.download_logs = to_custom_raw_response_wrapper(
592+
runs.download_logs,
593+
BinaryAPIResponse,
594+
)
499595
self.score = to_raw_response_wrapper(
500596
runs.score,
501597
)
@@ -517,6 +613,10 @@ def __init__(self, runs: AsyncRunsResource) -> None:
517613
self.complete = async_to_raw_response_wrapper(
518614
runs.complete,
519615
)
616+
self.download_logs = async_to_custom_raw_response_wrapper(
617+
runs.download_logs,
618+
AsyncBinaryAPIResponse,
619+
)
520620
self.score = async_to_raw_response_wrapper(
521621
runs.score,
522622
)
@@ -538,6 +638,10 @@ def __init__(self, runs: RunsResource) -> None:
538638
self.complete = to_streamed_response_wrapper(
539639
runs.complete,
540640
)
641+
self.download_logs = to_custom_streamed_response_wrapper(
642+
runs.download_logs,
643+
StreamedBinaryAPIResponse,
644+
)
541645
self.score = to_streamed_response_wrapper(
542646
runs.score,
543647
)
@@ -559,6 +663,10 @@ def __init__(self, runs: AsyncRunsResource) -> None:
559663
self.complete = async_to_streamed_response_wrapper(
560664
runs.complete,
561665
)
666+
self.download_logs = async_to_custom_streamed_response_wrapper(
667+
runs.download_logs,
668+
AsyncStreamedBinaryAPIResponse,
669+
)
562670
self.score = async_to_streamed_response_wrapper(
563671
runs.score,
564672
)

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)