diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f27781a0f..2c310a467 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.55.2" + ".": "0.56.1-beta" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 4ac8bf319..e93852be7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 93 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-5bf266bfc4635f690b764f54cbbcd71ff347622e3bfd8540a7d2a4d7d2d78be8.yml -openapi_spec_hash: 3769820d0ac76caf6a1950802c73a382 -config_hash: 7d940dc50b19e75e3719c4d41fd0e8dd +configured_endpoints: 100 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-feb1c5fb18adf1bfc11f6fc7ee95f08a319ce4a504c34c68dee66f090f69a70c.yml +openapi_spec_hash: 758379882a3c4bf49f3ded6ac065a604 +config_hash: b97411af91b8ec0b8b066358c29091b4 diff --git a/CHANGELOG.md b/CHANGELOG.md index b76a5cf43..d205c5257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.56.1-beta (2025-08-21) + +Full Changelog: [v0.55.2...v0.56.1-beta](https://github.com/runloopai/api-client-python/compare/v0.55.2...v0.56.1-beta) + +### Features + +* **api:** api update ([9ad6951](https://github.com/runloopai/api-client-python/commit/9ad69513705ef867763ef306c15af777de542437)) + ## 0.55.2 (2025-08-19) Full Changelog: [v0.55.1...v0.55.2](https://github.com/runloopai/api-client-python/compare/v0.55.1...v0.55.2) diff --git a/README.md b/README.md index 7270a5281..2392e05e8 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The REST API documentation can be found on [runloop.ai](https://runloop.ai). The ```sh # install from PyPI -pip install runloop_api_client +pip install --pre runloop_api_client ``` ## Usage @@ -73,7 +73,7 @@ You can enable this by installing `aiohttp`: ```sh # install from PyPI -pip install runloop_api_client[aiohttp] +pip install --pre runloop_api_client[aiohttp] ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: diff --git a/api.md b/api.md index 47223f898..d9c0b1032 100644 --- a/api.md +++ b/api.md @@ -1,7 +1,7 @@ # Shared Types ```python -from runloop_api_client.types import AfterIdle, CodeMountParameters, LaunchParameters +from runloop_api_client.types import AfterIdle, CodeMountParameters, LaunchParameters, RunProfile ``` # Benchmarks @@ -326,6 +326,29 @@ Methods: - client.scenarios.scorers.list(\*\*params) -> SyncScenarioScorersCursorIDPage[ScorerListResponse] - client.scenarios.scorers.validate(id, \*\*params) -> ScorerValidateResponse +# Objects + +Types: + +```python +from runloop_api_client.types import ( + ObjectCreateParameters, + ObjectDownloadURLView, + ObjectListView, + ObjectView, +) +``` + +Methods: + +- client.objects.create(\*\*params) -> ObjectView +- client.objects.retrieve(id) -> ObjectView +- client.objects.list(\*\*params) -> SyncObjectsCursorIDPage[ObjectView] +- client.objects.delete(id) -> ObjectView +- client.objects.complete(id) -> ObjectView +- client.objects.download(id, \*\*params) -> ObjectDownloadURLView +- client.objects.list_public(\*\*params) -> SyncObjectsCursorIDPage[ObjectView] + # Repositories Types: diff --git a/pyproject.toml b/pyproject.toml index ca2a3bf07..a5b712e75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "runloop_api_client" -version = "0.55.2" +version = "0.56.1-beta" 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 ff8c86578..ace01b2ee 100644 --- a/src/runloop_api_client/_client.py +++ b/src/runloop_api_client/_client.py @@ -21,7 +21,7 @@ ) from ._utils import is_given, get_async_library from ._version import __version__ -from .resources import secrets, blueprints, repositories +from .resources import objects, secrets, blueprints, repositories from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import RunloopError, APIStatusError from ._base_client import ( @@ -41,6 +41,7 @@ class Runloop(SyncAPIClient): blueprints: blueprints.BlueprintsResource devboxes: devboxes.DevboxesResource scenarios: scenarios.ScenariosResource + objects: objects.ObjectsResource repositories: repositories.RepositoriesResource secrets: secrets.SecretsResource with_raw_response: RunloopWithRawResponse @@ -106,6 +107,7 @@ def __init__( self.blueprints = blueprints.BlueprintsResource(self) self.devboxes = devboxes.DevboxesResource(self) self.scenarios = scenarios.ScenariosResource(self) + self.objects = objects.ObjectsResource(self) self.repositories = repositories.RepositoriesResource(self) self.secrets = secrets.SecretsResource(self) self.with_raw_response = RunloopWithRawResponse(self) @@ -221,6 +223,7 @@ class AsyncRunloop(AsyncAPIClient): blueprints: blueprints.AsyncBlueprintsResource devboxes: devboxes.AsyncDevboxesResource scenarios: scenarios.AsyncScenariosResource + objects: objects.AsyncObjectsResource repositories: repositories.AsyncRepositoriesResource secrets: secrets.AsyncSecretsResource with_raw_response: AsyncRunloopWithRawResponse @@ -286,6 +289,7 @@ def __init__( self.blueprints = blueprints.AsyncBlueprintsResource(self) self.devboxes = devboxes.AsyncDevboxesResource(self) self.scenarios = scenarios.AsyncScenariosResource(self) + self.objects = objects.AsyncObjectsResource(self) self.repositories = repositories.AsyncRepositoriesResource(self) self.secrets = secrets.AsyncSecretsResource(self) self.with_raw_response = AsyncRunloopWithRawResponse(self) @@ -402,6 +406,7 @@ def __init__(self, client: Runloop) -> None: self.blueprints = blueprints.BlueprintsResourceWithRawResponse(client.blueprints) self.devboxes = devboxes.DevboxesResourceWithRawResponse(client.devboxes) self.scenarios = scenarios.ScenariosResourceWithRawResponse(client.scenarios) + self.objects = objects.ObjectsResourceWithRawResponse(client.objects) self.repositories = repositories.RepositoriesResourceWithRawResponse(client.repositories) self.secrets = secrets.SecretsResourceWithRawResponse(client.secrets) @@ -412,6 +417,7 @@ def __init__(self, client: AsyncRunloop) -> None: self.blueprints = blueprints.AsyncBlueprintsResourceWithRawResponse(client.blueprints) self.devboxes = devboxes.AsyncDevboxesResourceWithRawResponse(client.devboxes) self.scenarios = scenarios.AsyncScenariosResourceWithRawResponse(client.scenarios) + self.objects = objects.AsyncObjectsResourceWithRawResponse(client.objects) self.repositories = repositories.AsyncRepositoriesResourceWithRawResponse(client.repositories) self.secrets = secrets.AsyncSecretsResourceWithRawResponse(client.secrets) @@ -422,6 +428,7 @@ def __init__(self, client: Runloop) -> None: self.blueprints = blueprints.BlueprintsResourceWithStreamingResponse(client.blueprints) self.devboxes = devboxes.DevboxesResourceWithStreamingResponse(client.devboxes) self.scenarios = scenarios.ScenariosResourceWithStreamingResponse(client.scenarios) + self.objects = objects.ObjectsResourceWithStreamingResponse(client.objects) self.repositories = repositories.RepositoriesResourceWithStreamingResponse(client.repositories) self.secrets = secrets.SecretsResourceWithStreamingResponse(client.secrets) @@ -432,6 +439,7 @@ def __init__(self, client: AsyncRunloop) -> None: self.blueprints = blueprints.AsyncBlueprintsResourceWithStreamingResponse(client.blueprints) self.devboxes = devboxes.AsyncDevboxesResourceWithStreamingResponse(client.devboxes) self.scenarios = scenarios.AsyncScenariosResourceWithStreamingResponse(client.scenarios) + self.objects = objects.AsyncObjectsResourceWithStreamingResponse(client.objects) self.repositories = repositories.AsyncRepositoriesResourceWithStreamingResponse(client.repositories) self.secrets = secrets.AsyncSecretsResourceWithStreamingResponse(client.secrets) diff --git a/src/runloop_api_client/_version.py b/src/runloop_api_client/_version.py index 4a5e9b111..b85a0a21b 100644 --- a/src/runloop_api_client/_version.py +++ b/src/runloop_api_client/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "runloop_api_client" -__version__ = "0.55.2" # x-release-please-version +__version__ = "0.56.1-beta" # x-release-please-version diff --git a/src/runloop_api_client/pagination.py b/src/runloop_api_client/pagination.py index eb5d5653f..734b6996f 100644 --- a/src/runloop_api_client/pagination.py +++ b/src/runloop_api_client/pagination.py @@ -24,6 +24,8 @@ "AsyncScenarioRunsCursorIDPage", "SyncScenarioScorersCursorIDPage", "AsyncScenarioScorersCursorIDPage", + "SyncObjectsCursorIDPage", + "AsyncObjectsCursorIDPage", ] _T = TypeVar("_T") @@ -74,6 +76,11 @@ class ScenarioScorersCursorIDPageItem(Protocol): id: str +@runtime_checkable +class ObjectsCursorIDPageItem(Protocol): + id: str + + class SyncBlueprintsCursorIDPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): blueprints: List[_T] has_more: Optional[bool] = None @@ -684,3 +691,71 @@ def next_page_info(self) -> Optional[PageInfo]: return None return PageInfo(params={"starting_after": item.id}) + + +class SyncObjectsCursorIDPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): + objects: List[_T] + has_more: Optional[bool] = None + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + objects = self.objects + if not objects: + return [] + return objects + + @override + def has_next_page(self) -> bool: + has_more = self.has_more + if has_more is not None and has_more is False: + return False + + return super().has_next_page() + + @override + def next_page_info(self) -> Optional[PageInfo]: + objects = self.objects + if not objects: + return None + + item = cast(Any, objects[-1]) + if not isinstance(item, ObjectsCursorIDPageItem) or item.id is None: # pyright: ignore[reportUnnecessaryComparison] + # TODO emit warning log + return None + + return PageInfo(params={"starting_after": item.id}) + + +class AsyncObjectsCursorIDPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): + objects: List[_T] + has_more: Optional[bool] = None + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + objects = self.objects + if not objects: + return [] + return objects + + @override + def has_next_page(self) -> bool: + has_more = self.has_more + if has_more is not None and has_more is False: + return False + + return super().has_next_page() + + @override + def next_page_info(self) -> Optional[PageInfo]: + objects = self.objects + if not objects: + return None + + item = cast(Any, objects[-1]) + if not isinstance(item, ObjectsCursorIDPageItem) or item.id is None: # pyright: ignore[reportUnnecessaryComparison] + # TODO emit warning log + return None + + return PageInfo(params={"starting_after": item.id}) diff --git a/src/runloop_api_client/resources/__init__.py b/src/runloop_api_client/resources/__init__.py index c493ac8c7..72ea92468 100644 --- a/src/runloop_api_client/resources/__init__.py +++ b/src/runloop_api_client/resources/__init__.py @@ -1,5 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .objects import ( + ObjectsResource, + AsyncObjectsResource, + ObjectsResourceWithRawResponse, + AsyncObjectsResourceWithRawResponse, + ObjectsResourceWithStreamingResponse, + AsyncObjectsResourceWithStreamingResponse, +) from .secrets import ( SecretsResource, AsyncSecretsResource, @@ -74,6 +82,12 @@ "AsyncScenariosResourceWithRawResponse", "ScenariosResourceWithStreamingResponse", "AsyncScenariosResourceWithStreamingResponse", + "ObjectsResource", + "AsyncObjectsResource", + "ObjectsResourceWithRawResponse", + "AsyncObjectsResourceWithRawResponse", + "ObjectsResourceWithStreamingResponse", + "AsyncObjectsResourceWithStreamingResponse", "RepositoriesResource", "AsyncRepositoriesResource", "RepositoriesResourceWithRawResponse", diff --git a/src/runloop_api_client/resources/benchmarks/benchmarks.py b/src/runloop_api_client/resources/benchmarks/benchmarks.py index c8b3ca1e7..38b84a5fb 100644 --- a/src/runloop_api_client/resources/benchmarks/benchmarks.py +++ b/src/runloop_api_client/resources/benchmarks/benchmarks.py @@ -36,6 +36,7 @@ from ..._base_client import AsyncPaginator, make_request_options from ...types.benchmark_view import BenchmarkView from ...types.benchmark_run_view import BenchmarkRunView +from ...types.shared_params.run_profile import RunProfile from ...types.scenario_definition_list_view import ScenarioDefinitionListView __all__ = ["BenchmarksResource", "AsyncBenchmarksResource"] @@ -69,6 +70,8 @@ def create( self, *, name: str, + attribution: Optional[str] | NotGiven = NOT_GIVEN, + description: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: List[str] | NotGiven = NOT_GIVEN, @@ -87,6 +90,10 @@ def create( Args: name: The name of the Benchmark. This must be unique. + attribution: Attribution information for the benchmark. + + description: Detailed description of the benchmark. + metadata: User defined metadata to attach to the benchmark for organization. required_environment_variables: Environment variables required to run the benchmark. If any required variables @@ -113,6 +120,8 @@ def create( body=maybe_transform( { "name": name, + "attribution": attribution, + "description": description, "metadata": metadata, "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, @@ -168,6 +177,8 @@ def update( id: str, *, name: str, + attribution: Optional[str] | NotGiven = NOT_GIVEN, + description: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: List[str] | NotGiven = NOT_GIVEN, @@ -186,6 +197,10 @@ def update( Args: name: The name of the Benchmark. This must be unique. + attribution: Attribution information for the benchmark. + + description: Detailed description of the benchmark. + metadata: User defined metadata to attach to the benchmark for organization. required_environment_variables: Environment variables required to run the benchmark. If any required variables @@ -214,6 +229,8 @@ def update( body=maybe_transform( { "name": name, + "attribution": attribution, + "description": description, "metadata": metadata, "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, @@ -380,7 +397,7 @@ def start_run( benchmark_id: str, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, run_name: Optional[str] | NotGiven = NOT_GIVEN, - run_profile: Optional[benchmark_start_run_params.RunProfile] | NotGiven = NOT_GIVEN, + run_profile: Optional[RunProfile] | 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, @@ -461,6 +478,8 @@ async def create( self, *, name: str, + attribution: Optional[str] | NotGiven = NOT_GIVEN, + description: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: List[str] | NotGiven = NOT_GIVEN, @@ -479,6 +498,10 @@ async def create( Args: name: The name of the Benchmark. This must be unique. + attribution: Attribution information for the benchmark. + + description: Detailed description of the benchmark. + metadata: User defined metadata to attach to the benchmark for organization. required_environment_variables: Environment variables required to run the benchmark. If any required variables @@ -505,6 +528,8 @@ async def create( body=await async_maybe_transform( { "name": name, + "attribution": attribution, + "description": description, "metadata": metadata, "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, @@ -560,6 +585,8 @@ async def update( id: str, *, name: str, + attribution: Optional[str] | NotGiven = NOT_GIVEN, + description: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: List[str] | NotGiven = NOT_GIVEN, @@ -578,6 +605,10 @@ async def update( Args: name: The name of the Benchmark. This must be unique. + attribution: Attribution information for the benchmark. + + description: Detailed description of the benchmark. + metadata: User defined metadata to attach to the benchmark for organization. required_environment_variables: Environment variables required to run the benchmark. If any required variables @@ -606,6 +637,8 @@ async def update( body=await async_maybe_transform( { "name": name, + "attribution": attribution, + "description": description, "metadata": metadata, "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, @@ -772,7 +805,7 @@ async def start_run( benchmark_id: str, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, run_name: Optional[str] | NotGiven = NOT_GIVEN, - run_profile: Optional[benchmark_start_run_params.RunProfile] | NotGiven = NOT_GIVEN, + run_profile: Optional[RunProfile] | 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, diff --git a/src/runloop_api_client/resources/objects.py b/src/runloop_api_client/resources/objects.py new file mode 100644 index 000000000..8f90b1323 --- /dev/null +++ b/src/runloop_api_client/resources/objects.py @@ -0,0 +1,902 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Optional +from typing_extensions import Literal + +import httpx + +from ..types import object_list_params, object_create_params, object_download_params, object_list_public_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 ..pagination import SyncObjectsCursorIDPage, AsyncObjectsCursorIDPage +from .._base_client import AsyncPaginator, make_request_options +from ..types.object_view import ObjectView +from ..types.object_download_url_view import ObjectDownloadURLView + +__all__ = ["ObjectsResource", "AsyncObjectsResource"] + + +class ObjectsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ObjectsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/runloopai/api-client-python#accessing-raw-response-data-eg-headers + """ + return ObjectsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ObjectsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response + """ + return ObjectsResourceWithStreamingResponse(self) + + def create( + self, + *, + content_type: Literal[ + "UNSPECIFIED", + "TEXT_PLAIN", + "TEXT_HTML", + "TEXT_CSS", + "TEXT_JAVASCRIPT", + "TEXT_YAML", + "TEXT_CSV", + "APPLICATION_JSON", + "APPLICATION_XML", + "APPLICATION_PDF", + "APPLICATION_ZIP", + "APPLICATION_GZIP", + "APPLICATION_TAR", + "APPLICATION_TAR_GZIP", + "APPLICATION_OCTET_STREAM", + "IMAGE_JPEG", + "IMAGE_PNG", + "IMAGE_GIF", + "IMAGE_SVG", + "IMAGE_WEBP", + ], + name: str, + metadata: Optional[Dict[str, 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, + idempotency_key: str | None = None, + ) -> ObjectView: + """Create a new Object with content and metadata. + + The Object will be assigned a + unique ID. + + Args: + content_type: The content type of the Object. + + name: The name of the Object. + + metadata: User defined metadata to attach to the object for organization. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + return self._post( + "/v1/objects", + body=maybe_transform( + { + "content_type": content_type, + "name": name, + "metadata": metadata, + }, + object_create_params.ObjectCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ObjectView, + ) + + def retrieve( + 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, + ) -> ObjectView: + """ + Retrieve a specific Object by its unique identifier. + + 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._get( + f"/v1/objects/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ObjectView, + ) + + def list( + self, + *, + content_type: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + search: str | NotGiven = NOT_GIVEN, + starting_after: str | NotGiven = NOT_GIVEN, + state: 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, + ) -> SyncObjectsCursorIDPage[ObjectView]: + """ + List all Objects for the authenticated account with pagination support. + + Args: + content_type: Filter objects by content type. + + limit: The limit of items to return. Default is 20. + + name: Filter objects by name (partial match supported). + + search: Search by object ID or name. + + starting_after: Load the next page of data starting after the item with the given ID. + + state: Filter objects by state (UPLOADING, READ_ONLY, DELETED). + + 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_api_list( + "/v1/objects", + page=SyncObjectsCursorIDPage[ObjectView], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "content_type": content_type, + "limit": limit, + "name": name, + "search": search, + "starting_after": starting_after, + "state": state, + }, + object_list_params.ObjectListParams, + ), + ), + model=ObjectView, + ) + + def delete( + 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, + idempotency_key: str | None = None, + ) -> ObjectView: + """Delete an existing Object by ID. + + This action is irreversible and will remove the + Object and all its metadata. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + f"/v1/objects/{id}/delete", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ObjectView, + ) + + def complete( + 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, + idempotency_key: str | None = None, + ) -> ObjectView: + """ + Mark an Object's upload as complete, transitioning it from UPLOADING to + READ-only state. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + f"/v1/objects/{id}/complete", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ObjectView, + ) + + def download( + self, + id: str, + *, + duration_seconds: int | 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, + ) -> ObjectDownloadURLView: + """Generate a presigned download URL for an Object. + + The URL will be valid for the + specified duration. + + Args: + duration_seconds: Duration in seconds for the presigned URL validity (default: 3600). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + f"/v1/objects/{id}/download", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"duration_seconds": duration_seconds}, object_download_params.ObjectDownloadParams + ), + ), + cast_to=ObjectDownloadURLView, + ) + + def list_public( + self, + *, + content_type: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + search: str | NotGiven = NOT_GIVEN, + starting_after: str | NotGiven = NOT_GIVEN, + state: 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, + ) -> SyncObjectsCursorIDPage[ObjectView]: + """ + List all public Objects with pagination support. + + Args: + content_type: Filter objects by content type. + + limit: The limit of items to return. Default is 20. + + name: Filter objects by name (partial match supported). + + search: Search by object ID or name. + + starting_after: Load the next page of data starting after the item with the given ID. + + state: Filter objects by state (UPLOADING, READ_ONLY, DELETED). + + 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_api_list( + "/v1/objects/list_public", + page=SyncObjectsCursorIDPage[ObjectView], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "content_type": content_type, + "limit": limit, + "name": name, + "search": search, + "starting_after": starting_after, + "state": state, + }, + object_list_public_params.ObjectListPublicParams, + ), + ), + model=ObjectView, + ) + + +class AsyncObjectsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncObjectsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/runloopai/api-client-python#accessing-raw-response-data-eg-headers + """ + return AsyncObjectsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncObjectsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/runloopai/api-client-python#with_streaming_response + """ + return AsyncObjectsResourceWithStreamingResponse(self) + + async def create( + self, + *, + content_type: Literal[ + "UNSPECIFIED", + "TEXT_PLAIN", + "TEXT_HTML", + "TEXT_CSS", + "TEXT_JAVASCRIPT", + "TEXT_YAML", + "TEXT_CSV", + "APPLICATION_JSON", + "APPLICATION_XML", + "APPLICATION_PDF", + "APPLICATION_ZIP", + "APPLICATION_GZIP", + "APPLICATION_TAR", + "APPLICATION_TAR_GZIP", + "APPLICATION_OCTET_STREAM", + "IMAGE_JPEG", + "IMAGE_PNG", + "IMAGE_GIF", + "IMAGE_SVG", + "IMAGE_WEBP", + ], + name: str, + metadata: Optional[Dict[str, 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, + idempotency_key: str | None = None, + ) -> ObjectView: + """Create a new Object with content and metadata. + + The Object will be assigned a + unique ID. + + Args: + content_type: The content type of the Object. + + name: The name of the Object. + + metadata: User defined metadata to attach to the object for organization. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + return await self._post( + "/v1/objects", + body=await async_maybe_transform( + { + "content_type": content_type, + "name": name, + "metadata": metadata, + }, + object_create_params.ObjectCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ObjectView, + ) + + async def retrieve( + 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, + ) -> ObjectView: + """ + Retrieve a specific Object by its unique identifier. + + 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._get( + f"/v1/objects/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ObjectView, + ) + + def list( + self, + *, + content_type: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + search: str | NotGiven = NOT_GIVEN, + starting_after: str | NotGiven = NOT_GIVEN, + state: 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, + ) -> AsyncPaginator[ObjectView, AsyncObjectsCursorIDPage[ObjectView]]: + """ + List all Objects for the authenticated account with pagination support. + + Args: + content_type: Filter objects by content type. + + limit: The limit of items to return. Default is 20. + + name: Filter objects by name (partial match supported). + + search: Search by object ID or name. + + starting_after: Load the next page of data starting after the item with the given ID. + + state: Filter objects by state (UPLOADING, READ_ONLY, DELETED). + + 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_api_list( + "/v1/objects", + page=AsyncObjectsCursorIDPage[ObjectView], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "content_type": content_type, + "limit": limit, + "name": name, + "search": search, + "starting_after": starting_after, + "state": state, + }, + object_list_params.ObjectListParams, + ), + ), + model=ObjectView, + ) + + async def delete( + 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, + idempotency_key: str | None = None, + ) -> ObjectView: + """Delete an existing Object by ID. + + This action is irreversible and will remove the + Object and all its metadata. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + f"/v1/objects/{id}/delete", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ObjectView, + ) + + async def complete( + 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, + idempotency_key: str | None = None, + ) -> ObjectView: + """ + Mark an Object's upload as complete, transitioning it from UPLOADING to + READ-only state. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + f"/v1/objects/{id}/complete", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ObjectView, + ) + + async def download( + self, + id: str, + *, + duration_seconds: int | 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, + ) -> ObjectDownloadURLView: + """Generate a presigned download URL for an Object. + + The URL will be valid for the + specified duration. + + Args: + duration_seconds: Duration in seconds for the presigned URL validity (default: 3600). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + f"/v1/objects/{id}/download", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"duration_seconds": duration_seconds}, object_download_params.ObjectDownloadParams + ), + ), + cast_to=ObjectDownloadURLView, + ) + + def list_public( + self, + *, + content_type: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + search: str | NotGiven = NOT_GIVEN, + starting_after: str | NotGiven = NOT_GIVEN, + state: 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, + ) -> AsyncPaginator[ObjectView, AsyncObjectsCursorIDPage[ObjectView]]: + """ + List all public Objects with pagination support. + + Args: + content_type: Filter objects by content type. + + limit: The limit of items to return. Default is 20. + + name: Filter objects by name (partial match supported). + + search: Search by object ID or name. + + starting_after: Load the next page of data starting after the item with the given ID. + + state: Filter objects by state (UPLOADING, READ_ONLY, DELETED). + + 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_api_list( + "/v1/objects/list_public", + page=AsyncObjectsCursorIDPage[ObjectView], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "content_type": content_type, + "limit": limit, + "name": name, + "search": search, + "starting_after": starting_after, + "state": state, + }, + object_list_public_params.ObjectListPublicParams, + ), + ), + model=ObjectView, + ) + + +class ObjectsResourceWithRawResponse: + def __init__(self, objects: ObjectsResource) -> None: + self._objects = objects + + self.create = to_raw_response_wrapper( + objects.create, + ) + self.retrieve = to_raw_response_wrapper( + objects.retrieve, + ) + self.list = to_raw_response_wrapper( + objects.list, + ) + self.delete = to_raw_response_wrapper( + objects.delete, + ) + self.complete = to_raw_response_wrapper( + objects.complete, + ) + self.download = to_raw_response_wrapper( + objects.download, + ) + self.list_public = to_raw_response_wrapper( + objects.list_public, + ) + + +class AsyncObjectsResourceWithRawResponse: + def __init__(self, objects: AsyncObjectsResource) -> None: + self._objects = objects + + self.create = async_to_raw_response_wrapper( + objects.create, + ) + self.retrieve = async_to_raw_response_wrapper( + objects.retrieve, + ) + self.list = async_to_raw_response_wrapper( + objects.list, + ) + self.delete = async_to_raw_response_wrapper( + objects.delete, + ) + self.complete = async_to_raw_response_wrapper( + objects.complete, + ) + self.download = async_to_raw_response_wrapper( + objects.download, + ) + self.list_public = async_to_raw_response_wrapper( + objects.list_public, + ) + + +class ObjectsResourceWithStreamingResponse: + def __init__(self, objects: ObjectsResource) -> None: + self._objects = objects + + self.create = to_streamed_response_wrapper( + objects.create, + ) + self.retrieve = to_streamed_response_wrapper( + objects.retrieve, + ) + self.list = to_streamed_response_wrapper( + objects.list, + ) + self.delete = to_streamed_response_wrapper( + objects.delete, + ) + self.complete = to_streamed_response_wrapper( + objects.complete, + ) + self.download = to_streamed_response_wrapper( + objects.download, + ) + self.list_public = to_streamed_response_wrapper( + objects.list_public, + ) + + +class AsyncObjectsResourceWithStreamingResponse: + def __init__(self, objects: AsyncObjectsResource) -> None: + self._objects = objects + + self.create = async_to_streamed_response_wrapper( + objects.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + objects.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + objects.list, + ) + self.delete = async_to_streamed_response_wrapper( + objects.delete, + ) + self.complete = async_to_streamed_response_wrapper( + objects.complete, + ) + self.download = async_to_streamed_response_wrapper( + objects.download, + ) + self.list_public = async_to_streamed_response_wrapper( + objects.list_public, + ) diff --git a/src/runloop_api_client/resources/scenarios/scenarios.py b/src/runloop_api_client/resources/scenarios/scenarios.py index 528b91bc5..81a4a9db4 100644 --- a/src/runloop_api_client/resources/scenarios/scenarios.py +++ b/src/runloop_api_client/resources/scenarios/scenarios.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import Dict, List, Optional +from typing_extensions import Literal import httpx @@ -46,6 +47,7 @@ from ...types.scenario_run_view import ScenarioRunView from ...types.input_context_param import InputContextParam from ...types.scoring_contract_param import ScoringContractParam +from ...types.shared_params.run_profile import RunProfile from ...types.input_context_update_param import InputContextUpdateParam from ...types.scenario_environment_param import ScenarioEnvironmentParam from ...types.scoring_contract_update_param import ScoringContractUpdateParam @@ -92,6 +94,7 @@ def create( reference_output: Optional[str] | NotGiven = NOT_GIVEN, required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: Optional[List[str]] | NotGiven = NOT_GIVEN, + validation_type: Optional[Literal["FORWARD", "REVERSE", "EVALUATION"]] | 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, @@ -126,6 +129,8 @@ def create( secret name). If these secrets are not provided or the mapping is incorrect, the scenario will fail to start. + validation_type: Validation strategy. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -148,6 +153,7 @@ def create( "reference_output": reference_output, "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, + "validation_type": validation_type, }, scenario_create_params.ScenarioCreateParams, ), @@ -206,6 +212,7 @@ def update( required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: Optional[List[str]] | NotGiven = NOT_GIVEN, scoring_contract: Optional[ScoringContractUpdateParam] | NotGiven = NOT_GIVEN, + validation_type: Optional[Literal["FORWARD", "REVERSE", "EVALUATION"]] | 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, @@ -238,6 +245,8 @@ def update( scoring_contract: The scoring contract for the Scenario. + validation_type: Validation strategy. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -262,6 +271,7 @@ def update( "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, "scoring_contract": scoring_contract, + "validation_type": validation_type, }, scenario_update_params.ScenarioUpdateParams, ), @@ -388,7 +398,7 @@ def start_run( benchmark_run_id: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, run_name: Optional[str] | NotGiven = NOT_GIVEN, - run_profile: Optional[scenario_start_run_params.RunProfile] | NotGiven = NOT_GIVEN, + run_profile: Optional[RunProfile] | 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, @@ -538,6 +548,7 @@ async def create( reference_output: Optional[str] | NotGiven = NOT_GIVEN, required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: Optional[List[str]] | NotGiven = NOT_GIVEN, + validation_type: Optional[Literal["FORWARD", "REVERSE", "EVALUATION"]] | 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, @@ -572,6 +583,8 @@ async def create( secret name). If these secrets are not provided or the mapping is incorrect, the scenario will fail to start. + validation_type: Validation strategy. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -594,6 +607,7 @@ async def create( "reference_output": reference_output, "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, + "validation_type": validation_type, }, scenario_create_params.ScenarioCreateParams, ), @@ -652,6 +666,7 @@ async def update( required_environment_variables: Optional[List[str]] | NotGiven = NOT_GIVEN, required_secret_names: Optional[List[str]] | NotGiven = NOT_GIVEN, scoring_contract: Optional[ScoringContractUpdateParam] | NotGiven = NOT_GIVEN, + validation_type: Optional[Literal["FORWARD", "REVERSE", "EVALUATION"]] | 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, @@ -684,6 +699,8 @@ async def update( scoring_contract: The scoring contract for the Scenario. + validation_type: Validation strategy. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -708,6 +725,7 @@ async def update( "required_environment_variables": required_environment_variables, "required_secret_names": required_secret_names, "scoring_contract": scoring_contract, + "validation_type": validation_type, }, scenario_update_params.ScenarioUpdateParams, ), @@ -834,7 +852,7 @@ async def start_run( benchmark_run_id: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, str]] | NotGiven = NOT_GIVEN, run_name: Optional[str] | NotGiven = NOT_GIVEN, - run_profile: Optional[scenario_start_run_params.RunProfile] | NotGiven = NOT_GIVEN, + run_profile: Optional[RunProfile] | 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, diff --git a/src/runloop_api_client/types/__init__.py b/src/runloop_api_client/types/__init__.py index 8a9145ca0..31f7c8ca5 100644 --- a/src/runloop_api_client/types/__init__.py +++ b/src/runloop_api_client/types/__init__.py @@ -6,16 +6,19 @@ from .. import _compat from .shared import ( AfterIdle as AfterIdle, + RunProfile as RunProfile, LaunchParameters as LaunchParameters, CodeMountParameters as CodeMountParameters, ) from .devbox_view import DevboxView as DevboxView +from .object_view import ObjectView as ObjectView from .secret_view import SecretView as SecretView from .input_context import InputContext as InputContext from .scenario_view import ScenarioView as ScenarioView from .benchmark_view import BenchmarkView as BenchmarkView from .blueprint_view import BlueprintView as BlueprintView from .devbox_list_view import DevboxListView as DevboxListView +from .object_list_view import ObjectListView as ObjectListView from .scoring_contract import ScoringContract as ScoringContract from .scoring_function import ScoringFunction as ScoringFunction from .secret_list_view import SecretListView as SecretListView @@ -23,6 +26,7 @@ from .benchmark_run_view import BenchmarkRunView as BenchmarkRunView from .devbox_list_params import DevboxListParams as DevboxListParams from .devbox_tunnel_view import DevboxTunnelView as DevboxTunnelView +from .object_list_params import ObjectListParams as ObjectListParams from .secret_list_params import SecretListParams as SecretListParams from .blueprint_build_log import BlueprintBuildLog as BlueprintBuildLog from .blueprint_list_view import BlueprintListView as BlueprintListView @@ -30,6 +34,7 @@ from .devbox_create_params import DevboxCreateParams as DevboxCreateParams from .devbox_snapshot_view import DevboxSnapshotView as DevboxSnapshotView from .devbox_update_params import DevboxUpdateParams as DevboxUpdateParams +from .object_create_params import ObjectCreateParams as ObjectCreateParams from .scenario_environment import ScenarioEnvironment as ScenarioEnvironment from .scenario_list_params import ScenarioListParams as ScenarioListParams from .secret_create_params import SecretCreateParams as SecretCreateParams @@ -37,6 +42,7 @@ from .benchmark_list_params import BenchmarkListParams as BenchmarkListParams from .blueprint_list_params import BlueprintListParams as BlueprintListParams from .blueprint_preview_view import BlueprintPreviewView as BlueprintPreviewView +from .object_download_params import ObjectDownloadParams as ObjectDownloadParams from .repository_list_params import RepositoryListParams as RepositoryListParams from .scenario_create_params import ScenarioCreateParams as ScenarioCreateParams from .scenario_run_list_view import ScenarioRunListView as ScenarioRunListView @@ -48,10 +54,12 @@ from .benchmark_update_params import BenchmarkUpdateParams as BenchmarkUpdateParams from .blueprint_create_params import BlueprintCreateParams as BlueprintCreateParams from .blueprint_preview_params import BlueprintPreviewParams as BlueprintPreviewParams +from .object_download_url_view import ObjectDownloadURLView as ObjectDownloadURLView from .repository_create_params import RepositoryCreateParams as RepositoryCreateParams from .repository_manifest_view import RepositoryManifestView as RepositoryManifestView from .devbox_snapshot_list_view import DevboxSnapshotListView as DevboxSnapshotListView from .devbox_upload_file_params import DevboxUploadFileParams as DevboxUploadFileParams +from .object_list_public_params import ObjectListPublicParams as ObjectListPublicParams from .repository_refresh_params import RepositoryRefreshParams as RepositoryRefreshParams from .scenario_start_run_params import ScenarioStartRunParams as ScenarioStartRunParams from .benchmark_start_run_params import BenchmarkStartRunParams as BenchmarkStartRunParams diff --git a/src/runloop_api_client/types/benchmark_create_params.py b/src/runloop_api_client/types/benchmark_create_params.py index 11937ef53..c43d5a98c 100644 --- a/src/runloop_api_client/types/benchmark_create_params.py +++ b/src/runloop_api_client/types/benchmark_create_params.py @@ -12,6 +12,12 @@ class BenchmarkCreateParams(TypedDict, total=False): name: Required[str] """The name of the Benchmark. This must be unique.""" + attribution: Optional[str] + """Attribution information for the benchmark.""" + + description: Optional[str] + """Detailed description of the benchmark.""" + metadata: Optional[Dict[str, str]] """User defined metadata to attach to the benchmark for organization.""" diff --git a/src/runloop_api_client/types/benchmark_start_run_params.py b/src/runloop_api_client/types/benchmark_start_run_params.py index 23f211cae..7655ff5ad 100644 --- a/src/runloop_api_client/types/benchmark_start_run_params.py +++ b/src/runloop_api_client/types/benchmark_start_run_params.py @@ -6,8 +6,9 @@ from typing_extensions import Required, Annotated, TypedDict from .._utils import PropertyInfo +from .shared_params.run_profile import RunProfile -__all__ = ["BenchmarkStartRunParams", "RunProfile"] +__all__ = ["BenchmarkStartRunParams"] class BenchmarkStartRunParams(TypedDict, total=False): @@ -22,23 +23,3 @@ class BenchmarkStartRunParams(TypedDict, total=False): run_profile: Annotated[Optional[RunProfile], PropertyInfo(alias="runProfile")] """Runtime configuration to use for this benchmark run""" - - -class RunProfile(TypedDict, total=False): - env_vars: Annotated[Optional[Dict[str, str]], PropertyInfo(alias="envVars")] - """Mapping of Environment Variable to Value. - - May be shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would - set the environment variable 'DB_PASS' to the value 'DATABASE_PASSWORD_VALUE'. - """ - - purpose: Optional[str] - """Purpose of the run.""" - - secrets: Optional[Dict[str, str]] - """Mapping of Environment Variable to User Secret Name. - - Never shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would - set the environment variable 'DB_PASS' to the value of the secret - 'DATABASE_PASSWORD'. - """ diff --git a/src/runloop_api_client/types/benchmark_update_params.py b/src/runloop_api_client/types/benchmark_update_params.py index 009dd5793..ef26cd42f 100644 --- a/src/runloop_api_client/types/benchmark_update_params.py +++ b/src/runloop_api_client/types/benchmark_update_params.py @@ -12,6 +12,12 @@ class BenchmarkUpdateParams(TypedDict, total=False): name: Required[str] """The name of the Benchmark. This must be unique.""" + attribution: Optional[str] + """Attribution information for the benchmark.""" + + description: Optional[str] + """Detailed description of the benchmark.""" + metadata: Optional[Dict[str, str]] """User defined metadata to attach to the benchmark for organization.""" diff --git a/src/runloop_api_client/types/benchmark_view.py b/src/runloop_api_client/types/benchmark_view.py index 1b8753c1f..877c8fe26 100644 --- a/src/runloop_api_client/types/benchmark_view.py +++ b/src/runloop_api_client/types/benchmark_view.py @@ -22,6 +22,12 @@ class BenchmarkView(BaseModel): scenario_ids: List[str] = FieldInfo(alias="scenarioIds") """List of Scenario IDs that make up the benchmark.""" + attribution: Optional[str] = None + """Attribution information for the benchmark.""" + + description: Optional[str] = None + """Detailed description of the benchmark.""" + is_public: Optional[bool] = None """Whether this benchmark is public.""" diff --git a/src/runloop_api_client/types/object_create_params.py b/src/runloop_api_client/types/object_create_params.py new file mode 100644 index 000000000..52a5af6f9 --- /dev/null +++ b/src/runloop_api_client/types/object_create_params.py @@ -0,0 +1,42 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Optional +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["ObjectCreateParams"] + + +class ObjectCreateParams(TypedDict, total=False): + content_type: Required[ + Literal[ + "UNSPECIFIED", + "TEXT_PLAIN", + "TEXT_HTML", + "TEXT_CSS", + "TEXT_JAVASCRIPT", + "TEXT_YAML", + "TEXT_CSV", + "APPLICATION_JSON", + "APPLICATION_XML", + "APPLICATION_PDF", + "APPLICATION_ZIP", + "APPLICATION_GZIP", + "APPLICATION_TAR", + "APPLICATION_TAR_GZIP", + "APPLICATION_OCTET_STREAM", + "IMAGE_JPEG", + "IMAGE_PNG", + "IMAGE_GIF", + "IMAGE_SVG", + "IMAGE_WEBP", + ] + ] + """The content type of the Object.""" + + name: Required[str] + """The name of the Object.""" + + metadata: Optional[Dict[str, str]] + """User defined metadata to attach to the object for organization.""" diff --git a/src/runloop_api_client/types/object_download_params.py b/src/runloop_api_client/types/object_download_params.py new file mode 100644 index 000000000..3dd9e3472 --- /dev/null +++ b/src/runloop_api_client/types/object_download_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__ = ["ObjectDownloadParams"] + + +class ObjectDownloadParams(TypedDict, total=False): + duration_seconds: int + """Duration in seconds for the presigned URL validity (default: 3600).""" diff --git a/src/runloop_api_client/types/object_download_url_view.py b/src/runloop_api_client/types/object_download_url_view.py new file mode 100644 index 000000000..eb35ac3db --- /dev/null +++ b/src/runloop_api_client/types/object_download_url_view.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["ObjectDownloadURLView"] + + +class ObjectDownloadURLView(BaseModel): + download_url: str + """The presigned download URL for the Object.""" diff --git a/src/runloop_api_client/types/object_list_params.py b/src/runloop_api_client/types/object_list_params.py new file mode 100644 index 000000000..044cff81a --- /dev/null +++ b/src/runloop_api_client/types/object_list_params.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ObjectListParams"] + + +class ObjectListParams(TypedDict, total=False): + content_type: str + """Filter objects by content type.""" + + limit: int + """The limit of items to return. Default is 20.""" + + name: str + """Filter objects by name (partial match supported).""" + + search: str + """Search by object ID or name.""" + + starting_after: str + """Load the next page of data starting after the item with the given ID.""" + + state: str + """Filter objects by state (UPLOADING, READ_ONLY, DELETED).""" diff --git a/src/runloop_api_client/types/object_list_public_params.py b/src/runloop_api_client/types/object_list_public_params.py new file mode 100644 index 000000000..a69ef53dd --- /dev/null +++ b/src/runloop_api_client/types/object_list_public_params.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ObjectListPublicParams"] + + +class ObjectListPublicParams(TypedDict, total=False): + content_type: str + """Filter objects by content type.""" + + limit: int + """The limit of items to return. Default is 20.""" + + name: str + """Filter objects by name (partial match supported).""" + + search: str + """Search by object ID or name.""" + + starting_after: str + """Load the next page of data starting after the item with the given ID.""" + + state: str + """Filter objects by state (UPLOADING, READ_ONLY, DELETED).""" diff --git a/src/runloop_api_client/types/object_list_view.py b/src/runloop_api_client/types/object_list_view.py new file mode 100644 index 000000000..049b1be81 --- /dev/null +++ b/src/runloop_api_client/types/object_list_view.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from .._models import BaseModel +from .object_view import ObjectView + +__all__ = ["ObjectListView"] + + +class ObjectListView(BaseModel): + has_more: bool + """True if there are more results available beyond this page.""" + + objects: List[ObjectView] + """List of Object entities.""" + + remaining_count: int + """Number of Objects remaining after this page.""" + + total_count: int + """Total number of Objects across all pages.""" diff --git a/src/runloop_api_client/types/object_view.py b/src/runloop_api_client/types/object_view.py new file mode 100644 index 000000000..549e7e8fb --- /dev/null +++ b/src/runloop_api_client/types/object_view.py @@ -0,0 +1,49 @@ +# 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__ = ["ObjectView"] + + +class ObjectView(BaseModel): + id: str + """The unique identifier of the Object.""" + + content_type: Literal[ + "UNSPECIFIED", + "TEXT_PLAIN", + "TEXT_HTML", + "TEXT_CSS", + "TEXT_JAVASCRIPT", + "TEXT_YAML", + "TEXT_CSV", + "APPLICATION_JSON", + "APPLICATION_XML", + "APPLICATION_PDF", + "APPLICATION_ZIP", + "APPLICATION_GZIP", + "APPLICATION_TAR", + "APPLICATION_TAR_GZIP", + "APPLICATION_OCTET_STREAM", + "IMAGE_JPEG", + "IMAGE_PNG", + "IMAGE_GIF", + "IMAGE_SVG", + "IMAGE_WEBP", + ] + """The content type of the Object.""" + + name: str + """The name of the Object.""" + + state: str + """The current state of the Object.""" + + size_bytes: Optional[int] = None + """The size of the Object content in bytes (null until uploaded).""" + + upload_url: Optional[str] = None + """Presigned URL for uploading content to S3 (only present on create).""" diff --git a/src/runloop_api_client/types/scenario_create_params.py b/src/runloop_api_client/types/scenario_create_params.py index 71f402aa9..294c1645d 100644 --- a/src/runloop_api_client/types/scenario_create_params.py +++ b/src/runloop_api_client/types/scenario_create_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, List, Optional -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict from .input_context_param import InputContextParam from .scoring_contract_param import ScoringContractParam @@ -47,3 +47,6 @@ class ScenarioCreateParams(TypedDict, total=False): secret name). If these secrets are not provided or the mapping is incorrect, the scenario will fail to start. """ + + validation_type: Optional[Literal["FORWARD", "REVERSE", "EVALUATION"]] + """Validation strategy.""" diff --git a/src/runloop_api_client/types/scenario_environment.py b/src/runloop_api_client/types/scenario_environment.py index 97c2977fc..94e244df9 100644 --- a/src/runloop_api_client/types/scenario_environment.py +++ b/src/runloop_api_client/types/scenario_environment.py @@ -15,9 +15,6 @@ class ScenarioEnvironment(BaseModel): launch_parameters: Optional[LaunchParameters] = None """Optional launch parameters to apply to the devbox environment at launch.""" - prebuilt_id: Optional[str] = None - """Use the prebuilt with matching ID.""" - snapshot_id: Optional[str] = None """Use the snapshot with matching ID.""" diff --git a/src/runloop_api_client/types/scenario_environment_param.py b/src/runloop_api_client/types/scenario_environment_param.py index 3b749bb76..5069e5943 100644 --- a/src/runloop_api_client/types/scenario_environment_param.py +++ b/src/runloop_api_client/types/scenario_environment_param.py @@ -17,9 +17,6 @@ class ScenarioEnvironmentParam(TypedDict, total=False): launch_parameters: Optional[LaunchParameters] """Optional launch parameters to apply to the devbox environment at launch.""" - prebuilt_id: Optional[str] - """Use the prebuilt with matching ID.""" - snapshot_id: Optional[str] """Use the snapshot with matching ID.""" diff --git a/src/runloop_api_client/types/scenario_start_run_params.py b/src/runloop_api_client/types/scenario_start_run_params.py index 91d7e34e8..6f5e39c00 100644 --- a/src/runloop_api_client/types/scenario_start_run_params.py +++ b/src/runloop_api_client/types/scenario_start_run_params.py @@ -6,8 +6,9 @@ from typing_extensions import Required, Annotated, TypedDict from .._utils import PropertyInfo +from .shared_params.run_profile import RunProfile -__all__ = ["ScenarioStartRunParams", "RunProfile"] +__all__ = ["ScenarioStartRunParams"] class ScenarioStartRunParams(TypedDict, total=False): @@ -25,23 +26,3 @@ class ScenarioStartRunParams(TypedDict, total=False): run_profile: Annotated[Optional[RunProfile], PropertyInfo(alias="runProfile")] """Runtime configuration to use for this benchmark run""" - - -class RunProfile(TypedDict, total=False): - env_vars: Annotated[Optional[Dict[str, str]], PropertyInfo(alias="envVars")] - """Mapping of Environment Variable to Value. - - May be shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would - set the environment variable 'DB_PASS' to the value 'DATABASE_PASSWORD_VALUE'. - """ - - purpose: Optional[str] - """Purpose of the run.""" - - secrets: Optional[Dict[str, str]] - """Mapping of Environment Variable to User Secret Name. - - Never shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would - set the environment variable 'DB_PASS' to the value of the secret - 'DATABASE_PASSWORD'. - """ diff --git a/src/runloop_api_client/types/scenario_update_params.py b/src/runloop_api_client/types/scenario_update_params.py index 6605c9f24..d92641215 100644 --- a/src/runloop_api_client/types/scenario_update_params.py +++ b/src/runloop_api_client/types/scenario_update_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, List, Optional -from typing_extensions import TypedDict +from typing_extensions import Literal, TypedDict from .input_context_update_param import InputContextUpdateParam from .scenario_environment_param import ScenarioEnvironmentParam @@ -40,3 +40,6 @@ class ScenarioUpdateParams(TypedDict, total=False): scoring_contract: Optional[ScoringContractUpdateParam] """The scoring contract for the Scenario.""" + + validation_type: Optional[Literal["FORWARD", "REVERSE", "EVALUATION"]] + """Validation strategy.""" diff --git a/src/runloop_api_client/types/scenario_view.py b/src/runloop_api_client/types/scenario_view.py index 2b608038a..230bda36c 100644 --- a/src/runloop_api_client/types/scenario_view.py +++ b/src/runloop_api_client/types/scenario_view.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional +from typing_extensions import Literal from .._models import BaseModel from .input_context import InputContext @@ -51,3 +52,6 @@ class ScenarioView(BaseModel): If any required secrets are missing, the scenario will fail to start. """ + + validation_type: Optional[Literal["FORWARD", "REVERSE", "EVALUATION"]] = None + """Validation strategy.""" diff --git a/src/runloop_api_client/types/shared/__init__.py b/src/runloop_api_client/types/shared/__init__.py index bc4b7503e..356cc4022 100644 --- a/src/runloop_api_client/types/shared/__init__.py +++ b/src/runloop_api_client/types/shared/__init__.py @@ -1,5 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .after_idle import AfterIdle as AfterIdle +from .run_profile import RunProfile as RunProfile from .launch_parameters import LaunchParameters as LaunchParameters from .code_mount_parameters import CodeMountParameters as CodeMountParameters diff --git a/src/runloop_api_client/types/shared/run_profile.py b/src/runloop_api_client/types/shared/run_profile.py new file mode 100644 index 000000000..d107fcc76 --- /dev/null +++ b/src/runloop_api_client/types/shared/run_profile.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["RunProfile"] + + +class RunProfile(BaseModel): + env_vars: Optional[Dict[str, str]] = FieldInfo(alias="envVars", default=None) + """Mapping of Environment Variable to Value. + + May be shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would + set the environment variable 'DB_PASS' to the value 'DATABASE_PASSWORD_VALUE'. + """ + + purpose: Optional[str] = None + """Purpose of the run.""" + + secrets: Optional[Dict[str, str]] = None + """Mapping of Environment Variable to User Secret Name. + + Never shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would + set the environment variable 'DB_PASS' to the value of the secret + 'DATABASE_PASSWORD'. + """ diff --git a/src/runloop_api_client/types/shared_params/__init__.py b/src/runloop_api_client/types/shared_params/__init__.py index bc4b7503e..356cc4022 100644 --- a/src/runloop_api_client/types/shared_params/__init__.py +++ b/src/runloop_api_client/types/shared_params/__init__.py @@ -1,5 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .after_idle import AfterIdle as AfterIdle +from .run_profile import RunProfile as RunProfile from .launch_parameters import LaunchParameters as LaunchParameters from .code_mount_parameters import CodeMountParameters as CodeMountParameters diff --git a/src/runloop_api_client/types/shared_params/run_profile.py b/src/runloop_api_client/types/shared_params/run_profile.py new file mode 100644 index 000000000..eca72fcd1 --- /dev/null +++ b/src/runloop_api_client/types/shared_params/run_profile.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Optional +from typing_extensions import Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["RunProfile"] + + +class RunProfile(TypedDict, total=False): + env_vars: Annotated[Optional[Dict[str, str]], PropertyInfo(alias="envVars")] + """Mapping of Environment Variable to Value. + + May be shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would + set the environment variable 'DB_PASS' to the value 'DATABASE_PASSWORD_VALUE'. + """ + + purpose: Optional[str] + """Purpose of the run.""" + + secrets: Optional[Dict[str, str]] + """Mapping of Environment Variable to User Secret Name. + + Never shown in devbox logging. Example: {"DB_PASS": "DATABASE_PASSWORD"} would + set the environment variable 'DB_PASS' to the value of the secret + 'DATABASE_PASSWORD'. + """ diff --git a/tests/api_resources/scenarios/test_scorers.py b/tests/api_resources/scenarios/test_scorers.py index 415693ada..f104a0924 100644 --- a/tests/api_resources/scenarios/test_scorers.py +++ b/tests/api_resources/scenarios/test_scorers.py @@ -209,7 +209,6 @@ def test_method_validate_with_all_params(self, client: Runloop) -> None: "username": "username", }, }, - "prebuilt_id": "prebuilt_id", "snapshot_id": "snapshot_id", "working_directory": "working_directory", }, @@ -441,7 +440,6 @@ async def test_method_validate_with_all_params(self, async_client: AsyncRunloop) "username": "username", }, }, - "prebuilt_id": "prebuilt_id", "snapshot_id": "snapshot_id", "working_directory": "working_directory", }, diff --git a/tests/api_resources/test_benchmarks.py b/tests/api_resources/test_benchmarks.py index 00afa4d43..5585bf1db 100644 --- a/tests/api_resources/test_benchmarks.py +++ b/tests/api_resources/test_benchmarks.py @@ -33,6 +33,8 @@ def test_method_create(self, client: Runloop) -> None: def test_method_create_with_all_params(self, client: Runloop) -> None: benchmark = client.benchmarks.create( name="name", + attribution="attribution", + description="description", metadata={"foo": "string"}, required_environment_variables=["string"], required_secret_names=["string"], @@ -115,6 +117,8 @@ def test_method_update_with_all_params(self, client: Runloop) -> None: benchmark = client.benchmarks.update( id="id", name="name", + attribution="attribution", + description="description", metadata={"foo": "string"}, required_environment_variables=["string"], required_secret_names=["string"], @@ -331,6 +335,8 @@ async def test_method_create(self, async_client: AsyncRunloop) -> None: async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -> None: benchmark = await async_client.benchmarks.create( name="name", + attribution="attribution", + description="description", metadata={"foo": "string"}, required_environment_variables=["string"], required_secret_names=["string"], @@ -413,6 +419,8 @@ async def test_method_update_with_all_params(self, async_client: AsyncRunloop) - benchmark = await async_client.benchmarks.update( id="id", name="name", + attribution="attribution", + description="description", metadata={"foo": "string"}, required_environment_variables=["string"], required_secret_names=["string"], diff --git a/tests/api_resources/test_objects.py b/tests/api_resources/test_objects.py new file mode 100644 index 000000000..aa3462a55 --- /dev/null +++ b/tests/api_resources/test_objects.py @@ -0,0 +1,582 @@ +# 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 ( + ObjectView, + ObjectDownloadURLView, +) +from runloop_api_client.pagination import SyncObjectsCursorIDPage, AsyncObjectsCursorIDPage + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestObjects: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Runloop) -> None: + object_ = client.objects.create( + content_type="UNSPECIFIED", + name="name", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Runloop) -> None: + object_ = client.objects.create( + content_type="UNSPECIFIED", + name="name", + metadata={"foo": "string"}, + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Runloop) -> None: + response = client.objects.with_raw_response.create( + content_type="UNSPECIFIED", + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Runloop) -> None: + with client.objects.with_streaming_response.create( + content_type="UNSPECIFIED", + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_retrieve(self, client: Runloop) -> None: + object_ = client.objects.retrieve( + "id", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Runloop) -> None: + response = client.objects.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Runloop) -> None: + with client.objects.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(ObjectView, object_, 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.objects.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: Runloop) -> None: + object_ = client.objects.list() + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Runloop) -> None: + object_ = client.objects.list( + content_type="content_type", + limit=0, + name="name", + search="search", + starting_after="starting_after", + state="state", + ) + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Runloop) -> None: + response = client.objects.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Runloop) -> None: + with client.objects.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: Runloop) -> None: + object_ = client.objects.delete( + "id", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: Runloop) -> None: + response = client.objects.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: Runloop) -> None: + with client.objects.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.objects.with_raw_response.delete( + "", + ) + + @parametrize + def test_method_complete(self, client: Runloop) -> None: + object_ = client.objects.complete( + "id", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_raw_response_complete(self, client: Runloop) -> None: + response = client.objects.with_raw_response.complete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + def test_streaming_response_complete(self, client: Runloop) -> None: + with client.objects.with_streaming_response.complete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_complete(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.objects.with_raw_response.complete( + "", + ) + + @parametrize + def test_method_download(self, client: Runloop) -> None: + object_ = client.objects.download( + id="id", + ) + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + @parametrize + def test_method_download_with_all_params(self, client: Runloop) -> None: + object_ = client.objects.download( + id="id", + duration_seconds=0, + ) + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + @parametrize + def test_raw_response_download(self, client: Runloop) -> None: + response = client.objects.with_raw_response.download( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + @parametrize + def test_streaming_response_download(self, client: Runloop) -> None: + with client.objects.with_streaming_response.download( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_download(self, client: Runloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.objects.with_raw_response.download( + id="", + ) + + @parametrize + def test_method_list_public(self, client: Runloop) -> None: + object_ = client.objects.list_public() + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + def test_method_list_public_with_all_params(self, client: Runloop) -> None: + object_ = client.objects.list_public( + content_type="content_type", + limit=0, + name="name", + search="search", + starting_after="starting_after", + state="state", + ) + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + def test_raw_response_list_public(self, client: Runloop) -> None: + response = client.objects.with_raw_response.list_public() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + def test_streaming_response_list_public(self, client: Runloop) -> None: + with client.objects.with_streaming_response.list_public() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(SyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncObjects: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.create( + content_type="UNSPECIFIED", + name="name", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.create( + content_type="UNSPECIFIED", + name="name", + metadata={"foo": "string"}, + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncRunloop) -> None: + response = await async_client.objects.with_raw_response.create( + content_type="UNSPECIFIED", + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncRunloop) -> None: + async with async_client.objects.with_streaming_response.create( + content_type="UNSPECIFIED", + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retrieve(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.retrieve( + "id", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncRunloop) -> None: + response = await async_client.objects.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncRunloop) -> None: + async with async_client.objects.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(ObjectView, object_, 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.objects.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.list() + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.list( + content_type="content_type", + limit=0, + name="name", + search="search", + starting_after="starting_after", + state="state", + ) + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncRunloop) -> None: + response = await async_client.objects.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncRunloop) -> None: + async with async_client.objects.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.delete( + "id", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncRunloop) -> None: + response = await async_client.objects.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncRunloop) -> None: + async with async_client.objects.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.objects.with_raw_response.delete( + "", + ) + + @parametrize + async def test_method_complete(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.complete( + "id", + ) + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_raw_response_complete(self, async_client: AsyncRunloop) -> None: + response = await async_client.objects.with_raw_response.complete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + @parametrize + async def test_streaming_response_complete(self, async_client: AsyncRunloop) -> None: + async with async_client.objects.with_streaming_response.complete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(ObjectView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_complete(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.objects.with_raw_response.complete( + "", + ) + + @parametrize + async def test_method_download(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.download( + id="id", + ) + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + @parametrize + async def test_method_download_with_all_params(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.download( + id="id", + duration_seconds=0, + ) + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + @parametrize + async def test_raw_response_download(self, async_client: AsyncRunloop) -> None: + response = await async_client.objects.with_raw_response.download( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + @parametrize + async def test_streaming_response_download(self, async_client: AsyncRunloop) -> None: + async with async_client.objects.with_streaming_response.download( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(ObjectDownloadURLView, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_download(self, async_client: AsyncRunloop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.objects.with_raw_response.download( + id="", + ) + + @parametrize + async def test_method_list_public(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.list_public() + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + async def test_method_list_public_with_all_params(self, async_client: AsyncRunloop) -> None: + object_ = await async_client.objects.list_public( + content_type="content_type", + limit=0, + name="name", + search="search", + starting_after="starting_after", + state="state", + ) + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + async def test_raw_response_list_public(self, async_client: AsyncRunloop) -> None: + response = await async_client.objects.with_raw_response.list_public() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + @parametrize + async def test_streaming_response_list_public(self, async_client: AsyncRunloop) -> None: + async with async_client.objects.with_streaming_response.list_public() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(AsyncObjectsCursorIDPage[ObjectView], object_, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_scenarios.py b/tests/api_resources/test_scenarios.py index 53507ac7f..a2da71fab 100644 --- a/tests/api_resources/test_scenarios.py +++ b/tests/api_resources/test_scenarios.py @@ -85,7 +85,6 @@ def test_method_create_with_all_params(self, client: Runloop) -> None: "username": "username", }, }, - "prebuilt_id": "prebuilt_id", "snapshot_id": "snapshot_id", "working_directory": "working_directory", }, @@ -93,6 +92,7 @@ def test_method_create_with_all_params(self, client: Runloop) -> None: reference_output="reference_output", required_environment_variables=["string"], required_secret_names=["string"], + validation_type="FORWARD", ) assert_matches_type(ScenarioView, scenario, path=["response"]) @@ -218,7 +218,6 @@ def test_method_update_with_all_params(self, client: Runloop) -> None: "username": "username", }, }, - "prebuilt_id": "prebuilt_id", "snapshot_id": "snapshot_id", "working_directory": "working_directory", }, @@ -245,6 +244,7 @@ def test_method_update_with_all_params(self, client: Runloop) -> None: } ] }, + validation_type="FORWARD", ) assert_matches_type(ScenarioView, scenario, path=["response"]) @@ -464,7 +464,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) - "username": "username", }, }, - "prebuilt_id": "prebuilt_id", "snapshot_id": "snapshot_id", "working_directory": "working_directory", }, @@ -472,6 +471,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) - reference_output="reference_output", required_environment_variables=["string"], required_secret_names=["string"], + validation_type="FORWARD", ) assert_matches_type(ScenarioView, scenario, path=["response"]) @@ -597,7 +597,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncRunloop) - "username": "username", }, }, - "prebuilt_id": "prebuilt_id", "snapshot_id": "snapshot_id", "working_directory": "working_directory", }, @@ -624,6 +623,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncRunloop) - } ] }, + validation_type="FORWARD", ) assert_matches_type(ScenarioView, scenario, path=["response"])