From 09bc4338396af1f0a28df189bd026ce052554532 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:02:26 +0000 Subject: [PATCH 01/11] fix: use correct field name format for multipart file arrays --- src/dedalus_sdk/_qs.py | 8 ++---- src/dedalus_sdk/_types.py | 3 +++ src/dedalus_sdk/_utils/_utils.py | 42 ++++++++++++++++++++++++++------ tests/test_extract_files.py | 28 +++++++++++++++++---- tests/test_files.py | 2 +- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/dedalus_sdk/_qs.py b/src/dedalus_sdk/_qs.py index de8c99b..4127c19 100644 --- a/src/dedalus_sdk/_qs.py +++ b/src/dedalus_sdk/_qs.py @@ -2,17 +2,13 @@ from typing import Any, List, Tuple, Union, Mapping, TypeVar from urllib.parse import parse_qs, urlencode -from typing_extensions import Literal, get_args +from typing_extensions import get_args -from ._types import NotGiven, not_given +from ._types import NotGiven, ArrayFormat, NestedFormat, not_given from ._utils import flatten _T = TypeVar("_T") - -ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] -NestedFormat = Literal["dots", "brackets"] - PrimitiveData = Union[str, int, float, bool, None] # this should be Data = Union[PrimitiveData, "List[Data]", "Tuple[Data]", "Mapping[str, Data]"] # https://github.com/microsoft/pyright/issues/3555 diff --git a/src/dedalus_sdk/_types.py b/src/dedalus_sdk/_types.py index 60d0aaf..33f4432 100644 --- a/src/dedalus_sdk/_types.py +++ b/src/dedalus_sdk/_types.py @@ -47,6 +47,9 @@ ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") +ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] +NestedFormat = Literal["dots", "brackets"] + # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances diff --git a/src/dedalus_sdk/_utils/_utils.py b/src/dedalus_sdk/_utils/_utils.py index 771859f..199cd23 100644 --- a/src/dedalus_sdk/_utils/_utils.py +++ b/src/dedalus_sdk/_utils/_utils.py @@ -17,11 +17,11 @@ ) from pathlib import Path from datetime import date, datetime -from typing_extensions import TypeGuard +from typing_extensions import TypeGuard, get_args import sniffio -from .._types import Omit, NotGiven, FileTypes, HeadersLike +from .._types import Omit, NotGiven, FileTypes, ArrayFormat, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -40,25 +40,45 @@ def extract_files( query: Mapping[str, object], *, paths: Sequence[Sequence[str]], + array_format: ArrayFormat = "brackets", ) -> list[tuple[str, FileTypes]]: """Recursively extract files from the given dictionary based on specified paths. A path may look like this ['foo', 'files', '', 'data']. + ``array_format`` controls how ```` segments contribute to the emitted + field name. Supported values: ``"brackets"`` (``foo[]``), ``"repeat"`` and + ``"comma"`` (``foo``), ``"indices"`` (``foo[0]``, ``foo[1]``). + Note: this mutates the given dictionary. """ files: list[tuple[str, FileTypes]] = [] for path in paths: - files.extend(_extract_items(query, path, index=0, flattened_key=None)) + files.extend(_extract_items(query, path, index=0, flattened_key=None, array_format=array_format)) return files +def _array_suffix(array_format: ArrayFormat, array_index: int) -> str: + if array_format == "brackets": + return "[]" + if array_format == "indices": + return f"[{array_index}]" + if array_format == "repeat" or array_format == "comma": + # Both repeat the bare field name for each file part; there is no + # meaningful way to comma-join binary parts. + return "" + raise NotImplementedError( + f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" + ) + + def _extract_items( obj: object, path: Sequence[str], *, index: int, flattened_key: str | None, + array_format: ArrayFormat, ) -> list[tuple[str, FileTypes]]: try: key = path[index] @@ -75,9 +95,11 @@ def _extract_items( if is_list(obj): files: list[tuple[str, FileTypes]] = [] - for entry in obj: - assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "") - files.append((flattened_key + "[]", cast(FileTypes, entry))) + for array_index, entry in enumerate(obj): + suffix = _array_suffix(array_format, array_index) + emitted_key = (flattened_key + suffix) if flattened_key else suffix + assert_is_file_content(entry, key=emitted_key) + files.append((emitted_key, cast(FileTypes, entry))) return files assert_is_file_content(obj, key=flattened_key) @@ -106,6 +128,7 @@ def _extract_items( path, index=index, flattened_key=flattened_key, + array_format=array_format, ) elif is_list(obj): if key != "": @@ -117,9 +140,12 @@ def _extract_items( item, path, index=index, - flattened_key=flattened_key + "[]" if flattened_key is not None else "[]", + flattened_key=( + (flattened_key if flattened_key is not None else "") + _array_suffix(array_format, array_index) + ), + array_format=array_format, ) - for item in obj + for array_index, item in enumerate(obj) ] ) diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index cdba814..4b12fbd 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,7 +4,7 @@ import pytest -from dedalus_sdk._types import FileTypes +from dedalus_sdk._types import FileTypes, ArrayFormat from dedalus_sdk._utils import extract_files @@ -37,10 +37,7 @@ def test_multiple_files() -> None: def test_top_level_file_array() -> None: query = {"files": [b"file one", b"file two"], "title": "hello"} - assert extract_files(query, paths=[["files", ""]]) == [ - ("files[]", b"file one"), - ("files[]", b"file two"), - ] + assert extract_files(query, paths=[["files", ""]]) == [("files[]", b"file one"), ("files[]", b"file two")] assert query == {"title": "hello"} @@ -71,3 +68,24 @@ def test_ignores_incorrect_paths( expected: list[tuple[str, FileTypes]], ) -> None: assert extract_files(query, paths=paths) == expected + + +@pytest.mark.parametrize( + "array_format,expected_top_level,expected_nested", + [ + ("brackets", [("files[]", b"a"), ("files[]", b"b")], [("items[][file]", b"a"), ("items[][file]", b"b")]), + ("repeat", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("comma", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("indices", [("files[0]", b"a"), ("files[1]", b"b")], [("items[0][file]", b"a"), ("items[1][file]", b"b")]), + ], +) +def test_array_format_controls_file_field_names( + array_format: ArrayFormat, + expected_top_level: list[tuple[str, FileTypes]], + expected_nested: list[tuple[str, FileTypes]], +) -> None: + top_level = {"files": [b"a", b"b"]} + assert extract_files(top_level, paths=[["files", ""]], array_format=array_format) == expected_top_level + + nested = {"items": [{"file": b"a"}, {"file": b"b"}]} + assert extract_files(nested, paths=[["items", "", "file"]], array_format=array_format) == expected_nested diff --git a/tests/test_files.py b/tests/test_files.py index 863b1e2..e1cd7d2 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -131,7 +131,7 @@ def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: copied = deepcopy_with_paths(original, [["items", "", "file"]]) extracted = extract_files(copied, paths=[["items", "", "file"]]) - assert extracted == [("items[][file]", file1), ("items[][file]", file2)] + assert [entry for _, entry in extracted] == [file1, file2] assert original == { "items": [ {"file": file1, "extra": 1}, From 31654ea7dba81fd19b0c334846eb4bf988035224 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:31:09 +0000 Subject: [PATCH 02/11] feat: support setting headers via env --- src/dedalus_sdk/_client.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/dedalus_sdk/_client.py b/src/dedalus_sdk/_client.py index 892f5a5..32dba49 100644 --- a/src/dedalus_sdk/_client.py +++ b/src/dedalus_sdk/_client.py @@ -20,7 +20,11 @@ RequestOptions, not_given, ) -from ._utils import is_given, get_async_library +from ._utils import ( + is_given, + is_mapping_t, + get_async_library, +) from ._compat import cached_property from ._models import SecurityOptions from ._version import __version__ @@ -105,6 +109,15 @@ def __init__( if base_url is None: base_url = f"https://dcs.dedaluslabs.ai" + custom_headers_env = os.environ.get("DEDALUS_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, @@ -339,6 +352,15 @@ def __init__( if base_url is None: base_url = f"https://dcs.dedaluslabs.ai" + custom_headers_env = os.environ.get("DEDALUS_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, From e2963215b941cf1f14c44215f4c5ba8427ea00d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:44:57 +0000 Subject: [PATCH 03/11] chore: remove custom code --- uv.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uv.lock b/uv.lock index a5ece63..c06f3a3 100644 --- a/uv.lock +++ b/uv.lock @@ -244,7 +244,7 @@ wheels = [ [[package]] name = "dedalus-sdk" -version = "0.1.0" +version = "0.2.0" source = { editable = "." } dependencies = [ { name = "anyio" }, From e1486b285339153358595740bbb860cd551ba083 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:17:39 +0000 Subject: [PATCH 04/11] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index aa2fad7..d378b3d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 29 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs%2Fdedalus-018f649c40452f64a7454d2841a410297ef931793d4f6dbfebab541b060a2b21.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-018f649c40452f64a7454d2841a410297ef931793d4f6dbfebab541b060a2b21.yml openapi_spec_hash: 7fd462f39c9dcf835904c06fea51ef46 config_hash: 816359ffd81767484efabdc39744bf77 From da809503a76ffca54b28cb1639f39c44331e14e5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:24:48 +0000 Subject: [PATCH 05/11] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index d378b3d..5695e43 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 29 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-018f649c40452f64a7454d2841a410297ef931793d4f6dbfebab541b060a2b21.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-a02ef5eb9c2357f4c06716829a39e0a3677f1ada1f838144a5195647ad1c9810.yml openapi_spec_hash: 7fd462f39c9dcf835904c06fea51ef46 config_hash: 816359ffd81767484efabdc39744bf77 From 6a4934a311b675e0b59dfe5e1d521e2d9405b62f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:59:59 +0000 Subject: [PATCH 06/11] chore(internal): reformat pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f1b7abd..e0354e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -155,7 +155,7 @@ show_error_codes = true # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. -exclude = ['src/dedalus_sdk/_files.py', '_dev/.*.py', 'tests/.*'] +exclude = ["src/dedalus_sdk/_files.py", "_dev/.*.py", "tests/.*"] strict_equality = true implicit_reexport = true From aa1c869547ee96d99910ac50f0962c02812cf844 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 16:25:19 +0000 Subject: [PATCH 07/11] fix(client): add missing f-string prefix in file type error message --- src/dedalus_sdk/_files.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dedalus_sdk/_files.py b/src/dedalus_sdk/_files.py index 0fdce17..76da9e0 100644 --- a/src/dedalus_sdk/_files.py +++ b/src/dedalus_sdk/_files.py @@ -99,7 +99,7 @@ async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles elif is_sequence_t(files): files = [(key, await _async_transform_file(file)) for key, file in files] else: - raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence") + raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence") return files From d2686f3ea4d92a9b4c1ab211f62483dd2cdfc712 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 17:41:24 +0000 Subject: [PATCH 08/11] feat(internal/types): support eagerly validating pydantic iterators --- src/dedalus_sdk/_models.py | 80 ++++++++++++++++++++++++++++++++++++++ tests/test_models.py | 60 ++++++++++++++++++++++++++-- 2 files changed, 137 insertions(+), 3 deletions(-) diff --git a/src/dedalus_sdk/_models.py b/src/dedalus_sdk/_models.py index b4f251a..ce728eb 100644 --- a/src/dedalus_sdk/_models.py +++ b/src/dedalus_sdk/_models.py @@ -25,7 +25,9 @@ ClassVar, Protocol, Required, + Annotated, ParamSpec, + TypeAlias, TypedDict, TypeGuard, final, @@ -79,7 +81,15 @@ from ._constants import RAW_RESPONSE_HEADER if TYPE_CHECKING: + from pydantic import GetCoreSchemaHandler, ValidatorFunctionWrapHandler + from pydantic_core import CoreSchema, core_schema from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema +else: + try: + from pydantic_core import CoreSchema, core_schema + except ImportError: + CoreSchema = None + core_schema = None __all__ = ["BaseModel", "GenericModel"] @@ -396,6 +406,76 @@ def model_dump_json( ) +class _EagerIterable(list[_T], Generic[_T]): + """ + Accepts any Iterable[T] input (including generators), consumes it + eagerly, and validates all items upfront. + + Validation preserves the original container type where possible + (e.g. a set[T] stays a set[T]). Serialization (model_dump / JSON) + always emits a list — round-tripping through model_dump() will not + restore the original container type. + """ + + @classmethod + def __get_pydantic_core_schema__( + cls, + source_type: Any, + handler: GetCoreSchemaHandler, + ) -> CoreSchema: + (item_type,) = get_args(source_type) or (Any,) + item_schema: CoreSchema = handler.generate_schema(item_type) + list_of_items_schema: CoreSchema = core_schema.list_schema(item_schema) + + return core_schema.no_info_wrap_validator_function( + cls._validate, + list_of_items_schema, + serialization=core_schema.plain_serializer_function_ser_schema( + cls._serialize, + info_arg=False, + ), + ) + + @staticmethod + def _validate(v: Iterable[_T], handler: "ValidatorFunctionWrapHandler") -> Any: + original_type: type[Any] = type(v) + + # Normalize to list so list_schema can validate each item + if isinstance(v, list): + items: list[_T] = v + else: + try: + items = list(v) + except TypeError as e: + raise TypeError("Value is not iterable") from e + + # Validate items against the inner schema + validated: list[_T] = handler(items) + + # Reconstruct original container type + if original_type is list: + return validated + # str(list) produces the list's repr, not a string built from items, + # so skip reconstruction for str and its subclasses. + if issubclass(original_type, str): + return validated + try: + return original_type(validated) + except (TypeError, ValueError): + # If the type cannot be reconstructed, just return the validated list + return validated + + @staticmethod + def _serialize(v: Iterable[_T]) -> list[_T]: + """Always serialize as a list so Pydantic's JSON encoder is happy.""" + if isinstance(v, list): + return v + return list(v) + + +EagerIterable: TypeAlias = Annotated[Iterable[_T], _EagerIterable] + + def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) diff --git a/tests/test_models.py b/tests/test_models.py index 58a18a1..159c141 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,8 @@ import json -from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast +from typing import TYPE_CHECKING, Any, Dict, List, Union, Iterable, Optional, cast from datetime import datetime, timezone -from typing_extensions import Literal, Annotated, TypeAliasType +from collections import deque +from typing_extensions import Literal, Annotated, TypedDict, TypeAliasType import pytest import pydantic @@ -9,7 +10,7 @@ from dedalus_sdk._utils import PropertyInfo from dedalus_sdk._compat import PYDANTIC_V1, parse_obj, model_dump, model_json -from dedalus_sdk._models import DISCRIMINATOR_CACHE, BaseModel, construct_type +from dedalus_sdk._models import DISCRIMINATOR_CACHE, BaseModel, EagerIterable, construct_type class BasicModel(BaseModel): @@ -961,3 +962,56 @@ def __getattr__(self, attr: str) -> Item: ... assert model.a.prop == 1 assert isinstance(model.a, Item) assert model.other == "foo" + + +# NOTE: Workaround for Pydantic Iterable behavior. +# Iterable fields are replaced with a ValidatorIterator and may be consumed +# during serialization, which can cause subsequent dumps to return empty data. +# See: https://github.com/pydantic/pydantic/issues/9541 +@pytest.mark.parametrize( + "data, expected_validated", + [ + ([1, 2, 3], [1, 2, 3]), + ((1, 2, 3), (1, 2, 3)), + (set([1, 2, 3]), set([1, 2, 3])), + (iter([1, 2, 3]), [1, 2, 3]), + ([], []), + ((x for x in [1, 2, 3]), [1, 2, 3]), + (map(lambda x: x, [1, 2, 3]), [1, 2, 3]), + (frozenset([1, 2, 3]), frozenset([1, 2, 3])), + (deque([1, 2, 3]), deque([1, 2, 3])), + ], + ids=["list", "tuple", "set", "iterator", "empty", "generator", "map", "frozenset", "deque"], +) +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2") +def test_iterable_construction(data: Iterable[int], expected_validated: Iterable[int]) -> None: + class TypeWithIterable(TypedDict): + items: EagerIterable[int] + + class Model(BaseModel): + data: TypeWithIterable + + m = Model.model_validate({"data": {"items": data}}) + assert m.data["items"] == expected_validated + + # Verify repeated dumps don't lose data (the original bug) + assert m.model_dump()["data"]["items"] == list(expected_validated) + assert m.model_dump()["data"]["items"] == list(expected_validated) + + +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2") +def test_iterable_construction_str_falls_back_to_list() -> None: + # str is iterable (over chars), but str(list_of_chars) produces the list's repr + # rather than reconstructing a string from items. We special-case str to fall + # back to list instead of attempting reconstruction. + class TypeWithIterable(TypedDict): + items: EagerIterable[str] + + class Model(BaseModel): + data: TypeWithIterable + + m = Model.model_validate({"data": {"items": "hello"}}) + + # falls back to list of chars rather than calling str(["h", "e", "l", "l", "o"]) + assert m.data["items"] == ["h", "e", "l", "l", "o"] + assert m.model_dump()["data"]["items"] == ["h", "e", "l", "l", "o"] From 3ecc5f71350a236eeb38b6ca1116146378ea7f20 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 19:07:31 +0000 Subject: [PATCH 09/11] feat(api): add orgs usage endpoints, autosleep to machines, remove if_match parameters --- .stats.yml | 8 +- README.md | 4 +- api.md | 22 + src/dedalus_sdk/_client.py | 39 +- src/dedalus_sdk/resources/__init__.py | 14 + .../resources/machines/machines.py | 46 +- src/dedalus_sdk/resources/orgs/__init__.py | 33 ++ src/dedalus_sdk/resources/orgs/orgs.py | 102 +++++ src/dedalus_sdk/resources/orgs/usage.py | 427 ++++++++++++++++++ src/dedalus_sdk/types/machine.py | 3 + .../types/machine_create_params.py | 7 + src/dedalus_sdk/types/machine_list_item.py | 3 + .../types/machine_update_params.py | 11 +- src/dedalus_sdk/types/orgs/__init__.py | 14 + .../types/orgs/machine_storage_usage.py | 20 + .../orgs/machine_storage_usage_evidence.py | 34 ++ src/dedalus_sdk/types/orgs/machine_usage.py | 23 + .../types/orgs/machine_usage_evidence.py | 58 +++ src/dedalus_sdk/types/orgs/org_usage.py | 34 ++ .../usage_get_machine_storage_usage_params.py | 20 + .../orgs/usage_get_machine_usage_params.py | 23 + .../types/orgs/usage_retrieve_params.py | 14 + .../api_resources/machines/test_artifacts.py | 48 +- .../api_resources/machines/test_executions.py | 100 ++-- tests/api_resources/machines/test_previews.py | 64 +-- tests/api_resources/machines/test_ssh.py | 60 +-- .../api_resources/machines/test_terminals.py | 64 +-- tests/api_resources/orgs/__init__.py | 1 + tests/api_resources/orgs/test_usage.py | 314 +++++++++++++ tests/api_resources/test_machines.py | 136 +++--- 30 files changed, 1473 insertions(+), 273 deletions(-) create mode 100644 src/dedalus_sdk/resources/orgs/__init__.py create mode 100644 src/dedalus_sdk/resources/orgs/orgs.py create mode 100644 src/dedalus_sdk/resources/orgs/usage.py create mode 100644 src/dedalus_sdk/types/orgs/__init__.py create mode 100644 src/dedalus_sdk/types/orgs/machine_storage_usage.py create mode 100644 src/dedalus_sdk/types/orgs/machine_storage_usage_evidence.py create mode 100644 src/dedalus_sdk/types/orgs/machine_usage.py create mode 100644 src/dedalus_sdk/types/orgs/machine_usage_evidence.py create mode 100644 src/dedalus_sdk/types/orgs/org_usage.py create mode 100644 src/dedalus_sdk/types/orgs/usage_get_machine_storage_usage_params.py create mode 100644 src/dedalus_sdk/types/orgs/usage_get_machine_usage_params.py create mode 100644 src/dedalus_sdk/types/orgs/usage_retrieve_params.py create mode 100644 tests/api_resources/orgs/__init__.py create mode 100644 tests/api_resources/orgs/test_usage.py diff --git a/.stats.yml b/.stats.yml index 5695e43..d4f19f2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 29 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-a02ef5eb9c2357f4c06716829a39e0a3677f1ada1f838144a5195647ad1c9810.yml -openapi_spec_hash: 7fd462f39c9dcf835904c06fea51ef46 -config_hash: 816359ffd81767484efabdc39744bf77 +configured_endpoints: 32 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-8618662d24c795caf31ecb2b62c603c5cb1002386003f3a40854664da766eef4.yml +openapi_spec_hash: 4dd9388612970bff30995d2a4f53fa59 +config_hash: 1459e41df47cbb91484141371c74dba9 diff --git a/README.md b/README.md index 2ee8b86..7615cb4 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ from dedalus_sdk import Dedalus client = Dedalus() stream = client.machines.watch( - machine_id="machine_id", + machine_id="dm-3", ) for machine in stream: print(machine.machine_id) @@ -142,7 +142,7 @@ from dedalus_sdk import AsyncDedalus client = AsyncDedalus() stream = await client.machines.watch( - machine_id="machine_id", + machine_id="dm-3", ) async for machine in stream: print(machine.machine_id) diff --git a/api.md b/api.md index 99c0772..4e35082 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,25 @@ +# Orgs + +## Usage + +Types: + +```python +from dedalus_sdk.types.orgs import ( + MachineStorageUsage, + MachineStorageUsageEvidence, + MachineUsage, + MachineUsageEvidence, + OrgUsage, +) +``` + +Methods: + +- client.orgs.usage.retrieve(\*, org_id, \*\*params) -> OrgUsage +- client.orgs.usage.get_machine_storage_usage(\*, org_id, \*\*params) -> MachineStorageUsage +- client.orgs.usage.get_machine_usage(\*, org_id, \*\*params) -> MachineUsage + # Machines Types: diff --git a/src/dedalus_sdk/_client.py b/src/dedalus_sdk/_client.py index 32dba49..899c34c 100644 --- a/src/dedalus_sdk/_client.py +++ b/src/dedalus_sdk/_client.py @@ -37,7 +37,8 @@ ) if TYPE_CHECKING: - from .resources import machines + from .resources import orgs, machines + from .resources.orgs.orgs import OrgsResource, AsyncOrgsResource from .resources.machines.machines import MachinesResource, AsyncMachinesResource __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "Dedalus", "AsyncDedalus", "Client", "AsyncClient"] @@ -133,6 +134,12 @@ def __init__( self._default_stream_cls = Stream + @cached_property + def orgs(self) -> OrgsResource: + from .resources.orgs import OrgsResource + + return OrgsResource(self) + @cached_property def machines(self) -> MachinesResource: from .resources.machines import MachinesResource @@ -376,6 +383,12 @@ def __init__( self._default_stream_cls = AsyncStream + @cached_property + def orgs(self) -> AsyncOrgsResource: + from .resources.orgs import AsyncOrgsResource + + return AsyncOrgsResource(self) + @cached_property def machines(self) -> AsyncMachinesResource: from .resources.machines import AsyncMachinesResource @@ -535,6 +548,12 @@ class DedalusWithRawResponse: def __init__(self, client: Dedalus) -> None: self._client = client + @cached_property + def orgs(self) -> orgs.OrgsResourceWithRawResponse: + from .resources.orgs import OrgsResourceWithRawResponse + + return OrgsResourceWithRawResponse(self._client.orgs) + @cached_property def machines(self) -> machines.MachinesResourceWithRawResponse: from .resources.machines import MachinesResourceWithRawResponse @@ -548,6 +567,12 @@ class AsyncDedalusWithRawResponse: def __init__(self, client: AsyncDedalus) -> None: self._client = client + @cached_property + def orgs(self) -> orgs.AsyncOrgsResourceWithRawResponse: + from .resources.orgs import AsyncOrgsResourceWithRawResponse + + return AsyncOrgsResourceWithRawResponse(self._client.orgs) + @cached_property def machines(self) -> machines.AsyncMachinesResourceWithRawResponse: from .resources.machines import AsyncMachinesResourceWithRawResponse @@ -561,6 +586,12 @@ class DedalusWithStreamedResponse: def __init__(self, client: Dedalus) -> None: self._client = client + @cached_property + def orgs(self) -> orgs.OrgsResourceWithStreamingResponse: + from .resources.orgs import OrgsResourceWithStreamingResponse + + return OrgsResourceWithStreamingResponse(self._client.orgs) + @cached_property def machines(self) -> machines.MachinesResourceWithStreamingResponse: from .resources.machines import MachinesResourceWithStreamingResponse @@ -574,6 +605,12 @@ class AsyncDedalusWithStreamedResponse: def __init__(self, client: AsyncDedalus) -> None: self._client = client + @cached_property + def orgs(self) -> orgs.AsyncOrgsResourceWithStreamingResponse: + from .resources.orgs import AsyncOrgsResourceWithStreamingResponse + + return AsyncOrgsResourceWithStreamingResponse(self._client.orgs) + @cached_property def machines(self) -> machines.AsyncMachinesResourceWithStreamingResponse: from .resources.machines import AsyncMachinesResourceWithStreamingResponse diff --git a/src/dedalus_sdk/resources/__init__.py b/src/dedalus_sdk/resources/__init__.py index 2967015..5b131fd 100644 --- a/src/dedalus_sdk/resources/__init__.py +++ b/src/dedalus_sdk/resources/__init__.py @@ -1,5 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .orgs import ( + OrgsResource, + AsyncOrgsResource, + OrgsResourceWithRawResponse, + AsyncOrgsResourceWithRawResponse, + OrgsResourceWithStreamingResponse, + AsyncOrgsResourceWithStreamingResponse, +) from .machines import ( MachinesResource, AsyncMachinesResource, @@ -10,6 +18,12 @@ ) __all__ = [ + "OrgsResource", + "AsyncOrgsResource", + "OrgsResourceWithRawResponse", + "AsyncOrgsResourceWithRawResponse", + "OrgsResourceWithStreamingResponse", + "AsyncOrgsResourceWithStreamingResponse", "MachinesResource", "AsyncMachinesResource", "MachinesResourceWithRawResponse", diff --git a/src/dedalus_sdk/resources/machines/machines.py b/src/dedalus_sdk/resources/machines/machines.py index 70ad0d1..b78a9ca 100644 --- a/src/dedalus_sdk/resources/machines/machines.py +++ b/src/dedalus_sdk/resources/machines/machines.py @@ -110,6 +110,7 @@ def create( memory_mib: int, storage_gib: int, vcpu: float, + autosleep: str | Omit = omit, # 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, @@ -128,6 +129,9 @@ def create( vcpu: CPU in vCPUs. + autosleep: Idle window before autosleep. Accepts fixed duration units like 30s, 30m, 2h, + 7d3h4s, or 1w3d, raw seconds ("1800"), or never to disable. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -145,6 +149,7 @@ def create( "memory_mib": memory_mib, "storage_gib": storage_gib, "vcpu": vcpu, + "autosleep": autosleep, }, machine_create_params.MachineCreateParams, ), @@ -195,7 +200,7 @@ def update( self, *, machine_id: str, - if_match: str, + autosleep: str | Omit = omit, memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, @@ -207,10 +212,14 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, idempotency_key: str | None = None, ) -> Machine: - """ - Update machine + """Update machine Args: + autosleep: Idle window before autosleep. + + Accepts fixed duration units like 30s, 30m, 2h, + 7d3h4s, or 1w3d, raw seconds ("1800"), or never to disable. + memory_mib: Memory in MiB. storage_gib: Storage in GiB. @@ -229,11 +238,11 @@ def update( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return self._patch( path_template("/v1/machines/{machine_id}", machine_id=machine_id), body=maybe_transform( { + "autosleep": autosleep, "memory_mib": memory_mib, "storage_gib": storage_gib, "vcpu": vcpu, @@ -297,7 +306,6 @@ def delete( self, *, machine_id: str, - if_match: 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, @@ -322,7 +330,6 @@ def delete( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return self._delete( path_template("/v1/machines/{machine_id}", machine_id=machine_id), options=make_request_options( @@ -339,7 +346,6 @@ def sleep( self, *, machine_id: str, - if_match: 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, @@ -364,7 +370,6 @@ def sleep( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return self._post( path_template("/v1/machines/{machine_id}/sleep", machine_id=machine_id), options=make_request_options( @@ -381,7 +386,6 @@ def wake( self, *, machine_id: str, - if_match: 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, @@ -406,7 +410,6 @@ def wake( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return self._post( path_template("/v1/machines/{machine_id}/wake", machine_id=machine_id), options=make_request_options( @@ -507,6 +510,7 @@ async def create( memory_mib: int, storage_gib: int, vcpu: float, + autosleep: str | Omit = omit, # 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, @@ -525,6 +529,9 @@ async def create( vcpu: CPU in vCPUs. + autosleep: Idle window before autosleep. Accepts fixed duration units like 30s, 30m, 2h, + 7d3h4s, or 1w3d, raw seconds ("1800"), or never to disable. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -542,6 +549,7 @@ async def create( "memory_mib": memory_mib, "storage_gib": storage_gib, "vcpu": vcpu, + "autosleep": autosleep, }, machine_create_params.MachineCreateParams, ), @@ -592,7 +600,7 @@ async def update( self, *, machine_id: str, - if_match: str, + autosleep: str | Omit = omit, memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, @@ -604,10 +612,14 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, idempotency_key: str | None = None, ) -> Machine: - """ - Update machine + """Update machine Args: + autosleep: Idle window before autosleep. + + Accepts fixed duration units like 30s, 30m, 2h, + 7d3h4s, or 1w3d, raw seconds ("1800"), or never to disable. + memory_mib: Memory in MiB. storage_gib: Storage in GiB. @@ -626,11 +638,11 @@ async def update( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return await self._patch( path_template("/v1/machines/{machine_id}", machine_id=machine_id), body=await async_maybe_transform( { + "autosleep": autosleep, "memory_mib": memory_mib, "storage_gib": storage_gib, "vcpu": vcpu, @@ -694,7 +706,6 @@ async def delete( self, *, machine_id: str, - if_match: 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, @@ -719,7 +730,6 @@ async def delete( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return await self._delete( path_template("/v1/machines/{machine_id}", machine_id=machine_id), options=make_request_options( @@ -736,7 +746,6 @@ async def sleep( self, *, machine_id: str, - if_match: 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, @@ -761,7 +770,6 @@ async def sleep( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return await self._post( path_template("/v1/machines/{machine_id}/sleep", machine_id=machine_id), options=make_request_options( @@ -778,7 +786,6 @@ async def wake( self, *, machine_id: str, - if_match: 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, @@ -803,7 +810,6 @@ async def wake( """ if not machine_id: raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {"If-Match": if_match, **(extra_headers or {})} return await self._post( path_template("/v1/machines/{machine_id}/wake", machine_id=machine_id), options=make_request_options( diff --git a/src/dedalus_sdk/resources/orgs/__init__.py b/src/dedalus_sdk/resources/orgs/__init__.py new file mode 100644 index 0000000..beaab70 --- /dev/null +++ b/src/dedalus_sdk/resources/orgs/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .orgs import ( + OrgsResource, + AsyncOrgsResource, + OrgsResourceWithRawResponse, + AsyncOrgsResourceWithRawResponse, + OrgsResourceWithStreamingResponse, + AsyncOrgsResourceWithStreamingResponse, +) +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) + +__all__ = [ + "UsageResource", + "AsyncUsageResource", + "UsageResourceWithRawResponse", + "AsyncUsageResourceWithRawResponse", + "UsageResourceWithStreamingResponse", + "AsyncUsageResourceWithStreamingResponse", + "OrgsResource", + "AsyncOrgsResource", + "OrgsResourceWithRawResponse", + "AsyncOrgsResourceWithRawResponse", + "OrgsResourceWithStreamingResponse", + "AsyncOrgsResourceWithStreamingResponse", +] diff --git a/src/dedalus_sdk/resources/orgs/orgs.py b/src/dedalus_sdk/resources/orgs/orgs.py new file mode 100644 index 0000000..ed577bb --- /dev/null +++ b/src/dedalus_sdk/resources/orgs/orgs.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["OrgsResource", "AsyncOrgsResource"] + + +class OrgsResource(SyncAPIResource): + @cached_property + def usage(self) -> UsageResource: + return UsageResource(self._client) + + @cached_property + def with_raw_response(self) -> OrgsResourceWithRawResponse: + """ + 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/dedalus-labs/dedalus-python#accessing-raw-response-data-eg-headers + """ + return OrgsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> OrgsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/dedalus-labs/dedalus-python#with_streaming_response + """ + return OrgsResourceWithStreamingResponse(self) + + +class AsyncOrgsResource(AsyncAPIResource): + @cached_property + def usage(self) -> AsyncUsageResource: + return AsyncUsageResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncOrgsResourceWithRawResponse: + """ + 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/dedalus-labs/dedalus-python#accessing-raw-response-data-eg-headers + """ + return AsyncOrgsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncOrgsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/dedalus-labs/dedalus-python#with_streaming_response + """ + return AsyncOrgsResourceWithStreamingResponse(self) + + +class OrgsResourceWithRawResponse: + def __init__(self, orgs: OrgsResource) -> None: + self._orgs = orgs + + @cached_property + def usage(self) -> UsageResourceWithRawResponse: + return UsageResourceWithRawResponse(self._orgs.usage) + + +class AsyncOrgsResourceWithRawResponse: + def __init__(self, orgs: AsyncOrgsResource) -> None: + self._orgs = orgs + + @cached_property + def usage(self) -> AsyncUsageResourceWithRawResponse: + return AsyncUsageResourceWithRawResponse(self._orgs.usage) + + +class OrgsResourceWithStreamingResponse: + def __init__(self, orgs: OrgsResource) -> None: + self._orgs = orgs + + @cached_property + def usage(self) -> UsageResourceWithStreamingResponse: + return UsageResourceWithStreamingResponse(self._orgs.usage) + + +class AsyncOrgsResourceWithStreamingResponse: + def __init__(self, orgs: AsyncOrgsResource) -> None: + self._orgs = orgs + + @cached_property + def usage(self) -> AsyncUsageResourceWithStreamingResponse: + return AsyncUsageResourceWithStreamingResponse(self._orgs.usage) diff --git a/src/dedalus_sdk/resources/orgs/usage.py b/src/dedalus_sdk/resources/orgs/usage.py new file mode 100644 index 0000000..dd9bf29 --- /dev/null +++ b/src/dedalus_sdk/resources/orgs/usage.py @@ -0,0 +1,427 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, 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 ...types.orgs import usage_retrieve_params, usage_get_machine_usage_params, usage_get_machine_storage_usage_params +from ..._base_client import make_request_options +from ...types.orgs.org_usage import OrgUsage +from ...types.orgs.machine_usage import MachineUsage +from ...types.orgs.machine_storage_usage import MachineStorageUsage + +__all__ = ["UsageResource", "AsyncUsageResource"] + + +class UsageResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> UsageResourceWithRawResponse: + """ + 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/dedalus-labs/dedalus-python#accessing-raw-response-data-eg-headers + """ + return UsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> UsageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/dedalus-labs/dedalus-python#with_streaming_response + """ + return UsageResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + org_id: str, + period_start: str | Omit = omit, + # 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, + ) -> OrgUsage: + """ + Get org billed machine usage + + Args: + period_start: Billing period start (YYYY-MM-DD). Defaults to first of current month. + + 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 org_id: + raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") + return self._get( + path_template("/v1/orgs/{org_id}/usage", org_id=org_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"period_start": period_start}, usage_retrieve_params.UsageRetrieveParams), + ), + cast_to=OrgUsage, + ) + + def get_machine_storage_usage( + self, + *, + org_id: str, + machine_id: str | Omit = omit, + period_end: str | Omit = omit, + period_start: str | Omit = omit, + # 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, + ) -> MachineStorageUsage: + """ + List machine storage usage evidence + + Args: + machine_id: Optional machine ID filter. + + period_end: Last UTC evidence date to include (YYYY-MM-DD). Defaults to current time. + + period_start: Evidence period start (YYYY-MM-DD). Defaults to first of current month. + + 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 org_id: + raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") + return self._get( + path_template("/v1/orgs/{org_id}/usage/storage/machines", org_id=org_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "machine_id": machine_id, + "period_end": period_end, + "period_start": period_start, + }, + usage_get_machine_storage_usage_params.UsageGetMachineStorageUsageParams, + ), + ), + cast_to=MachineStorageUsage, + ) + + def get_machine_usage( + self, + *, + org_id: str, + granularity: str | Omit = omit, + machine_id: str | Omit = omit, + period_end: str | Omit = omit, + period_start: str | Omit = omit, + # 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, + ) -> MachineUsage: + """ + List machine usage evidence + + Args: + granularity: Evidence granularity: hour or day. Defaults to hour. + + machine_id: Optional machine ID filter. + + period_end: Last UTC evidence date to include (YYYY-MM-DD). Defaults to current time. + + period_start: Evidence period start (YYYY-MM-DD). Defaults to first of current month. + + 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 org_id: + raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") + return self._get( + path_template("/v1/orgs/{org_id}/usage/machines", org_id=org_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "granularity": granularity, + "machine_id": machine_id, + "period_end": period_end, + "period_start": period_start, + }, + usage_get_machine_usage_params.UsageGetMachineUsageParams, + ), + ), + cast_to=MachineUsage, + ) + + +class AsyncUsageResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: + """ + 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/dedalus-labs/dedalus-python#accessing-raw-response-data-eg-headers + """ + return AsyncUsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/dedalus-labs/dedalus-python#with_streaming_response + """ + return AsyncUsageResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + org_id: str, + period_start: str | Omit = omit, + # 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, + ) -> OrgUsage: + """ + Get org billed machine usage + + Args: + period_start: Billing period start (YYYY-MM-DD). Defaults to first of current month. + + 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 org_id: + raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") + return await self._get( + path_template("/v1/orgs/{org_id}/usage", org_id=org_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"period_start": period_start}, usage_retrieve_params.UsageRetrieveParams + ), + ), + cast_to=OrgUsage, + ) + + async def get_machine_storage_usage( + self, + *, + org_id: str, + machine_id: str | Omit = omit, + period_end: str | Omit = omit, + period_start: str | Omit = omit, + # 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, + ) -> MachineStorageUsage: + """ + List machine storage usage evidence + + Args: + machine_id: Optional machine ID filter. + + period_end: Last UTC evidence date to include (YYYY-MM-DD). Defaults to current time. + + period_start: Evidence period start (YYYY-MM-DD). Defaults to first of current month. + + 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 org_id: + raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") + return await self._get( + path_template("/v1/orgs/{org_id}/usage/storage/machines", org_id=org_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "machine_id": machine_id, + "period_end": period_end, + "period_start": period_start, + }, + usage_get_machine_storage_usage_params.UsageGetMachineStorageUsageParams, + ), + ), + cast_to=MachineStorageUsage, + ) + + async def get_machine_usage( + self, + *, + org_id: str, + granularity: str | Omit = omit, + machine_id: str | Omit = omit, + period_end: str | Omit = omit, + period_start: str | Omit = omit, + # 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, + ) -> MachineUsage: + """ + List machine usage evidence + + Args: + granularity: Evidence granularity: hour or day. Defaults to hour. + + machine_id: Optional machine ID filter. + + period_end: Last UTC evidence date to include (YYYY-MM-DD). Defaults to current time. + + period_start: Evidence period start (YYYY-MM-DD). Defaults to first of current month. + + 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 org_id: + raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") + return await self._get( + path_template("/v1/orgs/{org_id}/usage/machines", org_id=org_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "granularity": granularity, + "machine_id": machine_id, + "period_end": period_end, + "period_start": period_start, + }, + usage_get_machine_usage_params.UsageGetMachineUsageParams, + ), + ), + cast_to=MachineUsage, + ) + + +class UsageResourceWithRawResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + self.retrieve = to_raw_response_wrapper( + usage.retrieve, + ) + self.get_machine_storage_usage = to_raw_response_wrapper( + usage.get_machine_storage_usage, + ) + self.get_machine_usage = to_raw_response_wrapper( + usage.get_machine_usage, + ) + + +class AsyncUsageResourceWithRawResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + self.retrieve = async_to_raw_response_wrapper( + usage.retrieve, + ) + self.get_machine_storage_usage = async_to_raw_response_wrapper( + usage.get_machine_storage_usage, + ) + self.get_machine_usage = async_to_raw_response_wrapper( + usage.get_machine_usage, + ) + + +class UsageResourceWithStreamingResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + self.retrieve = to_streamed_response_wrapper( + usage.retrieve, + ) + self.get_machine_storage_usage = to_streamed_response_wrapper( + usage.get_machine_storage_usage, + ) + self.get_machine_usage = to_streamed_response_wrapper( + usage.get_machine_usage, + ) + + +class AsyncUsageResourceWithStreamingResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + self.retrieve = async_to_streamed_response_wrapper( + usage.retrieve, + ) + self.get_machine_storage_usage = async_to_streamed_response_wrapper( + usage.get_machine_storage_usage, + ) + self.get_machine_usage = async_to_streamed_response_wrapper( + usage.get_machine_usage, + ) diff --git a/src/dedalus_sdk/types/machine.py b/src/dedalus_sdk/types/machine.py index 26ee71b..750a1c1 100644 --- a/src/dedalus_sdk/types/machine.py +++ b/src/dedalus_sdk/types/machine.py @@ -9,6 +9,9 @@ class Machine(BaseModel): + autosleep_seconds: int + """Seconds of inactivity before autosleep. 0 disables autosleep.""" + desired_state: Literal["running", "sleeping", "destroyed"] machine_id: str diff --git a/src/dedalus_sdk/types/machine_create_params.py b/src/dedalus_sdk/types/machine_create_params.py index ca95704..50df48b 100644 --- a/src/dedalus_sdk/types/machine_create_params.py +++ b/src/dedalus_sdk/types/machine_create_params.py @@ -16,3 +16,10 @@ class MachineCreateParams(TypedDict, total=False): vcpu: Required[float] """CPU in vCPUs.""" + + autosleep: str + """Idle window before autosleep. + + Accepts fixed duration units like 30s, 30m, 2h, 7d3h4s, or 1w3d, raw seconds + ("1800"), or never to disable. + """ diff --git a/src/dedalus_sdk/types/machine_list_item.py b/src/dedalus_sdk/types/machine_list_item.py index a2f236f..cb63899 100644 --- a/src/dedalus_sdk/types/machine_list_item.py +++ b/src/dedalus_sdk/types/machine_list_item.py @@ -10,6 +10,9 @@ class MachineListItem(BaseModel): + autosleep_seconds: int + """Seconds of inactivity before autosleep. 0 disables autosleep.""" + created_at: datetime desired_state: Literal["running", "sleeping", "destroyed"] diff --git a/src/dedalus_sdk/types/machine_update_params.py b/src/dedalus_sdk/types/machine_update_params.py index a7d36d7..90f5a35 100644 --- a/src/dedalus_sdk/types/machine_update_params.py +++ b/src/dedalus_sdk/types/machine_update_params.py @@ -2,9 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, Annotated, TypedDict - -from .._utils import PropertyInfo +from typing_extensions import Required, TypedDict __all__ = ["MachineUpdateParams"] @@ -12,7 +10,12 @@ class MachineUpdateParams(TypedDict, total=False): machine_id: Required[str] - if_match: Required[Annotated[str, PropertyInfo(alias="If-Match")]] + autosleep: str + """Idle window before autosleep. + + Accepts fixed duration units like 30s, 30m, 2h, 7d3h4s, or 1w3d, raw seconds + ("1800"), or never to disable. + """ memory_mib: int """Memory in MiB.""" diff --git a/src/dedalus_sdk/types/orgs/__init__.py b/src/dedalus_sdk/types/orgs/__init__.py new file mode 100644 index 0000000..d788a05 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/__init__.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .org_usage import OrgUsage as OrgUsage +from .machine_usage import MachineUsage as MachineUsage +from .machine_storage_usage import MachineStorageUsage as MachineStorageUsage +from .usage_retrieve_params import UsageRetrieveParams as UsageRetrieveParams +from .machine_usage_evidence import MachineUsageEvidence as MachineUsageEvidence +from .machine_storage_usage_evidence import MachineStorageUsageEvidence as MachineStorageUsageEvidence +from .usage_get_machine_usage_params import UsageGetMachineUsageParams as UsageGetMachineUsageParams +from .usage_get_machine_storage_usage_params import ( + UsageGetMachineStorageUsageParams as UsageGetMachineStorageUsageParams, +) diff --git a/src/dedalus_sdk/types/orgs/machine_storage_usage.py b/src/dedalus_sdk/types/orgs/machine_storage_usage.py new file mode 100644 index 0000000..60d25f4 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/machine_storage_usage.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime + +from ..._models import BaseModel +from .machine_storage_usage_evidence import MachineStorageUsageEvidence + +__all__ = ["MachineStorageUsage"] + + +class MachineStorageUsage(BaseModel): + period_end: datetime + """Exclusive evidence period end.""" + + period_start: datetime + """Inclusive evidence period start.""" + + rows: Optional[List[MachineStorageUsageEvidence]] = None + """Machine-level storage usage evidence rows.""" diff --git a/src/dedalus_sdk/types/orgs/machine_storage_usage_evidence.py b/src/dedalus_sdk/types/orgs/machine_storage_usage_evidence.py new file mode 100644 index 0000000..f38c2b2 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/machine_storage_usage_evidence.py @@ -0,0 +1,34 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["MachineStorageUsageEvidence"] + + +class MachineStorageUsageEvidence(BaseModel): + bucket_end: datetime + """Exclusive evidence bucket end.""" + + bucket_start: datetime + """Inclusive evidence bucket start.""" + + logical_storage_bytes: int + """Machine logical bytes observed for storage allocation.""" + + machine_id: str + """Machine identifier.""" + + org_metering_bucket_id: str + """Org storage bucket ID this evidence row contributes to.""" + + storage_mib_seconds: int + """Allocated logical MiB-seconds for this machine.""" + + stripe_storage_identifier: str + """Stripe storage meter event identifier linked to that org bucket.""" + + latest_stripe_emitted_at: Optional[datetime] = None + """Latest Stripe emission timestamp for the linked org bucket, when emitted.""" diff --git a/src/dedalus_sdk/types/orgs/machine_usage.py b/src/dedalus_sdk/types/orgs/machine_usage.py new file mode 100644 index 0000000..0f40345 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/machine_usage.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime + +from ..._models import BaseModel +from .machine_usage_evidence import MachineUsageEvidence + +__all__ = ["MachineUsage"] + + +class MachineUsage(BaseModel): + granularity: str + """Evidence granularity used for rows: hour or day.""" + + period_end: datetime + """Exclusive evidence period end.""" + + period_start: datetime + """Inclusive evidence period start.""" + + rows: Optional[List[MachineUsageEvidence]] = None + """Machine-level usage evidence rows.""" diff --git a/src/dedalus_sdk/types/orgs/machine_usage_evidence.py b/src/dedalus_sdk/types/orgs/machine_usage_evidence.py new file mode 100644 index 0000000..805d147 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/machine_usage_evidence.py @@ -0,0 +1,58 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["MachineUsageEvidence"] + + +class MachineUsageEvidence(BaseModel): + awake_seconds: int + """Machine-awake seconds in this bucket.""" + + bucket_end: datetime + """Exclusive evidence bucket end.""" + + bucket_start: datetime + """Inclusive evidence bucket start.""" + + cpu_millicore_seconds: int + """Requested vCPU millicores multiplied by active CPU seconds.""" + + last_window_end: datetime + """Latest raw window_end represented by this row.""" + + machine_id: str + """Machine identifier.""" + + memory_mib_seconds: int + """Requested memory MiB multiplied by awake seconds.""" + + org_metering_bucket_ids: Optional[List[str]] = None + """Org compute bucket IDs this evidence row contributes to.""" + + requested_memory_mib: int + """Requested memory for this shape, in MiB.""" + + requested_storage_gib: int + """Requested storage for this shape, in GiB.""" + + requested_vcpu: float + """Requested vCPU for this shape.""" + + spec_fingerprint: str + """Stable fingerprint for the requested machine shape.""" + + stripe_cpu_identifiers: Optional[List[str]] = None + """Stripe CPU meter event identifiers linked to those org buckets.""" + + stripe_memory_identifiers: Optional[List[str]] = None + """Stripe memory meter event identifiers linked to those org buckets.""" + + window_count: int + """Raw usage windows compacted into this evidence row.""" + + latest_stripe_emitted_at: Optional[datetime] = None + """Latest Stripe emission timestamp for linked org buckets, when emitted.""" diff --git a/src/dedalus_sdk/types/orgs/org_usage.py b/src/dedalus_sdk/types/orgs/org_usage.py new file mode 100644 index 0000000..d61ee23 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/org_usage.py @@ -0,0 +1,34 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["OrgUsage"] + + +class OrgUsage(BaseModel): + billed_awake_seconds: int + """Closed awake seconds in billed org buckets for the period.""" + + billed_cpu_millicore_seconds: int + """ + Closed requested vCPU millicores multiplied by active CPU seconds for the + period. + """ + + billed_logical_storage_mib_seconds: int + """ + Closed billable logical MiB-seconds for the period, matching the Stripe storage + meter. + """ + + billed_memory_mib_seconds: int + """Closed requested memory MiB multiplied by awake seconds for the period.""" + + included_storage_gib: int + """Plan-included storage in GiB, used as a local guardrail only.""" + + plan_slug: str + """Billing plan in effect for the organization.""" + + provisioned_storage_gib: int + """Current provisioned storage summed across machines in GiB.""" diff --git a/src/dedalus_sdk/types/orgs/usage_get_machine_storage_usage_params.py b/src/dedalus_sdk/types/orgs/usage_get_machine_storage_usage_params.py new file mode 100644 index 0000000..1e8b263 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/usage_get_machine_storage_usage_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["UsageGetMachineStorageUsageParams"] + + +class UsageGetMachineStorageUsageParams(TypedDict, total=False): + org_id: Required[str] + + machine_id: str + """Optional machine ID filter.""" + + period_end: str + """Last UTC evidence date to include (YYYY-MM-DD). Defaults to current time.""" + + period_start: str + """Evidence period start (YYYY-MM-DD). Defaults to first of current month.""" diff --git a/src/dedalus_sdk/types/orgs/usage_get_machine_usage_params.py b/src/dedalus_sdk/types/orgs/usage_get_machine_usage_params.py new file mode 100644 index 0000000..bafc90c --- /dev/null +++ b/src/dedalus_sdk/types/orgs/usage_get_machine_usage_params.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["UsageGetMachineUsageParams"] + + +class UsageGetMachineUsageParams(TypedDict, total=False): + org_id: Required[str] + + granularity: str + """Evidence granularity: hour or day. Defaults to hour.""" + + machine_id: str + """Optional machine ID filter.""" + + period_end: str + """Last UTC evidence date to include (YYYY-MM-DD). Defaults to current time.""" + + period_start: str + """Evidence period start (YYYY-MM-DD). Defaults to first of current month.""" diff --git a/src/dedalus_sdk/types/orgs/usage_retrieve_params.py b/src/dedalus_sdk/types/orgs/usage_retrieve_params.py new file mode 100644 index 0000000..429b805 --- /dev/null +++ b/src/dedalus_sdk/types/orgs/usage_retrieve_params.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["UsageRetrieveParams"] + + +class UsageRetrieveParams(TypedDict, total=False): + org_id: Required[str] + + period_start: str + """Billing period start (YYYY-MM-DD). Defaults to first of current month.""" diff --git a/tests/api_resources/machines/test_artifacts.py b/tests/api_resources/machines/test_artifacts.py index d57de2f..b4b6ff8 100644 --- a/tests/api_resources/machines/test_artifacts.py +++ b/tests/api_resources/machines/test_artifacts.py @@ -21,7 +21,7 @@ class TestArtifacts: @parametrize def test_method_retrieve(self, client: Dedalus) -> None: artifact = client.machines.artifacts.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) assert_matches_type(Artifact, artifact, path=["response"]) @@ -29,7 +29,7 @@ def test_method_retrieve(self, client: Dedalus) -> None: @parametrize def test_raw_response_retrieve(self, client: Dedalus) -> None: response = client.machines.artifacts.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) @@ -41,7 +41,7 @@ def test_raw_response_retrieve(self, client: Dedalus) -> None: @parametrize def test_streaming_response_retrieve(self, client: Dedalus) -> None: with client.machines.artifacts.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) as response: assert not response.is_closed @@ -62,21 +62,21 @@ def test_path_params_retrieve(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_id` but received ''"): client.machines.artifacts.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="", ) @parametrize def test_method_list(self, client: Dedalus) -> None: artifact = client.machines.artifacts.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(SyncCursorPage[Artifact], artifact, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Dedalus) -> None: artifact = client.machines.artifacts.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -85,7 +85,7 @@ def test_method_list_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_list(self, client: Dedalus) -> None: response = client.machines.artifacts.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -96,7 +96,7 @@ def test_raw_response_list(self, client: Dedalus) -> None: @parametrize def test_streaming_response_list(self, client: Dedalus) -> None: with client.machines.artifacts.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -116,7 +116,7 @@ def test_path_params_list(self, client: Dedalus) -> None: @parametrize def test_method_delete(self, client: Dedalus) -> None: artifact = client.machines.artifacts.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) assert_matches_type(Artifact, artifact, path=["response"]) @@ -124,7 +124,7 @@ def test_method_delete(self, client: Dedalus) -> None: @parametrize def test_raw_response_delete(self, client: Dedalus) -> None: response = client.machines.artifacts.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) @@ -136,7 +136,7 @@ def test_raw_response_delete(self, client: Dedalus) -> None: @parametrize def test_streaming_response_delete(self, client: Dedalus) -> None: with client.machines.artifacts.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) as response: assert not response.is_closed @@ -157,7 +157,7 @@ def test_path_params_delete(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_id` but received ''"): client.machines.artifacts.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="", ) @@ -170,7 +170,7 @@ class TestAsyncArtifacts: @parametrize async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: artifact = await async_client.machines.artifacts.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) assert_matches_type(Artifact, artifact, path=["response"]) @@ -178,7 +178,7 @@ async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.artifacts.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) @@ -190,7 +190,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: async with async_client.machines.artifacts.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) as response: assert not response.is_closed @@ -211,21 +211,21 @@ async def test_path_params_retrieve(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_id` but received ''"): await async_client.machines.artifacts.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", artifact_id="", ) @parametrize async def test_method_list(self, async_client: AsyncDedalus) -> None: artifact = await async_client.machines.artifacts.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(AsyncCursorPage[Artifact], artifact, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> None: artifact = await async_client.machines.artifacts.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -234,7 +234,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> @parametrize async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.artifacts.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -245,7 +245,7 @@ async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: async with async_client.machines.artifacts.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -265,7 +265,7 @@ async def test_path_params_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_delete(self, async_client: AsyncDedalus) -> None: artifact = await async_client.machines.artifacts.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) assert_matches_type(Artifact, artifact, path=["response"]) @@ -273,7 +273,7 @@ async def test_method_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.artifacts.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) @@ -285,7 +285,7 @@ async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: async with async_client.machines.artifacts.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="artifact_id", ) as response: assert not response.is_closed @@ -306,6 +306,6 @@ async def test_path_params_delete(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `artifact_id` but received ''"): await async_client.machines.artifacts.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", artifact_id="", ) diff --git a/tests/api_resources/machines/test_executions.py b/tests/api_resources/machines/test_executions.py index 37fb085..85091f9 100644 --- a/tests/api_resources/machines/test_executions.py +++ b/tests/api_resources/machines/test_executions.py @@ -25,7 +25,7 @@ class TestExecutions: @parametrize def test_method_create(self, client: Dedalus) -> None: execution = client.machines.executions.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], ) assert_matches_type(Execution, execution, path=["response"]) @@ -33,7 +33,7 @@ def test_method_create(self, client: Dedalus) -> None: @parametrize def test_method_create_with_all_params(self, client: Dedalus) -> None: execution = client.machines.executions.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], cwd="cwd", env={"foo": "string"}, @@ -45,7 +45,7 @@ def test_method_create_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_create(self, client: Dedalus) -> None: response = client.machines.executions.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], ) @@ -57,7 +57,7 @@ def test_raw_response_create(self, client: Dedalus) -> None: @parametrize def test_streaming_response_create(self, client: Dedalus) -> None: with client.machines.executions.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], ) as response: assert not response.is_closed @@ -79,7 +79,7 @@ def test_path_params_create(self, client: Dedalus) -> None: @parametrize def test_method_retrieve(self, client: Dedalus) -> None: execution = client.machines.executions.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(Execution, execution, path=["response"]) @@ -87,7 +87,7 @@ def test_method_retrieve(self, client: Dedalus) -> None: @parametrize def test_raw_response_retrieve(self, client: Dedalus) -> None: response = client.machines.executions.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -99,7 +99,7 @@ def test_raw_response_retrieve(self, client: Dedalus) -> None: @parametrize def test_streaming_response_retrieve(self, client: Dedalus) -> None: with client.machines.executions.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -120,21 +120,21 @@ def test_path_params_retrieve(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): client.machines.executions.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) @parametrize def test_method_list(self, client: Dedalus) -> None: execution = client.machines.executions.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(SyncCursorPage[Execution], execution, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Dedalus) -> None: execution = client.machines.executions.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -143,7 +143,7 @@ def test_method_list_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_list(self, client: Dedalus) -> None: response = client.machines.executions.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -154,7 +154,7 @@ def test_raw_response_list(self, client: Dedalus) -> None: @parametrize def test_streaming_response_list(self, client: Dedalus) -> None: with client.machines.executions.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -174,7 +174,7 @@ def test_path_params_list(self, client: Dedalus) -> None: @parametrize def test_method_delete(self, client: Dedalus) -> None: execution = client.machines.executions.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(Execution, execution, path=["response"]) @@ -182,7 +182,7 @@ def test_method_delete(self, client: Dedalus) -> None: @parametrize def test_raw_response_delete(self, client: Dedalus) -> None: response = client.machines.executions.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -194,7 +194,7 @@ def test_raw_response_delete(self, client: Dedalus) -> None: @parametrize def test_streaming_response_delete(self, client: Dedalus) -> None: with client.machines.executions.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -215,14 +215,14 @@ def test_path_params_delete(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): client.machines.executions.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) @parametrize def test_method_events(self, client: Dedalus) -> None: execution = client.machines.executions.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(SyncCursorPage[ExecutionEvent], execution, path=["response"]) @@ -230,7 +230,7 @@ def test_method_events(self, client: Dedalus) -> None: @parametrize def test_method_events_with_all_params(self, client: Dedalus) -> None: execution = client.machines.executions.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", cursor="cursor", limit=0, @@ -240,7 +240,7 @@ def test_method_events_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_events(self, client: Dedalus) -> None: response = client.machines.executions.with_raw_response.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -252,7 +252,7 @@ def test_raw_response_events(self, client: Dedalus) -> None: @parametrize def test_streaming_response_events(self, client: Dedalus) -> None: with client.machines.executions.with_streaming_response.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -273,14 +273,14 @@ def test_path_params_events(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): client.machines.executions.with_raw_response.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) @parametrize def test_method_output(self, client: Dedalus) -> None: execution = client.machines.executions.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(ExecutionOutput, execution, path=["response"]) @@ -288,7 +288,7 @@ def test_method_output(self, client: Dedalus) -> None: @parametrize def test_raw_response_output(self, client: Dedalus) -> None: response = client.machines.executions.with_raw_response.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -300,7 +300,7 @@ def test_raw_response_output(self, client: Dedalus) -> None: @parametrize def test_streaming_response_output(self, client: Dedalus) -> None: with client.machines.executions.with_streaming_response.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -321,7 +321,7 @@ def test_path_params_output(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): client.machines.executions.with_raw_response.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) @@ -334,7 +334,7 @@ class TestAsyncExecutions: @parametrize async def test_method_create(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], ) assert_matches_type(Execution, execution, path=["response"]) @@ -342,7 +342,7 @@ async def test_method_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], cwd="cwd", env={"foo": "string"}, @@ -354,7 +354,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncDedalus) - @parametrize async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.executions.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], ) @@ -366,7 +366,7 @@ async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncDedalus) -> None: async with async_client.machines.executions.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", command=["string"], ) as response: assert not response.is_closed @@ -388,7 +388,7 @@ async def test_path_params_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(Execution, execution, path=["response"]) @@ -396,7 +396,7 @@ async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.executions.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -408,7 +408,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: async with async_client.machines.executions.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -429,21 +429,21 @@ async def test_path_params_retrieve(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): await async_client.machines.executions.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) @parametrize async def test_method_list(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(AsyncCursorPage[Execution], execution, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -452,7 +452,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> @parametrize async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.executions.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -463,7 +463,7 @@ async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: async with async_client.machines.executions.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -483,7 +483,7 @@ async def test_path_params_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_delete(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(Execution, execution, path=["response"]) @@ -491,7 +491,7 @@ async def test_method_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.executions.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -503,7 +503,7 @@ async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: async with async_client.machines.executions.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -524,14 +524,14 @@ async def test_path_params_delete(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): await async_client.machines.executions.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) @parametrize async def test_method_events(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(AsyncCursorPage[ExecutionEvent], execution, path=["response"]) @@ -539,7 +539,7 @@ async def test_method_events(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_events_with_all_params(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", cursor="cursor", limit=0, @@ -549,7 +549,7 @@ async def test_method_events_with_all_params(self, async_client: AsyncDedalus) - @parametrize async def test_raw_response_events(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.executions.with_raw_response.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -561,7 +561,7 @@ async def test_raw_response_events(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_events(self, async_client: AsyncDedalus) -> None: async with async_client.machines.executions.with_streaming_response.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -582,14 +582,14 @@ async def test_path_params_events(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): await async_client.machines.executions.with_raw_response.events( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) @parametrize async def test_method_output(self, async_client: AsyncDedalus) -> None: execution = await async_client.machines.executions.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) assert_matches_type(ExecutionOutput, execution, path=["response"]) @@ -597,7 +597,7 @@ async def test_method_output(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_output(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.executions.with_raw_response.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) @@ -609,7 +609,7 @@ async def test_raw_response_output(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_output(self, async_client: AsyncDedalus) -> None: async with async_client.machines.executions.with_streaming_response.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="execution_id", ) as response: assert not response.is_closed @@ -630,6 +630,6 @@ async def test_path_params_output(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `execution_id` but received ''"): await async_client.machines.executions.with_raw_response.output( - machine_id="machine_id", + machine_id="dm-3", execution_id="", ) diff --git a/tests/api_resources/machines/test_previews.py b/tests/api_resources/machines/test_previews.py index d804571..271bac0 100644 --- a/tests/api_resources/machines/test_previews.py +++ b/tests/api_resources/machines/test_previews.py @@ -21,7 +21,7 @@ class TestPreviews: @parametrize def test_method_create(self, client: Dedalus) -> None: preview = client.machines.previews.create( - machine_id="machine_id", + machine_id="dm-3", port=0, ) assert_matches_type(Preview, preview, path=["response"]) @@ -29,7 +29,7 @@ def test_method_create(self, client: Dedalus) -> None: @parametrize def test_method_create_with_all_params(self, client: Dedalus) -> None: preview = client.machines.previews.create( - machine_id="machine_id", + machine_id="dm-3", port=0, protocol="http", visibility="public", @@ -39,7 +39,7 @@ def test_method_create_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_create(self, client: Dedalus) -> None: response = client.machines.previews.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", port=0, ) @@ -51,7 +51,7 @@ def test_raw_response_create(self, client: Dedalus) -> None: @parametrize def test_streaming_response_create(self, client: Dedalus) -> None: with client.machines.previews.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", port=0, ) as response: assert not response.is_closed @@ -73,7 +73,7 @@ def test_path_params_create(self, client: Dedalus) -> None: @parametrize def test_method_retrieve(self, client: Dedalus) -> None: preview = client.machines.previews.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) assert_matches_type(Preview, preview, path=["response"]) @@ -81,7 +81,7 @@ def test_method_retrieve(self, client: Dedalus) -> None: @parametrize def test_raw_response_retrieve(self, client: Dedalus) -> None: response = client.machines.previews.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) @@ -93,7 +93,7 @@ def test_raw_response_retrieve(self, client: Dedalus) -> None: @parametrize def test_streaming_response_retrieve(self, client: Dedalus) -> None: with client.machines.previews.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) as response: assert not response.is_closed @@ -114,21 +114,21 @@ def test_path_params_retrieve(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `preview_id` but received ''"): client.machines.previews.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="", ) @parametrize def test_method_list(self, client: Dedalus) -> None: preview = client.machines.previews.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(SyncCursorPage[Preview], preview, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Dedalus) -> None: preview = client.machines.previews.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -137,7 +137,7 @@ def test_method_list_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_list(self, client: Dedalus) -> None: response = client.machines.previews.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -148,7 +148,7 @@ def test_raw_response_list(self, client: Dedalus) -> None: @parametrize def test_streaming_response_list(self, client: Dedalus) -> None: with client.machines.previews.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -168,7 +168,7 @@ def test_path_params_list(self, client: Dedalus) -> None: @parametrize def test_method_delete(self, client: Dedalus) -> None: preview = client.machines.previews.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) assert_matches_type(Preview, preview, path=["response"]) @@ -176,7 +176,7 @@ def test_method_delete(self, client: Dedalus) -> None: @parametrize def test_raw_response_delete(self, client: Dedalus) -> None: response = client.machines.previews.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) @@ -188,7 +188,7 @@ def test_raw_response_delete(self, client: Dedalus) -> None: @parametrize def test_streaming_response_delete(self, client: Dedalus) -> None: with client.machines.previews.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) as response: assert not response.is_closed @@ -209,7 +209,7 @@ def test_path_params_delete(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `preview_id` but received ''"): client.machines.previews.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="", ) @@ -222,7 +222,7 @@ class TestAsyncPreviews: @parametrize async def test_method_create(self, async_client: AsyncDedalus) -> None: preview = await async_client.machines.previews.create( - machine_id="machine_id", + machine_id="dm-3", port=0, ) assert_matches_type(Preview, preview, path=["response"]) @@ -230,7 +230,7 @@ async def test_method_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncDedalus) -> None: preview = await async_client.machines.previews.create( - machine_id="machine_id", + machine_id="dm-3", port=0, protocol="http", visibility="public", @@ -240,7 +240,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncDedalus) - @parametrize async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.previews.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", port=0, ) @@ -252,7 +252,7 @@ async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncDedalus) -> None: async with async_client.machines.previews.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", port=0, ) as response: assert not response.is_closed @@ -274,7 +274,7 @@ async def test_path_params_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: preview = await async_client.machines.previews.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) assert_matches_type(Preview, preview, path=["response"]) @@ -282,7 +282,7 @@ async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.previews.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) @@ -294,7 +294,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: async with async_client.machines.previews.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) as response: assert not response.is_closed @@ -315,21 +315,21 @@ async def test_path_params_retrieve(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `preview_id` but received ''"): await async_client.machines.previews.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", preview_id="", ) @parametrize async def test_method_list(self, async_client: AsyncDedalus) -> None: preview = await async_client.machines.previews.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(AsyncCursorPage[Preview], preview, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> None: preview = await async_client.machines.previews.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -338,7 +338,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> @parametrize async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.previews.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -349,7 +349,7 @@ async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: async with async_client.machines.previews.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -369,7 +369,7 @@ async def test_path_params_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_delete(self, async_client: AsyncDedalus) -> None: preview = await async_client.machines.previews.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) assert_matches_type(Preview, preview, path=["response"]) @@ -377,7 +377,7 @@ async def test_method_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.previews.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) @@ -389,7 +389,7 @@ async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: async with async_client.machines.previews.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="preview_id", ) as response: assert not response.is_closed @@ -410,6 +410,6 @@ async def test_path_params_delete(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `preview_id` but received ''"): await async_client.machines.previews.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", preview_id="", ) diff --git a/tests/api_resources/machines/test_ssh.py b/tests/api_resources/machines/test_ssh.py index ecba31f..fc6e80c 100644 --- a/tests/api_resources/machines/test_ssh.py +++ b/tests/api_resources/machines/test_ssh.py @@ -21,7 +21,7 @@ class TestSSH: @parametrize def test_method_create(self, client: Dedalus) -> None: ssh = client.machines.ssh.create( - machine_id="machine_id", + machine_id="dm-3", public_key="public_key", ) assert_matches_type(SSHSession, ssh, path=["response"]) @@ -29,7 +29,7 @@ def test_method_create(self, client: Dedalus) -> None: @parametrize def test_raw_response_create(self, client: Dedalus) -> None: response = client.machines.ssh.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", public_key="public_key", ) @@ -41,7 +41,7 @@ def test_raw_response_create(self, client: Dedalus) -> None: @parametrize def test_streaming_response_create(self, client: Dedalus) -> None: with client.machines.ssh.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", public_key="public_key", ) as response: assert not response.is_closed @@ -63,7 +63,7 @@ def test_path_params_create(self, client: Dedalus) -> None: @parametrize def test_method_retrieve(self, client: Dedalus) -> None: ssh = client.machines.ssh.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) assert_matches_type(SSHSession, ssh, path=["response"]) @@ -71,7 +71,7 @@ def test_method_retrieve(self, client: Dedalus) -> None: @parametrize def test_raw_response_retrieve(self, client: Dedalus) -> None: response = client.machines.ssh.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) @@ -83,7 +83,7 @@ def test_raw_response_retrieve(self, client: Dedalus) -> None: @parametrize def test_streaming_response_retrieve(self, client: Dedalus) -> None: with client.machines.ssh.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) as response: assert not response.is_closed @@ -104,21 +104,21 @@ def test_path_params_retrieve(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): client.machines.ssh.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="", ) @parametrize def test_method_list(self, client: Dedalus) -> None: ssh = client.machines.ssh.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(SyncCursorPage[SSHSession], ssh, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Dedalus) -> None: ssh = client.machines.ssh.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -127,7 +127,7 @@ def test_method_list_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_list(self, client: Dedalus) -> None: response = client.machines.ssh.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -138,7 +138,7 @@ def test_raw_response_list(self, client: Dedalus) -> None: @parametrize def test_streaming_response_list(self, client: Dedalus) -> None: with client.machines.ssh.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -158,7 +158,7 @@ def test_path_params_list(self, client: Dedalus) -> None: @parametrize def test_method_delete(self, client: Dedalus) -> None: ssh = client.machines.ssh.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) assert_matches_type(SSHSession, ssh, path=["response"]) @@ -166,7 +166,7 @@ def test_method_delete(self, client: Dedalus) -> None: @parametrize def test_raw_response_delete(self, client: Dedalus) -> None: response = client.machines.ssh.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) @@ -178,7 +178,7 @@ def test_raw_response_delete(self, client: Dedalus) -> None: @parametrize def test_streaming_response_delete(self, client: Dedalus) -> None: with client.machines.ssh.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) as response: assert not response.is_closed @@ -199,7 +199,7 @@ def test_path_params_delete(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): client.machines.ssh.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="", ) @@ -212,7 +212,7 @@ class TestAsyncSSH: @parametrize async def test_method_create(self, async_client: AsyncDedalus) -> None: ssh = await async_client.machines.ssh.create( - machine_id="machine_id", + machine_id="dm-3", public_key="public_key", ) assert_matches_type(SSHSession, ssh, path=["response"]) @@ -220,7 +220,7 @@ async def test_method_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.ssh.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", public_key="public_key", ) @@ -232,7 +232,7 @@ async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncDedalus) -> None: async with async_client.machines.ssh.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", public_key="public_key", ) as response: assert not response.is_closed @@ -254,7 +254,7 @@ async def test_path_params_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: ssh = await async_client.machines.ssh.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) assert_matches_type(SSHSession, ssh, path=["response"]) @@ -262,7 +262,7 @@ async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.ssh.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) @@ -274,7 +274,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: async with async_client.machines.ssh.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) as response: assert not response.is_closed @@ -295,21 +295,21 @@ async def test_path_params_retrieve(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): await async_client.machines.ssh.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", session_id="", ) @parametrize async def test_method_list(self, async_client: AsyncDedalus) -> None: ssh = await async_client.machines.ssh.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(AsyncCursorPage[SSHSession], ssh, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> None: ssh = await async_client.machines.ssh.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -318,7 +318,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> @parametrize async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.ssh.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -329,7 +329,7 @@ async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: async with async_client.machines.ssh.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -349,7 +349,7 @@ async def test_path_params_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_delete(self, async_client: AsyncDedalus) -> None: ssh = await async_client.machines.ssh.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) assert_matches_type(SSHSession, ssh, path=["response"]) @@ -357,7 +357,7 @@ async def test_method_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.ssh.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) @@ -369,7 +369,7 @@ async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: async with async_client.machines.ssh.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="session_id", ) as response: assert not response.is_closed @@ -390,6 +390,6 @@ async def test_path_params_delete(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): await async_client.machines.ssh.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", session_id="", ) diff --git a/tests/api_resources/machines/test_terminals.py b/tests/api_resources/machines/test_terminals.py index 47e3aaa..ceacabc 100644 --- a/tests/api_resources/machines/test_terminals.py +++ b/tests/api_resources/machines/test_terminals.py @@ -21,7 +21,7 @@ class TestTerminals: @parametrize def test_method_create(self, client: Dedalus) -> None: terminal = client.machines.terminals.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, ) @@ -30,7 +30,7 @@ def test_method_create(self, client: Dedalus) -> None: @parametrize def test_method_create_with_all_params(self, client: Dedalus) -> None: terminal = client.machines.terminals.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, cwd="cwd", @@ -42,7 +42,7 @@ def test_method_create_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_create(self, client: Dedalus) -> None: response = client.machines.terminals.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, ) @@ -55,7 +55,7 @@ def test_raw_response_create(self, client: Dedalus) -> None: @parametrize def test_streaming_response_create(self, client: Dedalus) -> None: with client.machines.terminals.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, ) as response: @@ -79,7 +79,7 @@ def test_path_params_create(self, client: Dedalus) -> None: @parametrize def test_method_retrieve(self, client: Dedalus) -> None: terminal = client.machines.terminals.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) assert_matches_type(Terminal, terminal, path=["response"]) @@ -87,7 +87,7 @@ def test_method_retrieve(self, client: Dedalus) -> None: @parametrize def test_raw_response_retrieve(self, client: Dedalus) -> None: response = client.machines.terminals.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) @@ -99,7 +99,7 @@ def test_raw_response_retrieve(self, client: Dedalus) -> None: @parametrize def test_streaming_response_retrieve(self, client: Dedalus) -> None: with client.machines.terminals.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) as response: assert not response.is_closed @@ -120,21 +120,21 @@ def test_path_params_retrieve(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `terminal_id` but received ''"): client.machines.terminals.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="", ) @parametrize def test_method_list(self, client: Dedalus) -> None: terminal = client.machines.terminals.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(SyncCursorPage[Terminal], terminal, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Dedalus) -> None: terminal = client.machines.terminals.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -143,7 +143,7 @@ def test_method_list_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_list(self, client: Dedalus) -> None: response = client.machines.terminals.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -154,7 +154,7 @@ def test_raw_response_list(self, client: Dedalus) -> None: @parametrize def test_streaming_response_list(self, client: Dedalus) -> None: with client.machines.terminals.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -174,7 +174,7 @@ def test_path_params_list(self, client: Dedalus) -> None: @parametrize def test_method_delete(self, client: Dedalus) -> None: terminal = client.machines.terminals.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) assert_matches_type(Terminal, terminal, path=["response"]) @@ -182,7 +182,7 @@ def test_method_delete(self, client: Dedalus) -> None: @parametrize def test_raw_response_delete(self, client: Dedalus) -> None: response = client.machines.terminals.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) @@ -194,7 +194,7 @@ def test_raw_response_delete(self, client: Dedalus) -> None: @parametrize def test_streaming_response_delete(self, client: Dedalus) -> None: with client.machines.terminals.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) as response: assert not response.is_closed @@ -215,7 +215,7 @@ def test_path_params_delete(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `terminal_id` but received ''"): client.machines.terminals.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="", ) @@ -228,7 +228,7 @@ class TestAsyncTerminals: @parametrize async def test_method_create(self, async_client: AsyncDedalus) -> None: terminal = await async_client.machines.terminals.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, ) @@ -237,7 +237,7 @@ async def test_method_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncDedalus) -> None: terminal = await async_client.machines.terminals.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, cwd="cwd", @@ -249,7 +249,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncDedalus) - @parametrize async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.terminals.with_raw_response.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, ) @@ -262,7 +262,7 @@ async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncDedalus) -> None: async with async_client.machines.terminals.with_streaming_response.create( - machine_id="machine_id", + machine_id="dm-3", height=0, width=0, ) as response: @@ -286,7 +286,7 @@ async def test_path_params_create(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: terminal = await async_client.machines.terminals.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) assert_matches_type(Terminal, terminal, path=["response"]) @@ -294,7 +294,7 @@ async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.terminals.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) @@ -306,7 +306,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: async with async_client.machines.terminals.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) as response: assert not response.is_closed @@ -327,21 +327,21 @@ async def test_path_params_retrieve(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `terminal_id` but received ''"): await async_client.machines.terminals.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", terminal_id="", ) @parametrize async def test_method_list(self, async_client: AsyncDedalus) -> None: terminal = await async_client.machines.terminals.list( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(AsyncCursorPage[Terminal], terminal, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> None: terminal = await async_client.machines.terminals.list( - machine_id="machine_id", + machine_id="dm-3", cursor="cursor", limit=0, ) @@ -350,7 +350,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> @parametrize async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.terminals.with_raw_response.list( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -361,7 +361,7 @@ async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: async with async_client.machines.terminals.with_streaming_response.list( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -381,7 +381,7 @@ async def test_path_params_list(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_delete(self, async_client: AsyncDedalus) -> None: terminal = await async_client.machines.terminals.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) assert_matches_type(Terminal, terminal, path=["response"]) @@ -389,7 +389,7 @@ async def test_method_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.terminals.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) @@ -401,7 +401,7 @@ async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: async with async_client.machines.terminals.with_streaming_response.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="terminal_id", ) as response: assert not response.is_closed @@ -422,6 +422,6 @@ async def test_path_params_delete(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `terminal_id` but received ''"): await async_client.machines.terminals.with_raw_response.delete( - machine_id="machine_id", + machine_id="dm-3", terminal_id="", ) diff --git a/tests/api_resources/orgs/__init__.py b/tests/api_resources/orgs/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/orgs/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/orgs/test_usage.py b/tests/api_resources/orgs/test_usage.py new file mode 100644 index 0000000..1d6d9d1 --- /dev/null +++ b/tests/api_resources/orgs/test_usage.py @@ -0,0 +1,314 @@ +# 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 dedalus_sdk import Dedalus, AsyncDedalus +from tests.utils import assert_matches_type +from dedalus_sdk.types.orgs import ( + OrgUsage, + MachineUsage, + MachineStorageUsage, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestUsage: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: Dedalus) -> None: + usage = client.orgs.usage.retrieve( + org_id="org_id", + ) + assert_matches_type(OrgUsage, usage, path=["response"]) + + @parametrize + def test_method_retrieve_with_all_params(self, client: Dedalus) -> None: + usage = client.orgs.usage.retrieve( + org_id="org_id", + period_start="period_start", + ) + assert_matches_type(OrgUsage, usage, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Dedalus) -> None: + response = client.orgs.usage.with_raw_response.retrieve( + org_id="org_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = response.parse() + assert_matches_type(OrgUsage, usage, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Dedalus) -> None: + with client.orgs.usage.with_streaming_response.retrieve( + org_id="org_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = response.parse() + assert_matches_type(OrgUsage, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Dedalus) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `org_id` but received ''"): + client.orgs.usage.with_raw_response.retrieve( + org_id="", + ) + + @parametrize + def test_method_get_machine_storage_usage(self, client: Dedalus) -> None: + usage = client.orgs.usage.get_machine_storage_usage( + org_id="org_id", + ) + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + @parametrize + def test_method_get_machine_storage_usage_with_all_params(self, client: Dedalus) -> None: + usage = client.orgs.usage.get_machine_storage_usage( + org_id="org_id", + machine_id="machine_id", + period_end="period_end", + period_start="period_start", + ) + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + @parametrize + def test_raw_response_get_machine_storage_usage(self, client: Dedalus) -> None: + response = client.orgs.usage.with_raw_response.get_machine_storage_usage( + org_id="org_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = response.parse() + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + @parametrize + def test_streaming_response_get_machine_storage_usage(self, client: Dedalus) -> None: + with client.orgs.usage.with_streaming_response.get_machine_storage_usage( + org_id="org_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = response.parse() + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get_machine_storage_usage(self, client: Dedalus) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `org_id` but received ''"): + client.orgs.usage.with_raw_response.get_machine_storage_usage( + org_id="", + ) + + @parametrize + def test_method_get_machine_usage(self, client: Dedalus) -> None: + usage = client.orgs.usage.get_machine_usage( + org_id="org_id", + ) + assert_matches_type(MachineUsage, usage, path=["response"]) + + @parametrize + def test_method_get_machine_usage_with_all_params(self, client: Dedalus) -> None: + usage = client.orgs.usage.get_machine_usage( + org_id="org_id", + granularity="granularity", + machine_id="machine_id", + period_end="period_end", + period_start="period_start", + ) + assert_matches_type(MachineUsage, usage, path=["response"]) + + @parametrize + def test_raw_response_get_machine_usage(self, client: Dedalus) -> None: + response = client.orgs.usage.with_raw_response.get_machine_usage( + org_id="org_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = response.parse() + assert_matches_type(MachineUsage, usage, path=["response"]) + + @parametrize + def test_streaming_response_get_machine_usage(self, client: Dedalus) -> None: + with client.orgs.usage.with_streaming_response.get_machine_usage( + org_id="org_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = response.parse() + assert_matches_type(MachineUsage, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get_machine_usage(self, client: Dedalus) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `org_id` but received ''"): + client.orgs.usage.with_raw_response.get_machine_usage( + org_id="", + ) + + +class TestAsyncUsage: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: + usage = await async_client.orgs.usage.retrieve( + org_id="org_id", + ) + assert_matches_type(OrgUsage, usage, path=["response"]) + + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncDedalus) -> None: + usage = await async_client.orgs.usage.retrieve( + org_id="org_id", + period_start="period_start", + ) + assert_matches_type(OrgUsage, usage, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: + response = await async_client.orgs.usage.with_raw_response.retrieve( + org_id="org_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = await response.parse() + assert_matches_type(OrgUsage, usage, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: + async with async_client.orgs.usage.with_streaming_response.retrieve( + org_id="org_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = await response.parse() + assert_matches_type(OrgUsage, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncDedalus) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `org_id` but received ''"): + await async_client.orgs.usage.with_raw_response.retrieve( + org_id="", + ) + + @parametrize + async def test_method_get_machine_storage_usage(self, async_client: AsyncDedalus) -> None: + usage = await async_client.orgs.usage.get_machine_storage_usage( + org_id="org_id", + ) + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + @parametrize + async def test_method_get_machine_storage_usage_with_all_params(self, async_client: AsyncDedalus) -> None: + usage = await async_client.orgs.usage.get_machine_storage_usage( + org_id="org_id", + machine_id="machine_id", + period_end="period_end", + period_start="period_start", + ) + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + @parametrize + async def test_raw_response_get_machine_storage_usage(self, async_client: AsyncDedalus) -> None: + response = await async_client.orgs.usage.with_raw_response.get_machine_storage_usage( + org_id="org_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = await response.parse() + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + @parametrize + async def test_streaming_response_get_machine_storage_usage(self, async_client: AsyncDedalus) -> None: + async with async_client.orgs.usage.with_streaming_response.get_machine_storage_usage( + org_id="org_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = await response.parse() + assert_matches_type(MachineStorageUsage, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get_machine_storage_usage(self, async_client: AsyncDedalus) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `org_id` but received ''"): + await async_client.orgs.usage.with_raw_response.get_machine_storage_usage( + org_id="", + ) + + @parametrize + async def test_method_get_machine_usage(self, async_client: AsyncDedalus) -> None: + usage = await async_client.orgs.usage.get_machine_usage( + org_id="org_id", + ) + assert_matches_type(MachineUsage, usage, path=["response"]) + + @parametrize + async def test_method_get_machine_usage_with_all_params(self, async_client: AsyncDedalus) -> None: + usage = await async_client.orgs.usage.get_machine_usage( + org_id="org_id", + granularity="granularity", + machine_id="machine_id", + period_end="period_end", + period_start="period_start", + ) + assert_matches_type(MachineUsage, usage, path=["response"]) + + @parametrize + async def test_raw_response_get_machine_usage(self, async_client: AsyncDedalus) -> None: + response = await async_client.orgs.usage.with_raw_response.get_machine_usage( + org_id="org_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = await response.parse() + assert_matches_type(MachineUsage, usage, path=["response"]) + + @parametrize + async def test_streaming_response_get_machine_usage(self, async_client: AsyncDedalus) -> None: + async with async_client.orgs.usage.with_streaming_response.get_machine_usage( + org_id="org_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = await response.parse() + assert_matches_type(MachineUsage, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get_machine_usage(self, async_client: AsyncDedalus) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `org_id` but received ''"): + await async_client.orgs.usage.with_raw_response.get_machine_usage( + org_id="", + ) diff --git a/tests/api_resources/test_machines.py b/tests/api_resources/test_machines.py index 7b868f7..5e706dd 100644 --- a/tests/api_resources/test_machines.py +++ b/tests/api_resources/test_machines.py @@ -30,6 +30,16 @@ def test_method_create(self, client: Dedalus) -> None: ) assert_matches_type(Machine, machine, path=["response"]) + @parametrize + def test_method_create_with_all_params(self, client: Dedalus) -> None: + machine = client.machines.create( + memory_mib=0, + storage_gib=0, + vcpu=0, + autosleep="autosleep", + ) + assert_matches_type(Machine, machine, path=["response"]) + @parametrize def test_raw_response_create(self, client: Dedalus) -> None: response = client.machines.with_raw_response.create( @@ -61,14 +71,14 @@ def test_streaming_response_create(self, client: Dedalus) -> None: @parametrize def test_method_retrieve(self, client: Dedalus) -> None: machine = client.machines.retrieve( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: Dedalus) -> None: response = client.machines.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -79,7 +89,7 @@ def test_raw_response_retrieve(self, client: Dedalus) -> None: @parametrize def test_streaming_response_retrieve(self, client: Dedalus) -> None: with client.machines.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -99,16 +109,15 @@ def test_path_params_retrieve(self, client: Dedalus) -> None: @parametrize def test_method_update(self, client: Dedalus) -> None: machine = client.machines.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: Dedalus) -> None: machine = client.machines.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", + autosleep="autosleep", memory_mib=0, storage_gib=0, vcpu=0, @@ -118,8 +127,7 @@ def test_method_update_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_update(self, client: Dedalus) -> None: response = client.machines.with_raw_response.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -130,8 +138,7 @@ def test_raw_response_update(self, client: Dedalus) -> None: @parametrize def test_streaming_response_update(self, client: Dedalus) -> None: with client.machines.with_streaming_response.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -146,7 +153,6 @@ def test_path_params_update(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): client.machines.with_raw_response.update( machine_id="", - if_match="If-Match", ) @parametrize @@ -185,16 +191,14 @@ def test_streaming_response_list(self, client: Dedalus) -> None: @parametrize def test_method_delete(self, client: Dedalus) -> None: machine = client.machines.delete( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize def test_raw_response_delete(self, client: Dedalus) -> None: response = client.machines.with_raw_response.delete( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -205,8 +209,7 @@ def test_raw_response_delete(self, client: Dedalus) -> None: @parametrize def test_streaming_response_delete(self, client: Dedalus) -> None: with client.machines.with_streaming_response.delete( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -221,22 +224,19 @@ def test_path_params_delete(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): client.machines.with_raw_response.delete( machine_id="", - if_match="If-Match", ) @parametrize def test_method_sleep(self, client: Dedalus) -> None: machine = client.machines.sleep( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize def test_raw_response_sleep(self, client: Dedalus) -> None: response = client.machines.with_raw_response.sleep( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -247,8 +247,7 @@ def test_raw_response_sleep(self, client: Dedalus) -> None: @parametrize def test_streaming_response_sleep(self, client: Dedalus) -> None: with client.machines.with_streaming_response.sleep( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -263,22 +262,19 @@ def test_path_params_sleep(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): client.machines.with_raw_response.sleep( machine_id="", - if_match="If-Match", ) @parametrize def test_method_wake(self, client: Dedalus) -> None: machine = client.machines.wake( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize def test_raw_response_wake(self, client: Dedalus) -> None: response = client.machines.with_raw_response.wake( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -289,8 +285,7 @@ def test_raw_response_wake(self, client: Dedalus) -> None: @parametrize def test_streaming_response_wake(self, client: Dedalus) -> None: with client.machines.with_streaming_response.wake( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -305,20 +300,19 @@ def test_path_params_wake(self, client: Dedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): client.machines.with_raw_response.wake( machine_id="", - if_match="If-Match", ) @parametrize def test_method_watch(self, client: Dedalus) -> None: machine_stream = client.machines.watch( - machine_id="machine_id", + machine_id="dm-3", ) machine_stream.response.close() @parametrize def test_method_watch_with_all_params(self, client: Dedalus) -> None: machine_stream = client.machines.watch( - machine_id="machine_id", + machine_id="dm-3", last_event_id="Last-Event-ID", ) machine_stream.response.close() @@ -326,7 +320,7 @@ def test_method_watch_with_all_params(self, client: Dedalus) -> None: @parametrize def test_raw_response_watch(self, client: Dedalus) -> None: response = client.machines.with_raw_response.watch( - machine_id="machine_id", + machine_id="dm-3", ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -336,7 +330,7 @@ def test_raw_response_watch(self, client: Dedalus) -> None: @parametrize def test_streaming_response_watch(self, client: Dedalus) -> None: with client.machines.with_streaming_response.watch( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -368,6 +362,16 @@ async def test_method_create(self, async_client: AsyncDedalus) -> None: ) assert_matches_type(Machine, machine, path=["response"]) + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncDedalus) -> None: + machine = await async_client.machines.create( + memory_mib=0, + storage_gib=0, + vcpu=0, + autosleep="autosleep", + ) + assert_matches_type(Machine, machine, path=["response"]) + @parametrize async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.with_raw_response.create( @@ -399,14 +403,14 @@ async def test_streaming_response_create(self, async_client: AsyncDedalus) -> No @parametrize async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: machine = await async_client.machines.retrieve( - machine_id="machine_id", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.with_raw_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", ) assert response.is_closed is True @@ -417,7 +421,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: async with async_client.machines.with_streaming_response.retrieve( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -437,16 +441,15 @@ async def test_path_params_retrieve(self, async_client: AsyncDedalus) -> None: @parametrize async def test_method_update(self, async_client: AsyncDedalus) -> None: machine = await async_client.machines.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncDedalus) -> None: machine = await async_client.machines.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", + autosleep="autosleep", memory_mib=0, storage_gib=0, vcpu=0, @@ -456,8 +459,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncDedalus) - @parametrize async def test_raw_response_update(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.with_raw_response.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -468,8 +470,7 @@ async def test_raw_response_update(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_update(self, async_client: AsyncDedalus) -> None: async with async_client.machines.with_streaming_response.update( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -484,7 +485,6 @@ async def test_path_params_update(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): await async_client.machines.with_raw_response.update( machine_id="", - if_match="If-Match", ) @parametrize @@ -523,16 +523,14 @@ async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None @parametrize async def test_method_delete(self, async_client: AsyncDedalus) -> None: machine = await async_client.machines.delete( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.with_raw_response.delete( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -543,8 +541,7 @@ async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: async with async_client.machines.with_streaming_response.delete( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -559,22 +556,19 @@ async def test_path_params_delete(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): await async_client.machines.with_raw_response.delete( machine_id="", - if_match="If-Match", ) @parametrize async def test_method_sleep(self, async_client: AsyncDedalus) -> None: machine = await async_client.machines.sleep( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize async def test_raw_response_sleep(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.with_raw_response.sleep( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -585,8 +579,7 @@ async def test_raw_response_sleep(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_sleep(self, async_client: AsyncDedalus) -> None: async with async_client.machines.with_streaming_response.sleep( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -601,22 +594,19 @@ async def test_path_params_sleep(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): await async_client.machines.with_raw_response.sleep( machine_id="", - if_match="If-Match", ) @parametrize async def test_method_wake(self, async_client: AsyncDedalus) -> None: machine = await async_client.machines.wake( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert_matches_type(Machine, machine, path=["response"]) @parametrize async def test_raw_response_wake(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.with_raw_response.wake( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) assert response.is_closed is True @@ -627,8 +617,7 @@ async def test_raw_response_wake(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_wake(self, async_client: AsyncDedalus) -> None: async with async_client.machines.with_streaming_response.wake( - machine_id="machine_id", - if_match="If-Match", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -643,20 +632,19 @@ async def test_path_params_wake(self, async_client: AsyncDedalus) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): await async_client.machines.with_raw_response.wake( machine_id="", - if_match="If-Match", ) @parametrize async def test_method_watch(self, async_client: AsyncDedalus) -> None: machine_stream = await async_client.machines.watch( - machine_id="machine_id", + machine_id="dm-3", ) await machine_stream.response.aclose() @parametrize async def test_method_watch_with_all_params(self, async_client: AsyncDedalus) -> None: machine_stream = await async_client.machines.watch( - machine_id="machine_id", + machine_id="dm-3", last_event_id="Last-Event-ID", ) await machine_stream.response.aclose() @@ -664,7 +652,7 @@ async def test_method_watch_with_all_params(self, async_client: AsyncDedalus) -> @parametrize async def test_raw_response_watch(self, async_client: AsyncDedalus) -> None: response = await async_client.machines.with_raw_response.watch( - machine_id="machine_id", + machine_id="dm-3", ) assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -674,7 +662,7 @@ async def test_raw_response_watch(self, async_client: AsyncDedalus) -> None: @parametrize async def test_streaming_response_watch(self, async_client: AsyncDedalus) -> None: async with async_client.machines.with_streaming_response.watch( - machine_id="machine_id", + machine_id="dm-3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" From 0eb1d61c6017bdec31c07525fcd169eecd97f9df Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 19:08:52 +0000 Subject: [PATCH 10/11] ci: pin GitHub Actions to commit SHAs Pin all GitHub Actions referenced in generated workflows (both first-party `actions/*` and third-party) to immutable commit SHAs. Updating pinned actions is now a deliberate codegen-side bump rather than implicit on every workflow run. --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/publish-pypi.yml | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04cfb63..06b9186 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,10 +21,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/dedalus-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 with: version: '0.10.2' @@ -43,10 +43,10 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/dedalus-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 with: version: '0.10.2' @@ -61,7 +61,7 @@ jobs: github.repository == 'stainless-sdks/dedalus-python' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -81,10 +81,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/dedalus-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 with: version: '0.10.2' diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 7e1e57e..7155c9e 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -18,10 +18,10 @@ jobs: id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 with: version: '0.9.13' From b3059f24ac5a21854102aa9ad721a1cf1851a469 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 19:11:28 +0000 Subject: [PATCH 11/11] release: 0.3.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 22 ++++++++++++++++++++++ pyproject.toml | 2 +- src/dedalus_sdk/_version.py | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 10f3091..6b7b74c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.2.0" + ".": "0.3.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ebe111..09496f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.3.0 (2026-05-12) + +Full Changelog: [v0.2.0...v0.3.0](https://github.com/dedalus-labs/dedalus-python/compare/v0.2.0...v0.3.0) + +### Features + +* **api:** add orgs usage endpoints, autosleep to machines, remove if_match parameters ([3ecc5f7](https://github.com/dedalus-labs/dedalus-python/commit/3ecc5f71350a236eeb38b6ca1116146378ea7f20)) +* **internal/types:** support eagerly validating pydantic iterators ([d2686f3](https://github.com/dedalus-labs/dedalus-python/commit/d2686f3ea4d92a9b4c1ab211f62483dd2cdfc712)) +* support setting headers via env ([31654ea](https://github.com/dedalus-labs/dedalus-python/commit/31654ea7dba81fd19b0c334846eb4bf988035224)) + + +### Bug Fixes + +* **client:** add missing f-string prefix in file type error message ([aa1c869](https://github.com/dedalus-labs/dedalus-python/commit/aa1c869547ee96d99910ac50f0962c02812cf844)) +* use correct field name format for multipart file arrays ([09bc433](https://github.com/dedalus-labs/dedalus-python/commit/09bc4338396af1f0a28df189bd026ce052554532)) + + +### Chores + +* **internal:** reformat pyproject.toml ([6a4934a](https://github.com/dedalus-labs/dedalus-python/commit/6a4934a311b675e0b59dfe5e1d521e2d9405b62f)) +* remove custom code ([e296321](https://github.com/dedalus-labs/dedalus-python/commit/e2963215b941cf1f14c44215f4c5ba8427ea00d4)) + ## 0.2.0 (2026-04-22) Full Changelog: [v0.1.0...v0.2.0](https://github.com/dedalus-labs/dedalus-python/compare/v0.1.0...v0.2.0) diff --git a/pyproject.toml b/pyproject.toml index e0354e3..e76fef6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dedalus-sdk" -version = "0.2.0" +version = "0.3.0" description = "The official Python library for the Dedalus API" dynamic = ["readme"] license = "MIT" diff --git a/src/dedalus_sdk/_version.py b/src/dedalus_sdk/_version.py index bb150e3..5167202 100644 --- a/src/dedalus_sdk/_version.py +++ b/src/dedalus_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "dedalus_sdk" -__version__ = "0.2.0" # x-release-please-version +__version__ = "0.3.0" # x-release-please-version